Skip to content

Instantly share code, notes, and snippets.

@simonlc
Created October 14, 2012 16:01

Revisions

  1. Simon Laroche revised this gist Oct 15, 2012. 1 changed file with 35 additions and 11 deletions.
    46 changes: 35 additions & 11 deletions life.js
    Original file line number Diff line number Diff line change
    @@ -3,12 +3,21 @@

    var FPS = 5;
    var paused = true;
    var gameStarted = false;
    var gLoop;
    var generations = 0;
    var population = 0;

    var lifeForms = [
    [[28, 28], [29, 28], [30, 28], [28, 29], [28, 30], [30, 29], [30, 30]], //Arch
    [[29, 28], [30, 29], [30, 30], [29, 30], [28, 30]], //Glider
    [[29, 28], [30, 28], [28, 29], [29, 29], [29, 30]], //R-pentomino
    [[32, 27], [26, 28], [27, 28], [27, 29], [31, 29], [32, 29], [33, 29]] //Diehard
    ];

    var start = document.getElementById('start');
    var reset = document.getElementById('reset');
    var random = document.getElementById('random');
    var stats = document.getElementById('s');
    var wrapper = document.getElementById('w');
    var canvas = document.getElementById('c');
    @@ -24,7 +33,6 @@ function newGrid() {
    for (var i = 0; i < canvas.width / 10; i++) {
    cells[i] = new Array(canvas.height / 10);
    }
    clear();
    return cells;
    }

    @@ -96,10 +104,8 @@ function draw() {
    function update() {
    population = 0;
    cellsCopy = new Array();
    for(var i = 0; i < cells.length; i++) {
    cellsCopy.push(cells[i].slice());
    }
    for (var x = 0; x < cells.length; x++) {
    cellsCopy.push(cells[x].slice());
    for (var y = 0; y < cells[x].length; y++) {
    if (neighbours(x, y) < 2 || neighbours(x, y) > 3) {
    cellsCopy[x][y] = false;
    @@ -116,6 +122,7 @@ function update() {
    }

    function play() {
    gameStarted = true;
    if (paused) {
    gLoop = setInterval(gameLoop, 1000 / FPS);
    paused = false;
    @@ -127,6 +134,22 @@ function play() {
    }
    }

    function resetGame() {
    paused = false;
    play();
    cells = newGrid();
    generations = 0;
    population = 0;
    refresh();
    }

    function getLife(index) {
    var life = lifeForms[index] || lifeForms[~~(Math.random() * lifeForms.length)];
    for (var x = 0; x < life.length; x++) {
    cells[life[x][0]][life[x][1]] = true;
    }
    }

    canvas.addEventListener('click', function(e) {
    if (paused) {
    var mx = ~~((e.pageX - canvas.offsetLeft) / 10);
    @@ -142,15 +165,14 @@ canvas.addEventListener('click', function(e) {

    start.addEventListener('click', play, false);

    reset.addEventListener('click', function() {
    paused = false;
    play();
    cells = newGrid();
    generations = 0;
    population = 0;
    random.addEventListener('click', function() {
    resetGame();
    getLife();
    refresh();
    }, false);

    reset.addEventListener('click', resetGame, false);

    function refresh() {
    clear();
    draw();
    @@ -163,4 +185,6 @@ function gameLoop() {
    update();
    }

    cells = newGrid();
    cells = newGrid();
    getLife(0);
    refresh();
  2. Simon Laroche revised this gist Oct 14, 2012. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions life.js
    Original file line number Diff line number Diff line change
    @@ -44,16 +44,16 @@ function neighbours(x, y) {
    if (cells[x + 1][y - 1]) {
    count++;
    }
    if (cells[x - 0][y + 1]) {
    if (cells[x][y + 1]) {
    count++;
    }
    if (cells[x + 0][y - 1]) {
    if (cells[x][y - 1]) {
    count++;
    }
    if (cells[x - 1][y + 0]) {
    if (cells[x - 1][y]) {
    count++;
    }
    if (cells[x + 1][y - 0]) {
    if (cells[x + 1][y]) {
    count++;
    }
    }
  3. Simon Laroche created this gist Oct 14, 2012.
    166 changes: 166 additions & 0 deletions life.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,166 @@
    // Conway's Game of Life for HTML5 Canvas
    // By Simon Laroche

    var FPS = 5;
    var paused = true;
    var gLoop;
    var generations = 0;
    var population = 0;

    var start = document.getElementById('start');
    var reset = document.getElementById('reset');
    var stats = document.getElementById('s');
    var wrapper = document.getElementById('w');
    var canvas = document.getElementById('c');
    var ctx = canvas.getContext('2d');

    canvas.width = 600;
    canvas.height = 600;
    wrapper.style.width = canvas.width + 'px';
    stats.style.width = canvas.width - 20 + 'px';

    function newGrid() {
    var cells = new Array(canvas.width / 10);
    for (var i = 0; i < canvas.width / 10; i++) {
    cells[i] = new Array(canvas.height / 10);
    }
    clear();
    return cells;
    }

    function neighbours(x, y) {
    var count = 0;
    // TODO Test for out of bounds properly.
    if (x > 0 && y > 0 && x < canvas.width / 10 - 1 && y < canvas.width / 10 - 1) {
    if (cells[x - 1][y - 1]) {
    count++;
    }
    if (cells[x - 1][y + 1]) {
    count++;
    }
    if (cells[x + 1][y + 1]) {
    count++;
    }
    if (cells[x + 1][y - 1]) {
    count++;
    }
    if (cells[x - 0][y + 1]) {
    count++;
    }
    if (cells[x + 0][y - 1]) {
    count++;
    }
    if (cells[x - 1][y + 0]) {
    count++;
    }
    if (cells[x + 1][y - 0]) {
    count++;
    }
    }
    return count;
    }

    function clear() {
    ctx.fillStyle = '#eee';
    ctx.beginPath();
    ctx.rect(0, 0, canvas.width, canvas.height);
    ctx.closePath();
    ctx.fill();
    function grid(increment, color) {
    ctx.fillStyle = color;
    for (var i = 0; i < canvas.width + 1; i += increment) {
    ctx.fillRect(i - 1, 0, 2, canvas.height);
    }
    for (var i = 0; i < canvas.height + 1; i += increment) {
    ctx.fillRect(0, i - 1, canvas.width, 2);
    }
    }
    grid(10, '#ddd');
    grid(100, '#ccc');
    }

    function draw() {
    ctx.fillStyle = '#585858';
    for (var i = 0; i < cells.length; i++) {
    for (var j = 0; j < cells[i].length; j++) {
    if (cells[i][j]) {
    //ctx.fillRect(i * 10 + 1, j * 10 + 1, 8, 8); // square cells
    ctx.beginPath();
    ctx.arc(i * 10 + 5, j * 10 + 5, 4, 0, Math.PI*2, true);
    ctx.fill();
    }
    }
    }
    }

    function update() {
    population = 0;
    cellsCopy = new Array();
    for(var i = 0; i < cells.length; i++) {
    cellsCopy.push(cells[i].slice());
    }
    for (var x = 0; x < cells.length; x++) {
    for (var y = 0; y < cells[x].length; y++) {
    if (neighbours(x, y) < 2 || neighbours(x, y) > 3) {
    cellsCopy[x][y] = false;
    } else if (neighbours(x, y) == 3) {
    cellsCopy[x][y] = true;
    }
    if (cellsCopy[x][y]) {
    population++;
    }
    }
    }
    cells = cellsCopy;
    generations++
    }

    function play() {
    if (paused) {
    gLoop = setInterval(gameLoop, 1000 / FPS);
    paused = false;
    start.innerHTML = 'Pause';
    } else {
    clearInterval(gLoop);
    paused = true;
    start.innerHTML = 'Play';
    }
    }

    canvas.addEventListener('click', function(e) {
    if (paused) {
    var mx = ~~((e.pageX - canvas.offsetLeft) / 10);
    var my = ~~((e.pageY - canvas.offsetTop) / 10);
    if (cells[mx][my]) {
    cells[mx][my] = false;
    } else {
    cells[mx][my] = true;
    }
    refresh();
    }
    }, false);

    start.addEventListener('click', play, false);

    reset.addEventListener('click', function() {
    paused = false;
    play();
    cells = newGrid();
    generations = 0;
    population = 0;
    refresh();
    }, false);

    function refresh() {
    clear();
    draw();
    stats.innerHTML = 'Generations: ' + generations +
    ' Population: ' + population;
    }

    function gameLoop() {
    refresh();
    update();
    }

    cells = newGrid();