Skip to content

Instantly share code, notes, and snippets.

@AlexandruSimandi
Created April 6, 2015 15:25
Show Gist options
  • Save AlexandruSimandi/1f5bb5b37b77c608632f to your computer and use it in GitHub Desktop.
Save AlexandruSimandi/1f5bb5b37b77c608632f to your computer and use it in GitHub Desktop.
game of life javascript with canvas
var UIModule = (function (){
//function for listener, starts/stops runnig game
function enterPressed(e){
if(e.keyCode == 13){
if(gameModule.isRunning() == false){
document.getElementById('status').innerHTML = "Game is running ";
gameModule.run();
}else {
document.getElementById('status').innerHTML = "Game is paused ";
gameModule.pause();
}
}
}
//makes possible to click a cell anytime and change alive/dead property
function clickCell(e){
var mousePos = getMousePos(e);
var i = parseInt(mousePos.x / gameModule.getCellDiameter());
var j = parseInt(mousePos.y / gameModule.getCellDiameter());
gameModule.drawCell(i,j);
}
//gets mouse position relative to canvas, returns x,y coordiantes
function getMousePos(evt) {
var rect = gameModule.getCanvas().getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
return {
initialize: function(){
window.addEventListener("keydown",enterPressed,false);
document.getElementById("Acorn").addEventListener("mousedown",gameModule.makeAcorn,false);
gameModule.getCanvas().addEventListener("mousedown",clickCell,false);
}
};
})();
//module used to compute and render in canvas
var gameModule = (function () {
//matrix size
var dimension;
//canvas used in html file
var canvas;
//basic cell stuff good to know for module
var cellMargin;
var cellDiameter;
//canvas prop
var canvasDraw;
var canvasWidth;
var canvasHeight;
//matrix for alive/dead cells and matrix to memorize changes
var world;
var changes;
var moduleInitialized = false;
var gameRunning;
//draws cell in canvas
function drawCell(x,y,radius,alive){
//canvasDraw.clearRect(x,y,radius,radius);
canvasDraw.beginPath();
canvasDraw.fillStyle = "#000000";
//canvasDraw.arc(x,y,radius,0,2*Math.PI);
canvasDraw.rect(x,y,radius,radius);
canvasDraw.closePath();
canvasDraw.stroke();
if(alive){
canvasDraw.fillStyle="green";
} else canvasDraw.fillStyle="white";
canvasDraw.fill();
}
//gets the cell properly in case the questioned cell is over the border
function getCell(x, y){
if(x>=dimension) { x = 0; }
if(y>=dimension) { y = 0; }
if(x < 0) { x = dimension - 1; }
if(y < 0) { y = dimension - 1; }
return world[x][y];
}
//counts how many alive neighbors there are
function checkNeighbours(x,y){
var count = 0;
if(getCell(x-1, y-1)) count ++;
if(getCell(x, y-1)) count ++;
if(getCell(x+1, y-1)) count ++;
if(getCell(x-1, y)) count ++;
if(getCell(x+1, y)) count ++;
if(getCell(x-1, y+1)) count ++;
if(getCell(x, y+1)) count ++;
if(getCell(x+1, y+1)) count ++;
return count;
}
//todo, paint only changes
function paintCanvas(){
for(var i = 0; i < dimension; i++){
for(var j = 0; j < dimension; j++){
if(changes[i][j])
drawCell(i*cellDiameter+1,j*cellDiameter+1,cellDiameter,world[i][j]);
}
}
}
//places "acorn" shape on screen
function makeAcorn() {
var middle = parseInt(dimension/2);
world[middle][middle] = true;
drawCell((middle)*cellDiameter+1,(middle)*cellDiameter+1,cellDiameter,world[middle][middle]);
world[middle + 1][middle] = true;
drawCell((middle + 1)*cellDiameter+1,(middle)*cellDiameter+1,cellDiameter,world[middle + 1][middle]);
world[middle + 1][middle - 1] = true;
drawCell((middle + 1)*cellDiameter+1,(middle - 1)*cellDiameter+1,cellDiameter,world[middle + 1][middle - 1]);
world[middle + 2][middle] = true;
drawCell((middle + 2)*cellDiameter+1,(middle)*cellDiameter+1,cellDiameter,world[middle + 2][middle]);
world[middle + 2][middle + 1] = true;
drawCell((middle + 2)*cellDiameter+1,(middle + 1)*cellDiameter+1,cellDiameter,world[middle + 2][middle + 1]);
};
//looping function that computes and renders next generation in game, stops/stars running based on bool gameRunning modified by enterPressed
function playGeneration(){
if(gameRunning){
var worldTemp = [];
for(var i = 0; i < dimension; i++){
worldTemp[i] = [];
var lifeScore;
for(var j = 0; j < dimension; j++){
lifeScore = checkNeighbours(i,j);
if (world[i][j]) {
if(lifeScore == 2 || lifeScore == 3) {
worldTemp[i][j] = true;
} else {
worldTemp[i][j] = false;
}
} else if(lifeScore == 3) {
worldTemp[i][j] = true;
}
if(world[i][j] != worldTemp[i][j]){
changes[i][j] = true;
} else changes[i][j] = false;
}
}
world = worldTemp;
paintCanvas();
var x = setTimeout(function() {playGeneration();}, 1);
}
}
return {
//initializes everything only once
initialize: function(){
if(moduleInitialized == false){
moduleInitialized = true;
dimension = parseInt(window.prompt("enter matrix size"));
canvas = document.getElementById("main");
cellMargin = 0;
cellDiameter = canvas.width/(dimension + cellMargin);
canvasDraw = canvas.getContext("2d");
canvasDraw.lineWidth = 0.5;
canvasWidth = canvas.width;
canvasHeight = canvas.height;
world = [];
changes = [];
for(var i = 0; i < dimension; i++){
world[i] = [];
changes[i] = [];
for(var j = 0; j < dimension; j++){
world[i][j] = false;
changes[i][j] = true;
}
}
gameRunning = false;
//builds first time every cell
paintCanvas();
}
},
run: function (){
gameRunning = true;
playGeneration();
},
pause: function(){
gameRunning = false;
},
isRunning: function(){
return gameRunning;
},
makeAcorn: function(){
makeAcorn();
},
getCanvas: function(){
return canvas;
},
drawCell: function(i,j){
if(world[i][j]){
world[i][j] = false;
} else world[i][j] = true;
drawCell(i*cellDiameter+1,j*cellDiameter+1,cellDiameter,world[i][j]);
},
getCanvas: function(){
return canvas;
},
getCellDiameter: function(){
return cellDiameter;
}
};
})();
window.onload = function(){
gameModule.initialize();
UIModule.initialize();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment