2010/06/27

Geoff - Game of Life

I've been fascinated with Conway’s Game of Life for years now.  I love how there is an apparent order to things that is reproducible as well as simple in it's requirements.  Recently there was a discovery that made the tech news about a new pattern that replicated itself.  I'll be honest, the demo of the replicating code wasn't as sexy as I had hoped.  But it did remind me how much I want to make this game.

I've been on a recent tear through javascript, browser and server side (node.js is just fun).  So I set out to build a little game of life with js and html.  jQuery aided with some of the lifting too.  :)

After a couple afternoons Geoff was born.  He's a simple lad.  Just gives you the basics, but still fun to play with non-the-less.  I have only tested him on Chrome, FF, and Safari.  Interestingly this is a great way to see how fast your js engine is.  Chrome handles it the best on my laptop.  FF the worst.

A little bit about the code:

jQuery's live() event handling is perfect for this situation.  Since I opted to turn a crap-ton of b tags into large pixels of my game grid, I needed to bind some mouseover/mouseout and click events to each item.  There is no need to do this to each of the ~2k tags.  Instead, using live(), jQuery will bind to the document and as events bubble up, check to see if they're relevant to my event handlers.  This cuts memory usage as well as bind time.

Recursion with setTimeout.  Initially when I built this I was using setInterval() to fire my life function and advance Geoff another step.  On Chrome it was fast enough that I didn't notice any problems.  But when I tested in Safari and FF, I found that I was "dropping frames" when I cranked up the speed.  This had weird effects.  So I used a recursive function that pauses at the end of it's execution.  This will ensure that I don't lose an iteration, while giving reasonable control over the speed of execution.

Pseudo-casting as integer.  This is a hack that I picked up from James Padolsey's blog.  For my purposes it's a nice way to take a boolean expression and convert it into a 0 or 1.

// sum up the active neighbors
var t = typeof current[neighbors[j]];

active += ~~(t === 'number' && current[neighbors[j]] === 1);
    

Best practices.  I've violated them .. a bit.  

Well I hope you have fun playing.  I tried drawing moo and it lived a healthy and rich life.  

Enjoy Geoff!