Polar Defender & js13k

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.

Polar Defender

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
on mobile.

The tech

Some of the tech I used includes:

  • jsfxr for sound effects, based on Jack Rugile's blog post.
  • Liberal use of the native Canvas rotate() method.
  • 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
    window to w and Math to m reduces 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 1 for true and
    0 for 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
    on Wikipedia.

Further reading

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.