Conway's Game of Life! Mouse interacts with the canvas. Clicks toggle between "fading" and "classic" mode. Full version available here: http://www.eng.utoledo.edu/~scline/life/life.html
d=document;c=d.getElementById("c");ctx=c.getContext("2d");cW=cH=c.width=c.height=400;gW=gH=175;bW=cW/gW;bH=cH/gH;mX=mY=-1;g=[];s=true;cX=cY=0;for(o=c;o;){cX+=o.offsetLeft;cY+=o.offsetTop;o=o.offsetParent}function k(a,b){if(a<0||b<0||a>=gW||b>=gH)return 0;return g[a][b]}g=[];for(var l=null,m=0,n=0;n<gW;n++){l=[];for(var p=0;p<gH;p++){m=Math.random()<0.75?0:1;l.push(m)}g.push(l)} setInterval(function(){for(var a=[],b=null,e=0,f=0;f<gW;f++){b=[];for(var h=0;h<gH;h++){e=0;for(var i=-1;i<=1;i++)for(var j=-1;j<=1;j++)if(i!=0||j!=0)e+=k(f+i,h+j);e=k(f,h)==1?e>=2&&e<=3?1:0:e==3?1:0;b.push(e)}a.push(b)}g=a},100);setInterval(function(){s?ctx.fillStyle="rgba(0,0,0,.1)":ctx.fillStyle="#FFF";ctx.fillRect(0,0,cW,cH);ctx.fillStyle=s?"#FFF":"#000";for(var a=0;a<gW;a++)for(var b=0;b<gH;b++)k(a,b)==1&&ctx.fillRect(a*bW,b*bH,bW,bH)},50); c.onmousemove=function(a){mX=a.clientX-cX+d.body.scrollLeft;mY=a.clientY-cY+d.body.scrollTop;gX=~~(mX/bW);gY=~~(mY/bH);g[gX][gY]=1};c.onclick=function(){s=!s};
ZD1kb2N1bWVudDtjPWQuZ2V0RWxlbWVudEJ5SWQoImMiKTtjdHg9Yy5nZXRDb250ZXh0KCIyZCIpO2NXPWNIPWMud2lkdGg9Yy5oZWlnaHQ9NDAwO2dXPWdIPTE3NTtiVz1jVy9nVztiSD1jSC9nSDttWD1tWT0tMTtnPVtdO3M9dHJ1ZTtjWD1jWT0wO2ZvcihvPWM7bzspe2NYKz1vLm9mZnNldExlZnQ7Y1krPW8ub2Zmc2V0VG9wO289by5vZmZzZXRQYXJlbnR9ZnVuY3Rpb24gayhhLGIpe2lmKGE8MHx8YjwwfHxhPj1nV3x8Yj49Z0gpcmV0dXJuIDA7cmV0dXJuIGdbYV1bYl19Zz1bXTtmb3IodmFyIGw9bnVsbCxtPTAsbj0wO248Z1c7bisrKXtsPVtdO2Zvcih2YXIgcD0wO3A8Z0g7cCsrKXttPU1hdGgucmFuZG9tKCk8MC43NT8wOjE7bC5wdXNoKG0pfWcucHVzaChsKX0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKXtmb3IodmFyIGE9W10sYj1udWxsLGU9MCxmPTA7ZjxnVztmKyspe2I9W107Zm9yKHZhciBoPTA7aDxnSDtoKyspe2U9MDtmb3IodmFyIGk9LTE7aTw9MTtpKyspZm9yKHZhciBqPS0xO2o8PTE7aisrKWlmKGkhPTB8fGohPTApZSs9ayhmK2ksaCtqKTtlPWsoZixoKT09MT9lPj0yJiZlPD0zPzE6MDplPT0zPzE6MDtiLnB1c2goZSl9YS5wdXNoKGIpfWc9YX0sMTAwKTtzZXRJbnRlcnZhbChmdW5jdGlvbigpe3M/Y3R4LmZpbGxTdHlsZT0icmdiYSgwLDAsMCwuMSkiOmN0eC5maWxsU3R5bGU9IiNGRkYiO2N0eC5maWxsUmVjdCgwLDAsY1csY0gpO2N0eC5maWxsU3R5bGU9cz8iI0ZGRiI6IiMwMDAiO2Zvcih2YXIgYT0wO2E8Z1c7YSsrKWZvcih2YXIgYj0wO2I8Z0g7YisrKWsoYSxiKT09MSYmY3R4LmZpbGxSZWN0KGEqYlcsYipiSCxiVyxiSCl9LDUwKTsgYy5vbm1vdXNlbW92ZT1mdW5jdGlvbihhKXttWD1hLmNsaWVudFgtY1grZC5ib2R5LnNjcm9sbExlZnQ7bVk9YS5jbGllbnRZLWNZK2QuYm9keS5zY3JvbGxUb3A7Z1g9fn4obVgvYlcpO2dZPX5+KG1ZL2JIKTtnW2dYXVtnWV09MX07Yy5vbmNsaWNrPWZ1bmN0aW9uKCl7cz0hc307
/*
* File: life-js1k.htm
* Author: Sean Cline
* Version: .1
* Description: An HTML5 canvas-drawn "life" universe for Conway's Game of Life.
* License: You may do whatever you please with this file and any code it contains. It is public domain!
* Notes: This file is does not have what most people what consider good coding practices. It is in the name of fitting as much as possible a small space.
* It is effectively a stripped down version of my more functional JS life example found here:
* http://www.eng.utoledo.edu/~scline/life/life.html
*/
//
// Init vars.
//
d = document;
c = d.getElementById("c"); // Save the canvas element to create the context later.
ctx = c.getContext("2d"); // YAY! A place to draw!
cW = cH = c.width = c.height = 400;
gW = gH = 175;
bW = cW/gW;
bH = cH/gH;
mX = mY = -1; // mouseMove() updates this to be the position relative to the dockElement.
g = new Array();
s = true; // Which drawing mode to use, classic, or blurred.
// Set up the canvasX and canvasY in the browser.
cX = cY = 0;
o = c;
while(o) {
cX += o.offsetLeft;
cY += o.offsetTop;
o = o.offsetParent;
}
//
// Functions.
//
// Get the value (whether a cell is alive or dead) for an x,y pair.
function get(x, y) {
if (x < 0 || y < 0 || x >= gW || y >= gH) {
return 0; // Return 0 so everything off the grid is not alive.
}
return g[x][y];
}
// Run and draw 1 full generation.
function run() {
var newgrid = new Array();
var column = null;
var gridval = 0;
for (var x = 0; x < gW; x++) {
column = new Array();
for (var y = 0; y < gH; y++) {
gridval = next(x,y);
column.push(gridval);
}
newgrid.push(column);
}
g = newgrid;
}
// Fade out the old generation.
function draw() {
s ? ctx.fillStyle = "rgba(0,0,0,.1)" : ctx.fillStyle = "#FFF";
ctx.fillRect(0, 0, cW, cH);
// Draw the frame
ctx.fillStyle = s ? "#FFF" : "#000";
for(var x = 0; x < gW; x++) {
for(var y = 0; y < gH; y++) {
if(get(x,y) == 1)
{
ctx.fillRect(x*bW, y*bH, bW, bH);
}
}
}
}
// Executed when the mouse moves over the canvasElement.
function mouseMove(e) {
// Figure out where the mouse is.
// Subtract the canvas element's location from the mouse client location for the reletive position. See why offsetX,offsetY is easier?
mX = e.clientX - cX + d.body.scrollLeft;
mY = e.clientY - cY + d.body.scrollTop;
gX = ~~(mX/bW);
gY = ~~(mY/bH);
g[gX][gY] = 1;
}
// Executed when the canvas is clicked on.
function mouseClick(e) {
s = !s;
}
// Seed the game by generating a random grid.
function seed() {
g = new Array();
var column = null;
var gridval = 0;
for (var x = 0; x < gW; x++) {
column = new Array();
for (var y = 0; y < gH; y++) {
gridval = Math.random() < .75 ? 0 : 1;
column.push(gridval);
}
g.push(column);
}
}
// Calculate the next value for a cell on this grid.
function next(x, y) {
var aliveCount = 0;
for (var xOffset = -1; xOffset <= 1; xOffset++) {
for (var yOffset = -1; yOffset <= 1; yOffset++) {
if (xOffset != 0 || yOffset != 0) {
aliveCount += get(x+xOffset, y+yOffset);
}
}
}
var currentVal = get(x, y);
if (currentVal == 1) {
if (aliveCount >= 2 && aliveCount <= 3) {
return 1;
} else {
return 0;
}
} else {
if (aliveCount == 3) {
return 1;
} else {
return 0;
}
}
}
//
// Init code.
//
// Create a new grid and randomize it.
seed();
setInterval(run, 100);
setInterval(draw, 50);
c.onmousemove = mouseMove;
c.onclick = mouseClick;