Last weekend I submitted my entry for the JS13K game development competition. The goal of the competition was to write a game in Javascript that fills maximum 13 KB when zipped. The theme this year was “Reversed” so I decided to write a classic space shooter – but running in reverse.
You can try the official version here Galactic Backfire
In this blog post I will write a little about how the game was made and what went right and wrong.
Development Setup
I used the following tools:
- Atom for editing
- Gulp for building
- Babel for transpiling ES6 to ES5
- BrowserSync for automatically reloading the browser when the source changes
- Uglify for minifying the code
- JSFXR for generating sound
- Local Git repository for version control
- Firefox and Chrome for testing
- iPad Air and a Nexus 5 for last minute testing of touch controls
First Playable Prototype
I started by writing a simple prototype of the core game mechanic. It took me a while to find a good way to make the bullets start at the edge of the screen and end up at the player position. I used simple shapes like rectangles, triangles and circles to keep focus on the gameplay. I posted it on the HTML5 Game Devs Forum and got some positive feedback. When I was sure the idea would work and be fun, it was just a matter of refining it until I ran out of time.
Procedural Space Ship Generator
Every time the game is loaded it generates a new random set of 50 spaceship. Here are some examples
The algorithm is simply based on a series of random walks:
- Walk to the right while randomly distorting the Y coordinate.
- Walk up and to the left while randomly distorting both coordinates.
- Walk in a straigt line to the tip of the space ship
- Mirror the shape
- Fill it
- Paint a slightly distorted black half-circle on top of the ship
Cross Browser Issues
On the last friday a colleague tested the game on a Mac. It worked fine in Chrome but just gave a blank screen in Safari. When I got home I did not have access to a Mac which made hard to guess why the game would just show a black screen on Safari. This should teach me to test across platforms earlier in the process next time.
Luckily I found the online service MacInTheCloud where you can get remote access to a Mac. The connection was not fast enough to play the game smoothly, but it was good enough for testing. It turned out two things were wrong:
The first problem was that I used the user timing API performance.now() for timing which is not supported by Safari. I worked around this by passing the timestamp from requestAnimationFrame around instead. In a way the code ended up cleaner this way.
When Babel transpiles for..of loops to ES5 it uses Symbol which is not supported by Safari. Babel does provide a polyfill for these purposes, but it was simply too big to fit in a 13kb game. So I rewrote the for..of loops to use the forEach() method on Array and Set instead.
Last Minute Touch Control
On the last day I had available I got curious about how the game would run on iPad and my Nexus 5 phone. In retrospect this was a bad idea. The time would have been better spent on fine-tuning the game and adding extra power-ups and maybe even bosses.
First of all you have to deal with the difference between keyboard control and touch control. I tried to quickly hack together a virtual joystick, but I did not get it completely right. On top of this there is the matter of screen sizes and lack of a cross browser support for running full screen.
Performance, on the other hand, did not seem to be a problem. The animation runs smoothly on both the iPad and the Nexus.
The 13kb Size Constraint
I did not worry much about the size constraints while writing the game. I simply decided to procedurally generate the graphics, use JSFXR for sound and use standard fonts. I ran out of time before I ran out of space.
Some stats:
- Transpiled to ES5 the Javascript takes up 84kb including the jsfxr sound library
- After running it through the Uglify minifier it is down at 51kb
- After zipping the JS + HTML the total size is 12kb (12050 bytes)
Submitting Late Friday Night
The official deadline for submitting an entry was sunday the 13th, but since I was going on a small trip with my wife in the weekend to celebrate our 8 years together, I had to finish the game friday night. I submitted the game at 2:00 in the night. When I woke up the next morning I did a big play-through and discovered a couple of small bugs. Luckily the organizer accepted a patch for my entry.
I had a great weekend with my wife and since the competition spanned a month, it didn’t matter much to finish a couple of days early.
Conclusion
It was great fun to participate in the competition. I am impressed by the overall quality of entries and the many creative interpretations of the theme.
I hope I will have the time to participate again next year 🙂