Snakes Technical Details
Tue, Sep 27, 2011Last week I finally decided my Snakes game was just about as finished as it was going to get and pushed it live.
- play the game now
- view the source code
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
- and that feels like overkill.
For something like this I really like the idea of small, specific, microjs libraries that…
- do one job
- do it well
- are small
- are independent
- are easy to use
So for Snakes, I pulled together a handful of micro libraries that fit that description
- sizzle.js - a CSS selector engine
- animator.js - an animation timer for fade/slide effects
- stats.js - an FPS counter for measuring performance
- audio-fx.js - an HTML5
<audio>
wrapper - state-machine.js - a finite state machine
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:
base.js
- javascript prerequisitesgame.js
- a simple game loop and some helper methodsdom.js
- minimal jQuery-like $() DOM helperkey.js
- a config based keyboard event mapmath.js
- additional math helper methodsmenu.js
- a DOM based game menu library
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:
- play the game
- view the source code
- read how to implement the raw snakes game mechanics.
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…