GameOfLife
NOTE: DRAW WITH MOUSE. START SIMULATION WITH SPACEBAR.
For a space that is 'populated':
Each cell with one or no neighbors dies, as if by loneliness.
Each cell with four or more neighbors dies, as if by overpopulation.
Each cell with two or three neighbors survives.
For a space that is 'empty' or 'unpopulated'
Each cell with three neighbors becomes populated.
/**
* Copyright pipeep ( http://wonderfl.net/user/pipeep )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/vuSY
*/
//NOTE: DRAW WITH MOUSE. START SIMULATION WITH SPACEBAR.
/*
For a space that is 'populated':
Each cell with one or no neighbors dies, as if by loneliness.
Each cell with four or more neighbors dies, as if by overpopulation.
Each cell with two or three neighbors survives.
For a space that is 'empty' or 'unpopulated'
Each cell with three neighbors becomes populated.
*/
package {
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.MouseEvent;
import flash.utils.*;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.filters.GlowFilter;
import flash.filters.BitmapFilterQuality;
public class GameOfLife extends Sprite {
private var grid:Bitmap;
private var gridOutline:Bitmap;
private var resolution:uint = 7;
private var playing:Boolean;
private var oldBData:BitmapData;
private const emptyPixel:uint = 0x00FFFFFF;
private const filledPixel:uint = 0xFF000000;
private var speed:uint;
public function GameOfLife() {
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function toggleGlow() {
if(filters == null || filters.length == 0) {
filters = new Array(new GlowFilter(0, 1., 7.,7., 1, BitmapFilterQuality.LOW));
} else { filters = null; }
}
private function onAddedToStage(event:Event) {
speed = 100;
grid = new Bitmap();
grid.bitmapData = new BitmapData(stage.stageWidth/resolution, stage.stageHeight/resolution, true, emptyPixel);
grid.width = ((uint)(stage.stageWidth/resolution))*resolution;
grid.height = ((uint)(stage.stageHeight/resolution))*resolution;
gridOutline = new Bitmap();
drawGridOutline();
addChild(gridOutline);
addChild(grid);
stage.addEventListener(MouseEvent.MOUSE_DOWN, drawPixel);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
playing = true;
step();
toggleGlow();
}
private function drawGridOutline() {
gridOutline.bitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x00FFFFFF);
for(var ix:uint = 0; ix < stage.stageWidth; ix++) {
for(var iy:uint = 0; iy < stage.stageHeight; iy++) {
if(Math.floor(((Number)(ix))%((Number)(resolution))) == 0 || Math.floor(((Number)(iy))%((Number)(resolution))) == 0) {
gridOutline.bitmapData.setPixel32(ix, iy, 0x33000000);
}
}
}
}
private function step() {
//setTimeout(step, speed);
var sTime:int = getTimer();
if(grid.bitmapData.width != (uint)(stage.stageWidth/resolution) && grid.bitmapData.height != (uint)(stage.stageHeight/resolution)) {
oldBData = grid.bitmapData;
grid.bitmapData = new BitmapData(stage.stageWidth/resolution, stage.stageHeight/resolution, true, emptyPixel);
grid.bitmapData.merge(oldBData, new Rectangle(0, 0, oldBData.width, oldBData.height), new Point(0, 0), 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
grid.width = ((uint)(stage.stageWidth/resolution))*resolution;
grid.height = ((uint)(stage.stageHeight/resolution))*resolution;
drawGridOutline();
} else {
oldBData = grid.bitmapData.clone();
}
oldBData.lock();
grid.bitmapData.lock();
if(playing) {
var surroundCount:uint;
for(var ix:uint = 0; ix < grid.bitmapData.width; ix++) {
for(var iy:uint = 0; iy < grid.bitmapData.height; iy++) {
surroundCount = getSurroundingCount(ix, iy);
if(oldBData.getPixel32(ix, iy) == filledPixel) {
if(surroundCount<2 || surroundCount>3) {
grid.bitmapData.setPixel32(ix, iy, emptyPixel);
}
} else if(surroundCount == 3) { grid.bitmapData.setPixel32(ix, iy, filledPixel); }
}
}
}
grid.bitmapData.unlock();
oldBData.dispose();
var timeout:int = speed-(getTimer()-sTime);
if(timeout < 10) { timeout = 10; }
setTimeout(step, timeout);
}
private function getSurroundingCount(a_x:uint, a_y:uint) {
var total:uint = 0;
for(var ix:int = -1; ix < 2; ix++) {
for(var iy:int = -1; iy < 2; iy++) {
if((uint)(a_x+ix) < grid.bitmapData.width && (uint)(a_y+iy) < grid.bitmapData.height) {
total += (uint)(oldBData.getPixel32(a_x+ix, a_y+iy) == filledPixel);
}
}
}
total -= (uint)(oldBData.getPixel32(a_x, a_y) == filledPixel);
return total;
}
private function drawPixel(event:MouseEvent) {
grid.bitmapData.setPixel32((int)(event.localX/resolution), (int)(event.localY/resolution), filledPixel);
stage.addEventListener(MouseEvent.MOUSE_MOVE, drawPixel);
stage.addEventListener(MouseEvent.MOUSE_UP, cancelMouseMoveListener);
playing = false;
}
private function cancelMouseMoveListener(event:MouseEvent) {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, drawPixel);
stage.removeEventListener(MouseEvent.MOUSE_UP, cancelMouseMoveListener);
}
private function onKeyDown(event:KeyboardEvent) {
if(event.keyCode == Keyboard.UP) {
if(speed > 50) {
speed -= 10;
}
} else if(event.keyCode == Keyboard.DOWN) {
speed += 10;
} else if(event.keyCode == 187) {//plus
resolution++;
} else if(event.keyCode == 189) {//minus
if(resolution > 1) {
resolution--;
}
}
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyUp);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
private function onKeyUp(event:KeyboardEvent) {
if(event.keyCode == Keyboard.SPACE) {
playing = !playing;
} else if(event.keyCode == 70) { //'f' key
toggleGlow();
}
//trace(event.keyCode);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyUp);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
}
}