Back to blog

Elemental Entropy - My JS1k 2016 Entry

Time Worm! Screenshot

If you've previously visited my blog, you might be aware that I entered last year's js13kGames contest. Since then, I've been exploring games and application development with HTML5 canvas, so I entered this year's JS1k contest. The aim is along the same lines as js13kGames, except that technical demos are also accepted, and that submissions can not exceed 1024 bytes. And I remember complaining that 13 KB was small!

Given the theme this year is "EleMental" (yep, with that casing too!), I wrote a 2D canvas game called Elemental Entropy, in which the player rotates a shield around an oxygen particle to protect it from heat and fuel particles (because science is that fundamental, right?!). I also managed to squeeze in some very basic audio thanks to the Web Audio API's OscillatorNode interface.

The Process

Here's the final code that I submitted. It's 950 bytes in size:



Oh I see... so how does... what? Ridiculous right? This is the output of an amazing tool called RegPack, which removes duplicate tokens and ultimately builds a regular expression against which one's crushed code can be recompiled to executable JavaScript. Doing this alone, however, didn't permit me to get the game down to 950 bytes; this was just the final step. So how did I achieve this?

Let's take a look at the code in project's GitHub repository. In total there are four scripts:

index.original.js

This is the initial source code that I wrote to represent the game. Given the small target size, I'm not doing anything vectorial or converting pixel space to world space, but I have written small, manageable methods for handling particle generation, collision, and sound. Ironically, this code ended up being cleaner, in my opinion, than my js1kGames entry; look at that Particle constructor function!

So how big is this script? 6.98 KB. Oh dear. What next?

index.pre-min.js

Turns out that by throwing software engineering best practices out the window, I was able to half the game's size. All of the functions have been replaced with a giant game loop function, the Particle prototype was ruled out in favour of object literals, and constants have been ditched for magic values. This, for the most part, entailed my finding and replacing functions and constants in my text editor manually.

index.pre-crush.js

This is the pre-min script passed to Google's Closure Compiler. I was originally using UglifyJS, but the mangling options were not flexible enough for my needs. I'm using Closure's advanced optimisations and referencing an externs script to mark the JS1k shim globals as reserved tokens. I then manually remove all instances of the var keyword, effectively placing everything on the global object since the script doesn't run in strict mode.

Now we're down to 1.54 KB. Just another 553 bytes to go...

index.crushed.js

This is the pre-crushed script processed with RegPack, using the online UI with these options:

This results in the 950-byte script that I shared above.

Observations

I enjoyed writing this game, but reducing its size by 6 KB was insane and took a great deal of optimisation. Additionally, this project has made me realise that my maths is pretty poor; I had to spend an hour or two on BBC GCSE Bitesize to remind myself of how geometry works. To resolve this, I've bought Mathematics and Physics for Programmers by Danny Kodicek and John Flynt; the book starts with the very basics, before progressing into algebra, geometry, calculus, and then more advanced concepts. I'm therefore going to implement the provided pseudo-code in JavaScript and ultimately use it in my games. I'm also going to learn how to map world space to pixel space properly!

Tips

I'm now going to take a couple of months off from extra-curricular development before my brain sets on fire. Then I'm going to start working on developing games properly.