Blade Gunner: js13kGames 2016 post mortem

This was my first time participating in the JS13KGAMES challenge, a month long competition running from August 13th to September 13th about creating a HTML5 game that fits within 13 kilobytes when zipped (a game jam mixed with a code golfing contest).

I made Blade Gunner, an 8bit “demake” of 1982 sci-fi movie Blade Runner. (official JS13KGAMES entry at http://js13kgames.com/entries/blade-gunner and its still evolving alter ego on my website http://herebefrogs.com/bladegunner/).

A sure way to tell a glitchy android apart is its red eyes… oh, and his gun!

In this game, androids are hiding among bystanders. As a Blade Gunner, your goal is to “retire” them while limiting bystander casualties: if you get too close or if they randomly glitch, they will go on a shooting spree. Each time you successfully retire all androids, you start the next level with one more in hiding.

Game ideation

This year, JS13KGAMES’s theme was Glitch. Visual glitch was obvious, but I didn’t feel confident enough to come up with something impressive. Glitch as in bugs was bound to happen on its own and not be a great experience, so I had to find something else. That left me with glitch as a game mechanic (can that even be considered a glitch anymore if it’s intentional?) and glitch as a narrative element. It took me 2 weeks to imagine a factory manager trying to prevent glitchy robots from damaging other robots on a production line, which for some reason reminded me of the chase scene in 1982 sci-fi cult movie Blade Runner: Deckard tries to get close to a fleeing replicant in a packed street before he discharges his gun to avoid bystanders getting hit. It seemed a balanced gameplay that the player would have to act fast to limit casualties inflicted by glitchy androids, while not acting carelessly either to avoid causing more damage in doing so.

With 2.5 weeks left before contest end, I set myself the goal to create a one-screen, android-hunting game from scratch. It’s only when I got most of the core mechanics working that I gave some thoughts to replayability. I’m not a super fan of “infinite runner” type games as they tend to feel quite repetitive to the least competitive players, but I felt adding one more android to neutralize after each completed level was still the simplest option for a first game attempt. I will strive to create a better curated experience next year.

Art direction

I had practiced my pixelart skills for about a year by participating to the Pixel Daily challenge on Twitter (https://twitter.com/Pixel_Dailies) and JS13KGAMES felt the perfect validation of my training. I had to rapidly produce a good looking tileset with a low footprint in a short amount of time. I liked the appeal of small sprites such as the ones from Super Mario or The Legend Of Zelda and I didn’t want to waste time obsessing over color choices for hours (pixelart truth: the hard part ain’t so much placing the pixels as picking the right colors to create light and shadows). So I adopted the Pico8 virtual console’s constraints: its color palette is limited to 16 choices that work well with each other and its sprites are 8 x 8 pixels (I used 9 x 9 to give myself a bit more artistic freedom).

Each line: walk cycle (2 frames), shoot cycle (2 frames) and death sprite

Such a small canvas calls for a minimalist style where character features are simplified to the extreme, and therefore relatively quick to draw. For the same reason, all my animations are only composed of 2 frames.

As for sound, I’m no good at composing melodies for background musics but I was very keen having sound effects, especially to reinforce the consequences of player actions: when “retiring” a bystander by mistake, the death sprite is accompanied by an unpleasant sound, while “retiring” a glitchy android earns the player a cheerful and energetic sound.

Technical choices

As time was running short, I didn’t invest in learning a gaming micro framework on top of inventing a brand new game. Instead I relied on vanilla JavaScript, which is a great way to learn the fundamentals.

I used a fairly typical game loop and rendered the game state off-screen on a 198 x 153 pixel canvas (with 9 x 9 sprites, that’s a 22 x 17 square grid). Then I rendered this image on a on-screen canvas that had been scaled to fit the browser window while preserving the off-screen canvas’ aspect ratio. This way, my pixelart was scaled up 2 to 4 times depending on the browser window dimensions, but not distorted. I had to turn off smoothing to preserve the sprites’s crisp edges, which I attempted to do at first with CSS property “image-rendering: pixelated” but only Chrome honors that value, so I ended up doing it programmatically by setting “imageSmootingEnabled = false” on my on-screen canvas 2D context (which has to be set every time the on-screen canvas is resized to fit the new browser window dimensions).

I used 42 global variables and 35 functions, which is a simple but not very maintainable way to structure code. Before optimizations, Blade Gunner is composed of:
- 187 bytes of HTML markup,
- 718 bytes of tilesheet in PNG format,
- 23,422 bytes of JavaScript game code (including 983 byte of base64 encoded tilesheet)
- 2517 bytes of minified JavaScript for JSFXR, an audio synthesizer library
I used UglifyJS to minify my JavaScript code and a Gulp pipeline to inline it in the HTML page. After these basic optimizations, Blade Gunner was composed of a single HTML file of 16,953 bytes that compressed down to a 6,402 bytes Zip, leaving 52% of the 13kb limit free for more features.

But the only thing that I ran short of was time, never space: I’ve spent all my free time after work and before bedtime (or about 2.5~3h per day) for 14 consecutive days, which adds up to roughly 40h of development time.

Lessons learned

#1 — Project Manage the heck out of the feature list

With 14 days left before contest close, I knew I had to ace Blade Gunner’s execution and could not afford to loose time going down dead ends. I made an exhaustive list of features, each simply described (e.g. hero can move, android can shoot…). Then I split the features into 3 groups:

  1. what was absolutely necessary to have the most basic yet playable game
  2. what was needed to spice up the game a bit more
  3. what would be nice to have if everything else was done

Finally, I ordered features within each group based on their dependencies (e.g. hero must be able to shoot before android can die). During the course of development, I revised these lists several times, marking completed features and swapping some between groups based on my progress and learnings.

The first group was of utmost importance because if everything else failed and I ran out of time, at least I had a playable game (albeit very bare) that I could submit. From this foundation, I knocked down all features from my second group, progressively enhancing Blade Gunner. The third group became synonymous of non-essential game mechanics that I’d like to explore when the contest is over.

#2 — Keep it fun to make

I’ve heard too many stories of game developers starting by things like a 3D rendering engine; all their time get sucked into that and 6 months down the road they still don’t have anything playable. I had a strong resolve to take the opposite approach of focusing only on gameplay features using the most basic graphic placeholders (like simple colored shapes), with the rationale that if the game mechanics were good, the game will be fun to play even with no graphics.

On day #1 I followed through on my plan and this is what Blade Gunner looked like:

Green for our hero, red for glitchy androids and blue for bystanders. Compelling, eh?

Right there, I realized that even if by some miracle the game was ever fun to play this way, it wouldn’t be very fun for me to make. When things would go wrong and I’d be tempted to give up, I would need to have something to remind me why I cared to create this game and why it’ll worth for me to finish it. It sure ain’t gonna be colored cubes. So I came up to a compromise between my 2 opposite views of game development and settled for something in the middle.

On day #2 I worked on sprites and animations for the 2 main protagonists:

Hero and glitchy android animations made in PyxelEdit.

On day #3 I replaced the placeholders with final art, but using only the 1st sprite of the walk animation:

Now I can relate to the game I’m making

They glided rigidly over the screen, but that was enough to convey the spirit of my game. Then came the bullets and the “game over” screen. I didn’t start implementing sprite animations until I was able play and win Blade Gunner (which was easy because glitchy androids weren’t firing back yet ;p). It definitely looked better once all the characters started moving convincingly, but no placeholder could ever have elicited the excitement of having even the simplest of sprites moving here and there, going by their Blade Gunnery business.

#3 — Design systemic rules that govern the game

I had just finished reading Spelunky, an awesome game development book published by Boss Fight Books (https://bossfightbooks.com/collections/books/products/spelunky-by-derek-yu) and written by Derek Yu, the game creator himself. In his account of how Spelunky came to be, Derek explained his love for game systems where a few rules consistently govern and apply to all entities of the game. Initially, I had listed moving the hero, the androids and the bystanders 3 separate items, shooting was 2 (hero, androids) and dying was 2 as well (androids, bystanders). Keeping Derek’s principles in mind, I quickly realized that hero, androids and bystanders were the same entity with different sprites tacked on and some abilities enabled or disabled (bystanders can’t shoot, and initially I didn’t even consider the hero could die), which saved me a lot of development time over many entity specific rules.

During play testing, a friend suggested it would be cool if a bullet could stop another bullet. I realized I had treated bullets differently instead of subjecting them to the same collision test other characters underwent to check if they were hit. This simple change gave Blade Gunner a bit more depth, as bystanders could now be saved by shooting down the androids bullets.

Another nice benefit of systemic rules is that they allowed unexpected (but logical) behaviors to emerge. As soon as I permitted androids to fire, it became apparent that during their random shooting spree a glitchy android could take another one down. It would have never crossed my mind to code that situation specifically, yet systemic rules made it happen.

#4 — Loading assets

When it came to loading my tileset into an Image object so I could render the character sprites onto the HTML canvas, I had 2 options: a URL to the tileset’s PNG file or a data URL (a string of ASCII characters representing the PNG’s binary data encoded in base64)

// option #1 file URL
var i = new Image();
i.addEventListener('load', function() { // image can be drawn });
i.src = 'assets.png';
// option #2 data URL
var i = new Image();
i.src = 'data:image/png;base64,iVBORw0KGgoAAAANS...RU5ErkJggg==');
// image can be drawn

It’s fairly easy to find code examples or tools that convert your PNG file into a base64 encoded string. However, this data URL is usually double the size of your original image. In a code golfing competition like JS13KGAMES where every byte counts, why would I pick that option?

Well, speed. From what I read, the appeal of data URL lies in the facts that #1 browsers don’t have to make a separate HTTP request to download the image since the data URL is already embedded into my HTML page and #2 the Image object is available for drawing as soon as its src attribute is set to the data URL.

Turns out Chrome is the only browser where #2 is true. In Firefox, Safari and IE/Edge, I had to wait for the image to fire a “load” event, like I normally would when using a file URL, before I could safely render it on my HTML canvas. Still, this wait is negligible compared to the network roundtrip necessary to fetch an external asset file. Since I was well below the 13kb limit, I decided to optimize my game for load time over size, and used this version:

// safest way to load data URLs on all browsers
var i = new Image();
i.addEventListener('load', function() { // image can be drawn });
i.src = 'data:image/png;base64,iVBORw0KGgoAAAANS...RU5ErkJggg==');

#5 — Stoping the game loop

Some examples of game loop I came across looked like this:

// what I read online
function loop() {
requestAnimationFrame(loop); // repeat ASAP once this loop ends
render(); // the game state
update(); // the game state
}

It seemed counter-intuitive to start the game loop by requesting another game loop be queued while I hadn’t even updated or rendered my game state, so I moved the call to requestAnimationFrame() at the end of the loop.

// what I tried instead
var requestId;
function loop() {
update(); // the game state
render(); // the game state
requestId = requestAnimationFrame(loop);
}
function update() {
...
if (gameOver) {
cancelAnimationFrame(requestId);
}
}

However it became clear why that was a mistake once I tried stop the game loop when the game was over: I saved the request ID returned by requestAnimationFrame() into a global variable and passed it to cancelAnimationFrame(), which prevents a queued up animation frame request from executing next. That didn’t work: since requestAnimationFrame() happened last in my game loop, the next time update() ran requestId was in fact set to the animation frame request in which update() was currently executing and therefore couldn’t be dequeued.

The proper way to structure the game loop is indeed to queue up the next game loop, then render the game state and finally if the game is over, to dequeue that game loop request, making the current animation frame effectively the last one to run:

// what I read online was correct but not the complete picture
function loop() {
var requestId = requestAnimationFrame(loop);
render(); // the game state
update(requestId); // the game state
}
function update(requestId) {
...
if (gameOver) {
cancelAnimationFrame(requestId);
}
}

#6 — Golfing HTML

This is what my HTML page looked like:

<style> body { margin: 0; background: #121212; ... } </style>
<canvas></canvas>
<script>
document.title = "Blade Gunner";
...
</script>

Turns out this is all the markup you need! Modern browsers will generate the missing <html>, <head> and <body> tags for you, move the <style> tag under <head> and wrap the rest under<body>. As for the page title that you normally express with a <title> tag under <head>, document.title allows you to set it programmatically.

What I will do differently

#1 — Clearly explain the game goals

I assumed everyone had seen Blade Runner before and remembered that Blade Runner cops took great care never to retire a human by mistake, a significant risk in their position. Therefore I thought it would be obvious that stealth was the way to play. In the final game, I intentionally didn’t use a single sprite variation for all androids as it would have made them easy targets (like I did during development for the exact same reason that it made debugging easier for me). Instead I used the same sprites as bystanders, hiding the androids among them, like in the movie.

I knew this would be a problem when I designed the startup screen, for I couldn’t express it in a concise sentence that would fit the screen. The two sprites on the right were my attempt to warn the player that glitchy androids had red eyes and their gun drawn out. As expected, early play tests revealed that although some players got it, others wiped out the entire bystander population and didn’t understand what they had done wrong to deserve a “game over” screen.

A potential gameplay tweak could have been to use a unique sprite for all androids, but only make them glitch when the player got too close. That would have preserved the tension between hazarding a shot from far aside with increased risk of hitting a bystander, or getting up close for a clean shot with the risk of triggering a shooting spree. This would have been easier to describe clearly while preserving the interest of the game.

#2 — Pixelart font

One thing I really wanted was a pixel font for the startup screen and other in-game texts to match the 8bit pixelart style. I assumed it would require producing a pixelart alphabet and a function to look up every characters in my texts and draw the corresponding glyph on screen.

When time ran short, I cut that feature down as it didn’t bring anything to the game play, and settled for monospace font ‘Courier’. Yet I wasn’t really satisfied by the lack of great fallback fonts available on all OSes so next time I will make sure to get that done early on during the development.

#3 — Scoring

Similarly, I didn’t think hard enough to find a way to combine the number of androids retired and the number of bystander casualties into a single meaningful score that could clearly convey to players how poorly or well they did, and appeal to their competitive side to increase the game’s replay value.

I saw plenty of JS13KGAMES entries this year that successfully did that, and offered a simple way to tease other players on Twitter with their high score, driving the game viral factor up.

#4 — Collision detection

In my original vision, the player had to shove its way through the crowd to get to the android, just like Deckard did in Blade Runner went he chased a replicant down a packed street.

I knew collision detection and resolution would be something quite complex to develop in order for it to feel just right (the hero had to stay on course while being slowed down, and bystanders forcefully moved aside their trajectory). I kept pushing it down the list and trading it for easier “wins” that took less time to develop. I’m OK with this decision, since the game benefited more from all these smaller improvements, but I will make sure I don’t keep collision for the last day on my next JS13KGAMES attempt because it sure would have made a nice difference if it had been part of the game.

#5 — Mobile support

This one is geared toward increasing chances to win a JS13KGAMES prize. For simplicity’s sake I only implemented keyboard control in Blade Gunner. I gave touch control a quick thought (dragging to move the hero, tapping to aim and shoot) but didn’t budget any time to work on it as I suspected it would require a lot more effort for it to feel good (dragging the hero means the thumb is probably obscuring its sprite and therefore doesn’t allow for precise motion).

Yet when I look at historical game entries from the past five JS13KGAMES contests, Desktop is the most crowed category (~120 submissions on average) compared to Mobile (~40) and Server (~10). Server implies a lot more work, but I believe adding Mobile support is a low-hanging fruit if the game mechanics translate easily for touch control, thus increasing my chances to get noticed by the judges by entering my game into a less crowded category.

In conclusion

My goal in participating to JS13KGAMES was to create a game from start to finish. The funny thing is: give me an arbitrary deadline and I will make the time to create this game I can’t find the time to make if I had set the deadline myself.

I’m happy to say I didn’t hit any major roadblock and development went relatively smoothly. I was happily surprised by how little code was necessary to make bystanders move around or to control the hero. It was exhilarating to see the gameplay getting closer to my original vision with every new line of Javascript.

If you’ve been looking for an excuse or a motivator to get started on this game idea of yours, JS13KGAMES is a perfect opportunity: it’s a lot of fun to participate in and a great place to learn from others (there are hundreds of tricks to discover by skimming the code of past entries). The 13kb limitation will force first timers to imagine a short game rather than an unreasonably big one, and challenge the seasoned game developers to cram in all the content and levels they dreamed of in their contest submission.