From cd91b753210c9cc4ecb602b8159932e559660100 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Mon, 20 Jun 2011 23:54:24 -0700 Subject: [PATCH] More or less finished product: added options like speed and density and age color effects --- life.html | 176 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 143 insertions(+), 33 deletions(-) diff --git a/life.html b/life.html index e4c65c2..a686d7c 100644 --- a/life.html +++ b/life.html @@ -10,13 +10,15 @@ var width_c; var cells; var timer; + var effects; - + // set start/stop button value function btn_control_set_name(name) { var btn = document.getElementById('control-btn'); btn.value = name; } + // generate an 2d array of cells based on current geometry function gen_cells() { var new_cells = new Array(height_c); for(var i = 0; i < height_c; i++) { @@ -24,33 +26,54 @@ } for (var y = 0; y < height_c; y++) { for (var x = 0; x < width_c; x++) { - new_cells[y][x] = false; + new_cells[y][x] = 0; } } return new_cells; } - + + // init the cells function init_cells() { cells = gen_cells(); } + // Generate and populate the geometry variables + // possibly over complicated from my experiment with an elastic resizeable board + function get_demensions() { + var canvas = document.getElementById('board'); + size = parseInt( document.getElementById('density').value); + width_px = canvas.offsetWidth - (canvas.offsetWidth%size); + canvas.width = width_px; + width_c = width_px/ size; + height_px = canvas.offsetHeight - (canvas.offsetHeight%size); + canvas.height = height_px; + height_c = height_px/size; + //console.log(width_px + 'x' + height_px + ' => ' + width_c + 'x' +height_c); + } + + // init the board + // set vars + // get geometry + // generate cells for 1st time + // draw function board_init() { var canvas = document.getElementById('board'); - size = 10; - width_px = canvas.width; - width_c = width_px/ size; - height_px = canvas.height; - height_c = height_px/size; + document.getElementById('density').value = 10; + get_demensions(); btn_control_set_name('Start'); - hertz = 4; + document.getElementById('speed').value = 8; + change_speed(); init_cells(); + document.getElementById('effects').value=0; + effects=0; redraw(); } + // Draw the current board: gird, then cells function redraw() { - console.log('redraw()'); var canvas = document.getElementById('board'); var c = canvas.getContext('2d'); + get_demensions(); c.globalCompositeOperation = 'destination-over'; @@ -58,7 +81,6 @@ c.fillStyle='rgba(0,0,0,0.)'; c.strokeStyle= 'rgba(192,192,192,1)'; - c.save(); c.beginPath(); @@ -66,28 +88,54 @@ c.stroke(); - c.strokeStyle= 'rgba(0,0,0,1)'; - c.fillStyle = c.strokeStyle; - c.beginPath(); draw_cells(c); - c.stroke(); - c.fill(); } + // Generate a cycling darkening with age rainbow color + // based on math/code from http://www.krazydad.com/makecolors.php + function setStrokeAgeRainbow(l, c) { + var frequency = 0.3; + var center = 200; //128; + var width = 55; //127; + + var red = Math.floor( (Math.sin(frequency*l + 0) * width + center) -l) ; + var green = Math.floor( (Math.sin(frequency*l + 2) * width + center) -l); + var blue = Math.floor( (Math.sin(frequency*l + 4) * width + center) -l); + + red = Math.max(0, red); + green = Math.max(0, green); + blue = Math.max(0, blue); + + c.strokeStyle= 'rgba('+red+','+green+','+blue+','+1+')'; + } + + // Draw all the cells onto the board inside the grid function draw_cells(c) { for (var y = 0; y < height_c; y++) { for (var x =0; x < width_c; x ++) { - if (cells[y][x] == true) { + if (cells[y][x] != 0) { + + if(effects == 0) { + c.strokeStyle = 'rgba(0,0,0,1)'; + } else { + setStrokeAgeRainbow(cells[y][x], c); + } + + c.fillStyle = c.strokeStyle; + c.beginPath(); c.moveTo(x*size +1, y*size+1); c.lineTo(x*size+ size-1, y*size+1); c.lineTo(x*size+ size-1, y*size + size-1); c.lineTo(x*size+1, y*size + size-1); - // auto return home? + // auto return home + c.stroke(); + c.fill(); } } } } + // draw the grid and border function draw_grid(c) { // Horizontal lines for (var y = 0; y <= height_px; y += size) { @@ -102,20 +150,24 @@ } - + // When we've loaded, run! window.onload = board_init; + // is a cell alive or dead + // 0 for dead, 1 for alive + // walls count as dead + // used by num_neighbours function cell_value(x, y) { //console.log('(x:' + x + ',y:' + y + ') w/s:' + (width/size) + ' h/s:' + (height/size) ); if (x < 0 || x >= width_c || y < 0 || y >= height_c) { return 0; } else { - return cells[y][x]; + return cells[y][x] == 0 ? 0 : 1; } } - - + // return the number of neighbours for a cell + // walls count as dead function num_neighbours(x, y) { var n = 0; n += cell_value(x-1, y-1); @@ -132,22 +184,24 @@ return n; } + // Simulate one generation of cells + // create a new cells 2d array and simulate the next generation + // into it and then replace the current cells with it function step() { var new_cells = gen_cells(); for(var y=0; y < height_c; y++) { for(var x =0 ; x < width_c; x++) { var n = num_neighbours(x, y); - if (cells[y][x] == true) { + if (cells[y][x] != 0) { if (n < 2 || n > 3) { - new_cells[y][x] = false; + new_cells[y][x] = 0; } else { - console.log('ALIVE'); - new_cells[y][x] = true; + new_cells[y][x] = cells[y][x] +1; } } else if (n == 3) { - new_cells[y][x] = true; + new_cells[y][x] = 1; } else { - new_cells[y][x] = false; + new_cells[y][x] = 0; } } } @@ -155,6 +209,7 @@ cells = new_cells; } + // Stop/Start button press function control_click() { var btn = document.getElementById('control-btn'); if (btn.value == 'Start') { @@ -166,28 +221,83 @@ } } + // Function to call on timmer + // simulate on e generation, + // redrawn + // reset timmer function tick() { step(); redraw(); - timmer = setTimeout('tick();', 1000/hertz); + timmer = setTimeout('tick();', 1000.0/hertz); } + // Handler for a click on the board to place/unplace a cell function board_click(e) { var canvas = document.getElementById('board'); var x = Math.floor((e.pageX-canvas.offsetLeft)/size); var y = Math.floor((e.pageY-canvas.offsetTop)/size); - console.log(e.pageX + '/' + size + ' = ' + x + ' && ' + e.pageY + '/' + size + ' = ' +y); cells[y][x] = ! cells[y][x]; redraw(); } + // Change speed handler + function change_speed() { + hertz = parseInt(document.getElementById('speed').value); + } + + // Resize board handler (kind of not used) + // Left over from experiment in resiable elastic board + // Abandoned because of problems with lining up mouse clicks on board + // and weird stretcing issues + function resize_cells() { + var new_cells = gen_cells(); + var w = Math.min(width_c, cells[0].length); + var h = Math.min(height_c, cells.length); + for(var y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + new_cells[y][x] = cells[y][x]; + } + } + + cells = new_cells; + } + + // What to do on a document resize (more usefull for elastic boards) + function canvas_resize() { + get_demensions(); + resize_cells(); + redraw(); + } - - + + Speed: + Density: + Effects: + + + Dan Ballard (2011) <dan@mindstab.net> +
- +