Fort Knight post-mortem #js13k

Play the 2023 entry here: https://js13kgames.com/entries/fort-knight

The post-mortem is usually a quick look through the gifs tweeted during the game jam, 30 days of steady progress for the engine and art plus some funny bugs; for my 2023 write up Id like to go into more detail and talk about some of the highs and lows and my overall approach to the jam.

Over the past four years, I’ve been on a journey of continuous improvement in my game jam entries. In 2022, I achieved a significant milestone by securing fourth place. However, my primary goal this time around was to enhance the quality of my entry and craft a game that offers an enjoyable experience.

Previous Entries

The idea

The theme in 2023 was 13th Century, I decided on day 2 that I would make a wave attack type game and the graphics would be isometric. Here is the original idea with coffee stains and all:

isometric island surrounded by sea, there are trees and a castles, a hero stands guard.

Approach

Over the previous years I have built up a template that I strip back to the bare bones, its handles all of the basics of a simple ‘engine’ to allow me to start directly on a game idea, in the first year a lot of time was taken up learning these basics with the Canvas API. The main JS files are loaded into a html file using some JS code:

<script type="application/javascript">
    version = Math.floor(Math.random() * 1000);
    var files = ["projectile","menu","audio","camera","particle","keys","entity","hero","enums","tile","utility","mob","level","cart","game","sound"];
    for (f of files) {
      document.write("<script type='application/javascript' src='assets/js/" + f + ".js?" + version + "'\><\/script>");
    }
 </script>

When ever I add a new file I add it to the array of files, my workflow is very simple, code, F5 and test, I use a python to run the game (“python3 -m http.server”) to avoid isues with cross origin:. There are probably better ways to do this but its a simple way to load the JS files and tag on a random id to stop the browser caching the code. I use the developer console to output messages and play with the code in real time. If I have settings I want to test like speed Ill edit them in console and have current values written to the screen.

The key exisiting files are roughly as follows:

  • game (Handles listeners, inputs and calling the game loop with a delta)
  • cart (Sets up the game screen, generates levels, calls render & logic functions)
  • enums (a list of tile and mob types)
  • entity (class to handle all objects, position, hitboxes, setting image coords based on type)
  • hero (extends entity with all the functions for the main character)
  • level (generate a random level or load from file)
  • keys (key number mappings)
  • camera (simple class to track camera position)
  • audio (http://sb.bitsnbites.eu contains the song)
  • utility (general purpose functions like collisions etc)

These classes are stripped right back to the bare bones but really need a complete rewrite, I lose bytes from badly written code, do not split up entities into new classes and end up dumping code all over the place, during the jam its fresh in my mind but after its hard to come back and make changes.

The entity rendering starts out as simple render code but ends up littered with magic numbers and polluted as I just want to get something working. I have always enjoyed adding features and testing without a plan but I really need to organise next year given my spare time is so limited.

Building Final Code

During the first jam I have a process to minify and uglify the javascript code into a single JS file using a grunt file I use npm to install the packages required. Once grunt has run, I copy the code into Road Roller which saves a lot of space.

My final zip files are generated using 7-zip on Windows, it contains a minified html file, the js and image file. This year I used a new sound library from Frank Force, grunt could not handle the javascript version used which caused me a pain, I’d build the single compressed javascript without this one class and have to tag the code on after. The whole process needs updating and streamlining as it was clunky and adding new libraries is going to cause more issues.

Images

I load all my images into a single file and use a simple process to keep this small, https://imageoptim.com/mac to remove meta data and then https://tinypng.com/ to further compress; I run the image through the app and website several times.

Getting Started

The template is a decent starting point, I have last years song as a placeholder which also acts as a reminder to save those bytes for the new song, and the ability to start rendering a map very quickly, the hero can move up, down, left and right but there are no collisions, objects etc just background tiles and a moveable character. What I would like to address next year is the start size of the template, a poor build process and separation of code.

To move onto the stages of development for the game! I started out rendering a random map of tiles I had created in Photoshop:

It was not until the 18th I had written a slighty random map generator and started playing with the sea, I wanted some wave like movement to add some life to the game from the start:
This affect uses some simple code which can be seen here, setting an offset to the Y position based on the time, tile column, a movement amount and speed, you can quite easily have small slow waves or huge fast ones.

I really got carried away with different ways to move the tiles around, including creating mountains; while this was not going to be used in game it did end up as a transition between levels:

I put some effort into learning how to rotate the map which is something I had tried and failed to do previously, this was partially working through out the jam but removed to save space later on. This is where my unplanned approach falls over! I work on what I think is fun and will contribute to a better game but lose sight of the bytes and required features to deliver a final product.

At this point I was not really sure on the game play but kept working on generating an island which would have a castle, trees and rocks, that would likely be enough to add some type of game later on. I was not decided on if you were defending, destroying or saving the castle.

I worked on a function to create pillars, from these pillars I could create a castle, due to all objects being Y sorted I had to exclude the pillar from the object array to ensure the render order was correct, this later became a pain when entities were in front or behind it! I decided to make its alpha below 1 when you colided to simplify this, here is castle and a slighly crazy for loop to allow the tile orderingto be top to bottom or reversed in one function.

Music

An old friend makes game music for a living, they have been kind enough to help with creating a song since the last jam, this helped with the 4th place last time around for sure! If I make the top 100 will be buying Adam a tee shirt again so we both have one.

Weapons

To add some feel to the hero I created hands, I experimented with them moving while walking, idle and holding weapons; they reminded me of Rayman so I added a punch! I never really got a weapon movement for the sword that I liked, the punch is fun, the axe and hammer are fine but the sword is not great. Players have fed back on the attacks and they could have been improved.

Was quite worrying to be over two weeks into the jam and only have this much completed, I started making todo lists and focusing more on completing the basics than adding nice touches to working code.

Here is the sword powering up, a click of the sword grants 1 damage, powered up its 10, I wanted a nice visual for this; I lost some time adding this arc due to some issues with how I scale the screen and render entities, there is simple way right now to render debug boxes etc, this needs a total rewrite for next year its a mess.

September 4th, 6 days to go until I had to submit due to a holiday; I finally added mobs, I decided to improve my usual mob code and try to have them space out around the hero, maybe I should have made the weapons over powered and had bigger mobs!

At this point I was working the normal 8 hour day, spending time with the family until 11pm and then coding until 3am. This was pretty stressful, plus I am training for a half marathon and running 30-40 miles a week (I did cut back on running a little). I had to become more focued on the todo list and started making decisions on what could and could not be completed:

What i have not covered is that HP was added to entities and Skeletons and Goblins were added and given movement code, to save time I used an asset pack purchased on itch, please check it out: https://danieldiggle.itch.io/sunnyside

the skeletons chase you down and hurt you by making contact, the Goblins will hunt you down but try to stay a given number of pixels away from you, they periodically throw spears, these were going to be arrows but due to their size and the animation being simpler they are spears!

There has been feedback on the combat and mobs, people are a little confused on how to fight and commented on weapon changing, I should have created imporved and clearer tutorials. The game is quite simple, you destory rocks and trees to stop mobs spawning, and then clear the mobs to drop. abridge to. thenext level but this was still not clear enough. I should have allowed the mouse wheel to change weapons and also allowed the shield to toggle on/off. Skipping play testing really hurt me!

The final Stretch!

It is quite amazing to look back at the 9th September and see how much I had left to implement and realise I did manage to submit on the 10th. Huge compromises were made, no boss, no shield cool down, upgrades are random on breaking drops and so on. The mobs were not even doing damage at this point.

To show that defence has increased a skull helmet is added to our hero, the powerups really needed a larger pop up text so players understood what just happened and why.

You can check out the commits to the game here, I made an effort this year to commit small incremental changes so I could roll back any game breaking changes quickly. If I have had the final 3 days seeing what I managed on the 10th alone I could have improved combat and tutorials which may have dealt with many of the comments / issues.

Feedback

  • Gameplay is a little not obvious
  • When introducing each item it wasn’t clear that the text was the hotkey to use it and not the number of times I needed to use it. Having the number hotkey under the item’s icon would have help
  • I forgot shield key by the time I needed it, could use a reminder in the text what it was
  • It wasn’t exactly clear what was needed to clear each stage. I was stuck on stage 3 killing enemies and bridge never came. Took me awhile to think about destroying the tree to move on
  • I kept dying in stage 4 to constant knockback and getting pushed off the edge of the map
  • I couldn’t attack enemies from above / below, which lead to the previous problem of getting constant knockback from the skeletons when they were below me
  • Trying to hold the shield button while simultaneously trying to attack was very tiring. Would have liked a toggle for the shield or something
  • Got stuck on about level 4, with seemingly infinite baddies spawning
  • I just can’t get past the goblins no matter what I do. Blocking only gets me so far, and they just freaking keep coming, getting me stuck in the water, or other things. I never got past Stage 4

All of these are fair comments, people were kind also but I get their frustrations, I didnt test, balance and deal with teaching people how to play. Some comments mentioned not enough variation in levels, I may look at using code to generate the images next time to allow more variation.

Conclusion

While there are many improvements that need to be made next time around:

  • New template
  • Automated build process
  • Better screen resizing
  • Improved menus
  • Better rendering with debug options
  • Play testing
  • Tutorials
  • Mobile friendly

To name the key areas; there are plenty of positives I take from the jam, I completed a game in 30 days with limited time, added loads of features and within the 13kb limit plus I engaged with the community and gave some advice to others and had fun!

Leave a comment