Over the last month I've been working on a game for the #js13k game competition.
The concept is fairly simple: make a game in under 13 kilobytes with no external
dependencies. The idea is to see what people can come up with on a budget, and
it's awesome to see some of the entries this year.
My game, Polar Defender, is a basic shoot 'em up on a polar coordinate system. It's
heavily inspired by space invaders, except you have to defend various planets from
all sides at once. It's heavily reliant particles and a basic polar trajectory
system to provide messy, explodey space fun.
The theme of "elements: earth, air, fire, water" is optional in the contest,
but I incorporated it into my level system (an earth-like planet, water planet
fire and gas planet). It's a /little/ contrived, but I think it works well in
terms of playability.
I wanted to include a playable level system with a playful narrative since there's
only so much you can do in 13 kb and I felt it would make it a more personal
experience. I feel it worked out well, with six levels (including an initial training
level) on various planets and varying degrees of difficulty. After early feedback
stating it's too hard to finish in one go, I adjusted the menus to make each level
unlockable rather than having to start over, which really improves the gameplay
in a casual sense.
Touch input is significantly more difficult than desktop input because I
essentially shoehorned the same concept in where it doesn't really fit. If I had
the chance to do it again I would introduce a separate tap-based firing system
Some of the tech I used includes:
- jsfxr for sound effects, based on Jack Rugile's blog post.
- Liberal use of the native Canvas
- Regular CSS & JS for the menu system.
- Gulp, Uglify, svgo and a bunch of hand-tweaks to package and minify my codebase.
- Super rudimentary box-based collision detection.
- A basic entity/component model through which to extend base sprites.
- SVG for infinitely customisable graphics. (There's only four enemy sprites in
the game, each recoloured and resized as needed.)
- Procedurally generated starfield & planets.
How to ultra-compress your JS
13 kilobytes is quite a lot in terms of raw code, but also a challenge to
meet when including graphics, sound, polyfills and other boilerplate.
Minification of Polar Defender was done by hand and involved a lot of code tweaks.
The ultimate deliverable needed to be compressed into 13 kilobytes of zip file,
which is roughly comparable to a gzipped distribution from a web server.
Some of the things I did which aren't necessarily best practices include:
- Strip unnecessary properties and pre-compile SVG files into a JSON file to be
bundled into the main JS build process. This improves compression because there's
less junk and the SVG gets compressed in with the JS which presumably improves
duplicate string elimination in the zip format.
- Collapse JSON structures into CSV-like strings that can be reinflated later.
JSON objects are super-wasteful in terms of repeated properties, and while
compression algorithms are generally pretty good with repeated content, it's
still better to remove the duplicates where possible.
- Globalise commonly used functions. This isn't something I'd usually recommend
but considering the constraints what the hey. Things like aliasing
mreduces byte-level repetition. Additionally keeping
everything in a local scope lets Uglify optimise away long function names.
- Loose comparison and other sneaky tricks. For instance using
1for true and
0for false saves 3 bytes per bool and works in a loose JS equality
operation if you're prepared to ignore JSHint complaining a lot.
- Reuse everything. I reused a basic set of drawing functions and sprite classes
for everything in-game, meaning each new feature was an iteration on an
existing one rather than a completely new piece of functionality. See also
entity component system
In addition to my jS13k entry, I've got a side-build available in the
Chrome Web Store
which you can install and carry around with you. The main benefit is that your
scores are stored in the cloud and unlocked content goes wherever you do.
Overall I think it worked quite well and I'm happy with the result. There's some
awesome games submitted so far and I can't wait to see how everyone goes.
The source code to Polar Defender can be found on GitHub.