Conway's Game of Life
Click and drag mouse around to get it going or unstuck
/**
* Copyright devon_o ( http://wonderfl.net/user/devon_o )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/9Xnl
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.LineScaleMode;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
/**
* ...Conway's game of life...
* http://en.wikipedia.org/wiki/Conway's_Game_of_Life
* http://gamedev.tutsplus.com/tutorials/implementation/creating-life-conways-game-of-life/
*
* @author Devon O.
*/
[SWF(width='465', height='465', backgroundColor='#FFFFFF', frameRate='60')]
public class Main extends Sprite
{
public static const CELL_SIZE:int = 15;
public static var MOUSE_DOWN:Boolean = false;
public static var MOUSE_POS:SimplePoint;
private var mDisplay:BitmapData;
private var mGrid:GameGrid;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(event:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
initStage();
initDisplay();
initGrid();
initCells();
initListeners();
}
private function initStage():void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.showDefaultContextMenu = false;
}
private function initDisplay():void
{
mDisplay = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xFFFFFF);
addChild(new Bitmap(mDisplay));
}
private function initGrid():void
{
var grid:Shape = new Shape();
grid.graphics.lineStyle(0, 0x939393, 1.0, false, LineScaleMode.NONE);
var i:int;
for (i = CELL_SIZE; i < stage.stageWidth; i += CELL_SIZE)
{
grid.graphics.moveTo(i, 0);
grid.graphics.lineTo(i, stage.stageHeight);
}
for (i = CELL_SIZE; i < stage.stageHeight; i += CELL_SIZE)
{
grid.graphics.moveTo(0, i);
grid.graphics.lineTo(stage.stageWidth, i);
}
addChild(grid);
}
private function initCells():void
{
var cellsX:Number = stage.stageWidth / CELL_SIZE;
var cellsY:Number = stage.stageHeight / CELL_SIZE;
mGrid = new GameGrid(cellsX, cellsY, mDisplay);
}
private function initListeners():void
{
MOUSE_POS = new SimplePoint();
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
stage.addEventListener(Event.ENTER_FRAME, onTick);
}
//private var mCount:int = 0;
private function onTick(event:Event):void
{
mGrid.update();
}
private function onDown(event:MouseEvent):void
{
MOUSE_POS.x = stage.mouseX;
MOUSE_POS.y = stage.mouseY;
MOUSE_DOWN = true;
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
stage.addEventListener(Event.MOUSE_LEAVE, onUp);
}
private function onMove(event:MouseEvent):void
{
MOUSE_POS.x = stage.mouseX;
MOUSE_POS.y = stage.mouseY;
}
private function onUp(event:*):void
{
MOUSE_DOWN = false;
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
stage.removeEventListener(Event.MOUSE_LEAVE, onUp);
}
}
}
import flash.display.BitmapData;
import flash.geom.Rectangle;
class Cell
{
public var position:SimplePoint;
public var bounds:Rectangle;
public var isAlive:Boolean;
private var mDisplay:BitmapData;
public function Cell(pos:SimplePoint, display:BitmapData)
{
mDisplay = display;
position = pos;
bounds = new Rectangle(position.x, position.y, Main.CELL_SIZE, Main.CELL_SIZE);
isAlive = false;
}
public function update():void
{
if (Main.MOUSE_DOWN)
{
if (bounds.contains(Main.MOUSE_POS.x, Main.MOUSE_POS.y))
{
isAlive = true;
}
}
}
public function draw():void
{
if (isAlive)
mDisplay.fillRect(bounds, 0x000000);
else
mDisplay.fillRect(bounds, 0xFFFFFF);
}
}
class GameGrid
{
private var mCellsX:int;
private var mCellsY:int;
private var mCells:Array;
private var mNextCellStates:Array;
public function GameGrid(cx:int, cy:int, display:BitmapData )
{
mCellsX = cx;
mCellsY = cy;
mCells = [];
mNextCellStates = [];
for (var i:int = 0; i < mCellsX; i++)
{
mCells[i] = [];
mNextCellStates[i] = [];
for (var j:int = 0; j < mCellsY; j++)
{
mCells[i][j] = new Cell(new SimplePoint(i * Main.CELL_SIZE, j * Main.CELL_SIZE), display);
mNextCellStates[i][j] = false;
}
}
}
private var mCount:int = 0;
public function update():void
{
updateCells();
mCount++
// quick and dirty cheat
if (!(mCount % 4))
{
for (var i:int = 0; i < mCellsX; i++)
{
for (var j:int = 0; j < mCellsX; j++)
{
var cell:Cell = mCells[i][j] as Cell;
var living:Boolean = cell.isAlive;
var count:int = getLivingNeighbors(i, j);
var result:Boolean = false;
if (living && count < 2)
result = false;
if (living && (count == 2 || count == 3))
result = true;
if (living && count > 3)
result = false;
if (!living && count == 3)
result = true;
mNextCellStates[i][j] = result;
}
}
setNextState();
}
}
private function setNextState():void
{
for (var i:int = 0; i < mCellsX; i++)
{
for (var j:int = 0; j < mCellsY; j++)
{
var cell:Cell = mCells[i][j] as Cell;
cell.isAlive = mNextCellStates[i][j];
cell.update();
cell.draw();
}
}
}
private function updateCells():void
{
for (var i:int = 0; i < mCellsX; i++)
{
for (var j:int = 0; j < mCellsY; j++)
{
var cell:Cell = mCells[i][j] as Cell;
cell.update();
cell.draw();
}
}
}
private function getLivingNeighbors(x:int, y:int):int
{
var count:int = 0;
// Check cell on the right.
if (x != mCellsX - 1)
if ((mCells[x + 1][y] as Cell).isAlive)
count++;
// Check cell on the bottom right.
if (x != mCellsX - 1 && y != mCellsY - 1)
if ((mCells[x + 1][y + 1] as Cell).isAlive)
count++;
// Check cell on the bottom.
if (y != mCellsY - 1)
if ((mCells[x][y + 1] as Cell).isAlive)
count++;
// Check cell on the bottom left.
if (x != 0 && y != mCellsY - 1)
if ((mCells[x - 1][y + 1] as Cell).isAlive)
count++;
// Check cell on the left.
if (x != 0)
if ((mCells[x - 1][y] as Cell).isAlive)
count++;
// Check cell on the top left.
if (x != 0 && y != 0)
if ((mCells[x - 1][y - 1] as Cell).isAlive)
count++;
// Check cell on the top.
if (y != 0)
if ((mCells[x][y - 1] as Cell).isAlive)
count++;
// Check cell on the top right.
if (x != mCellsX - 1 && y != 0)
if ((mCells[x + 1][y - 1] as Cell).isAlive)
count++;
return count;
}
}
class SimplePoint
{
public var x:Number;
public var y:Number;
public function SimplePoint(x:Number = 0.0, y:Number = 0.0)
{
this.x = x;
this.y = y;
}
}