Skip to content

Instantly share code, notes, and snippets.

@christospappas
Last active August 29, 2015 14:15
Show Gist options
  • Save christospappas/b2cecec1bdcbc0e90947 to your computer and use it in GitHub Desktop.
Save christospappas/b2cecec1bdcbc0e90947 to your computer and use it in GitHub Desktop.
Conways Game Of Life
var GameOfLife = (function(window, undefined) {
'use strict';
var Game = function(width, height, initPattern) {
this.grid = new Grid(width, height, initPattern);
this.stopped = false;
this.run();
};
Game.prototype = {
run: function() {
window.requestAnimationFrame(this.tick.bind(this));
},
stop: function() {
this.stopped = true;
},
tick: function() {
this.grid.render();
this.grid.nextGeneration();
window.requestAnimationFrame(this.tick.bind(this));
}
};
var Grid = function(width, height, initPattern) {
this.cellSize = 4;
this.width = width;
this.height = height;
this.cwidth = width * this.cellSize;
this.cheight = height * this.cellSize;
this.initGrid(initPattern);
};
Grid.prototype = {
// create Grid and set initial pattern
initGrid: function(pattern) {
this.grid = new Array(this.width);
for (var i=0; i < this.width; i++) {
this.grid[i] = new Array(this.height);
for (var j=0; j < this.height; j++) {
this.grid[i][j] = new Cell(i, j);
}
}
if (!this.pattern) {
this.pattern = this.randomPattern();
}
for (i=0; i < this.pattern.length; i++) {
this.grid[this.pattern[i][0]][this.pattern[i][1]].live = true;
}
this.$canvas = $('<canvas/>').attr({width: this.cwidth, height: this.cheight}).appendTo('body');
this.ctx = this.$canvas[0].getContext('2d');
},
randomPattern: function() {
var total = Math.floor((this.width*this.height)/2);
var pattern = [];
while(total) {
var rx = Math.round(Math.random() * (this.width-1));
var ry = Math.round(Math.random() * (this.height-1));
if (!this.grid[rx][ry].live) {
pattern.push([rx, ry]);
total--;
}
}
return pattern;
},
nextGeneration: function() {
this.traverseCells(function(cell) {
cell.liveNeighbors = this.getLiveNeighborsCount(cell);
}.bind(this));
this.traverseCells(function(cell) {
cell.update();
});
},
traverseCells: function(cb) {
for (var i=0; i < this.width; i++) {
for (var j=0; j < this.height; j++) {
cb(this.grid[i][j]);
}
}
},
getLiveNeighborsCount: function(cell) {
var offsets = [[-1,-1], [-1, 0], [-1, 1], [0,-1], [0,1], [1,-1], [1,0], [1,1]];
var count = 0;
for (var i=0; i < offsets.length; i++) {
var xOffset = cell.x+offsets[i][0];
var yOffset = cell.y+offsets[i][1];
if (this.grid[xOffset] && this.grid[xOffset][yOffset]) {
var neighbor = this.grid[xOffset][yOffset];
if (neighbor && neighbor.live) { count++; }
}
}
return count;
},
render: function() {
this.ctx.fillStyle = '#eee';
this.ctx.clearRect(0, 0, this.cwidth, this.cheight);
this.traverseCells(function(cell) {
if (cell.live) {
this.ctx.fillStyle = 'black';
this.ctx.fillRect(cell.x*this.cellSize, cell.y*this.cellSize, this.cellSize, this.cellSize);
}
}.bind(this));
}
};
var Cell = function(x, y) {
this.x = x;
this.y = y;
this.liveNeighbors = 0;
this.live = false;
};
Cell.prototype = {
update: function() {
var liveNeighbors = this.liveNeighbors;
if (this.live) {
if (liveNeighbors < 2 || liveNeighbors > 3) {
this.live = false;
}
}
if (liveNeighbors === 3) {
this.live = true;
}
}
};
return {
start: function(width, height, initPattern) {
return new Game(width, height, initPattern);
},
/* test-code */
Grid: Grid,
Game: Game
/* end-test-code */
};
})(window);
GameOfLife.start(100, 100);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment