Conway's Game of Life in Javascript
Published: 23 Jun 2016
Conway's Game of Life is probably the most interesting and popular automata simulation. A automata simulation is when a set of cells get given simple rules of how to react within their environment that when played out over time (in steps) create a patterns, often complex and organic looking in nature.
I've been interested in Conway's work and specifically his simulation Game of Life for a while, both on a theorical level and as a fun way to learn programming languages by implementing it. Recently I finally got round to program this one using vanilla javascript and the html5 Canvas API.
js
// setup canvas
var canvas = document.getElementById('gameCanvas');
var ctx = canvas.getContext('2d')
// canvas and grid size defaults
var gridWidth = 140;
var gridHeight = 70;
var gridSquareWidth = 10;
canvas.width = gridWidth * gridSquareWidth;
canvas.height = gridHeight * gridSquareWidth;
canvas.style.width = canvas.width;
canvas.style.height = canvas.height;
var grid = [];
var gridNext = [];
// create default grid array
// sudo random noise
for (var x = 0; x < gridWidth; x++) {
grid[x] = []
gridNext[x] = []
for (var y = 0; y < gridHeight; y++) {
grid[x][y] = [];
gridNext[x][y] = []
var rand = Math.random()*100;
if (rand > 44) {
grid[x][y] = 1;
}
}
}
// life init grid
function life(){
// touch each grid coord
for (var x = 0; x < gridWidth; x++) {
for (var y = 0; y < gridHeight; y++) {
// counts alive or dead for neighbours
var count = countNearby(x,y);
if(grid[x][y] == 0){
if(count == 3){
// life is born
gridNext[x][y] = 1;
}
}else{
if(count < 2 || count > 3){
// underpopulation & overpopulation
gridNext[x][y] = 0;
}else{
gridNext[x][y] = 1;
}
}
}
}
// replace old grid with new population grid
grid = gridNext;
}
// count grid neighbours
function countNearby(x,y){
var count = 0;
// count all nearby sqaures
counter(x-1,y-1);
counter(x-1,y);
counter(x-1,y+1);
counter(x,y-1);
counter(x,y+1);
counter(x+1,y-1);
counter(x+1,y);
counter(x+1,y+1);
function counter(x,y){
// if x and y on the grid
if(x > 0 && x < gridWidth && y > 0 && y < gridHeight){
if (grid[x][y] == 1) count++;
}
}
// return count value
return count;
}
// game update
function update(dt) {
// iterate simulation rules
life();
// draw result
draw();
}
function draw() {
// clear canvas
ctx.fillStyle = '#fee';
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var x = 0; x < gridWidth; x++) {
for (var y = 0; y < gridHeight; y++) {
if (grid[x][y] == 1) {
ctx.fillStyle = "#ee66aa";
ctx.fillRect(x * gridSquareWidth, y * gridSquareWidth, gridSquareWidth, gridSquareWidth);
}
}
}
}
// The main game loop
var lastTime;
function gameLoop() {
var now = Date.now();
var dt = (now - lastTime) / 1000.0;
update(dt);
lastTime = now;
window.setTimeout(gameLoop, 50);
};
// start game
gameLoop();
Clone it on Github:
References:
Next experiment: An End - a Twine Story