Snakes Technical Details

Tue, Sep 27, 2011

Last week I finally decided my Snakes game was just about as finished as it was going to get and pushed it live.

Before moving on to something else, I wanted to write up a brief technical overview of how the game is implemented.

I have already written about how to implement the raw mechanics of snakes. It is a fairly simple game and there is no need to revisit that again. Instead, this post is about some of the trimmings that go around the core to polish the game into a finished state.

Development Tools

Snakes is a pure HTML5 game using plain vanilla HTML, Javascript and CSS. There is no server component. So the majority of development is simply editing files and viewing them in a browser.

Best practice is to maintain individual source files for development and then unify (and minify) them for performance reasons, to serve up a single javascript and a single css file at run time.

Using Ruby and Rake, I have a simple UnifiedAssets library that will take my individual .js and .css files and combine them into a single unified/minified run-time file:

UnifiedAssets::Task.new do |t|
  t.minify = true
  t.assets = {
    "snakes.js"  => [
      'js/game/vendor/stats.js',
      'js/game/vendor/sizzle.js',
      'js/game/vendor/animator.js',
      'js/game/vendor/audio-fx.js',
      'js/game/vendor/state-machine.js',
      'js/game/base.js',
      'js/game/game.js',
      'js/game/dom.js',
      'js/game/menu.js',
      'js/game/key.js',
      'js/game/math.js',
      'js/game/vector.js',
      'js/snakes.js'
    ],
    "snakes.css" => [
      'css/vendor/normalize.css',
      'css/snakes.css'
    ]
  }
end
$ rake assets:create

However, running this from the command line for every change would be frustrating, so the UnifiedAssets library also includes a tiny little rack server that can be used to serve up the game whilst automatically regenerating the unified files if it detects that the underlying source has been modified.

$ rake assets:server
(in /home/jake/github/javascript-snakes)                           
>> Thin web server (v1.2.11 codename Bat-Shit Crazy)               
>> Maximum connections set to 1024                                 
>> Listening on 0.0.0.0:3000, CTRL+C to stop
...

So now you can point your browser at localhost:3000, edit the source files in your favorite editor, hit refresh in your browser and see the changes immediately.

If I was starting over today, I would most likely use the new version of the Sprockets library that performs this same function in a more robust manner (its a core part of Rails 3.1)

3rd Party Code

The Snakes game goes beyond simple <canvas> usage and includes a DOM based menu system. The easiest way to do DOM manipulation today is with a library such as jQuery, and for full blown web applications I would have no hesitation to go down that path.

However, this game has very simple requirements and I would most likely end up using only a tiny fraction of the available functionality

For something like this I really like the idea of small, specific, microjs libraries that…

So for Snakes, I pulled together a handful of micro libraries that fit that description

FULL DISCLOSURE: those last 2 are my own libraries

Where I didn’t find a simple library that was a good fit, I built the minimal functionality I needed into the game itself.

Base Game Library

The base game library consists of the generic code that is not Snakes specific, and might be reused in other games. This is code that started off life as the base for a Pong game, evolved through Breakout and Snakes and I’m sure will evolve further when I make future HTML5 games.

It is broken down into individual source modules:

NOTE: at this point, the code is still evolving as it is copied from game to game and there is no single ‘game library’ that is shared across games. At some point I hope that will change when this code matures into a stable re-usable game library.

Snakes Game Code

Pushing the generic code down into a base game library allows the Snakes-specific code to stay tidy, and fit into a single js\snakes.js file! We can use the javascript module pattern to create a closure over some private implementation details and return a new game() at the very end.

Snakes = function() {

  var cfg = {
    // a bunch of declarative configuration
  };

  var game   = Class.create({ ... }); // define the core game class - also an FSM
  var score  = Class.create({ ... }); // define a score helper class
  var court  = Class.create({ ... }); // define a court helper class
  var fruit  = Class.create({ ... }); // define a fruit helper class
  var snake  = Class.create({ ... }); // define a snake helper class
  var render = Class.create({ ... }); // define a rendering helper class

  return new game(); // construct final game instance

};

Summary

That was a brief, whirlwind tour of the Snakes game structure. Don’t forget to:

If anyone wants a more depth about one particular piece let me know and I’ll try to add a little color. Otherwise I’m going to say goodbye to Snakes and move on to something new…