I first learned about Processing at Maker Faire in 2011. I don’t consider myself a visual artist, but Processing made it straightforward to create beautiful graphics using code. However, I didn’t want to go through the hassle of working with the Processing IDE, so I set it aside for a couple years.
Recently, I came across Processing.js and decided to give it another shot. By porting it to JavaScript, the developers have made it easier to get started and publish to the web (though I would guess that the JavaScript version runs slower than native Processing). All I needed was a project.
Naturally, I chose to implement Conway’s Game of Life. First publicized in 1970, it has fascinated many over the years due to the complexity of patterns that it produces based on a few simple rules. YouTube is full of videos depicting this cellular automaton; one of my favorites is this one taken of an installation on the Boston Greenway that I got to see in person. For Inception-level brain melting, there’s Game of Life in Game of Life. My favorite among the common patterns that arise is the glider since it always seems like it’s on a mission.
So here it is! You can reset the game by clicking anywhere on it, or you can wait five minutes and it will reset itself. I experimented with some crazier color shifting patterns as I was developing it, but I settled on a subtly undulating rainbow that I think would make for a good screen saver. Besides increasing performance to allow for a grid with more cells, the code could also be improved by adding a method for determining when the game has reached a steady state. One way would be to cache the previous few generations and compare the current generation against them, but computationally that could have a terrible worst-case performance. I’m open to suggestions! The source code is available here.
Pingback: Today’s Links « /dev
Pingback: Friday Links #243 | Blue Onion Software *
One good way to determine when the game has reached a steady state is to use a zorbrist hashing
A proposition (not tested)
//you have to add this code
function getRandomInt () {
return Math.floor(Math.random() * (1<<31 + 1)) ;
}
function initializeZ() {
for(var i = 0; i < WIDTH; i++) {
for(var j = 0; j < HEIGHT; j++) {
z[0][i][j] = getRandomInt ();
z[1][i][j] = getRandomInt ();
}
}
}
function hash() {
var hash = 0;
iterateGrid(function(i, j, isAlive) {
hash ^= z[isAlive?0:1][i[j];
});
}
// and modify the folowing functions
function initializeGrid() {
GRID = constructNewGrid();
populateGrid();
GENERATIONS = 1;
z = [constructNewGrid(),constructNewGrid()];
initializeZ();
generationsHash = array();
generationHash[hash()] = GENERATIONS;
}
// create the GRID for the next generation based on the current GRID
function generate() {
var nextGeneration = constructNewGrid();
iterateGrid(function(i, j, isAlive) {
nextGeneration[i][j] = cellWillBeAlive(i, j, isAlive);
});
GRID = nextGeneration;
GENERATIONS++;
h = hash();
if (generationHash[h]) {
// repetition of generationHash[h] occured at generation GENERATION
// do whatever you want
// maybe stopping to save the generationHash
}
generationHash[h] = GENERATION;
}
Thanks for your detailed comment! I wasn’t aware of this technique, so I’ll do some more research into using it. Hopefully there won’t be too much of a performance hit when implementing it.
aarg the code tag eat all my white space
but I think it’s readable enought)
It’s perfectly readable =)
Yo David! Just wanted to say, this inspired me to look into Processing.js. I created a cellular automata simulator at http://robinforest.net/.
I like the circular cells and rainbow colors in yours, looks pretty sweet.
Pingback: Life and polyominoes | cartesian product