/**
* Copyright krogue ( http://wonderfl.net/user/krogue )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/cJXU
*/
// todo: ランダム配置ボタン
// note: gameのstep使ってない
package {
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.Stage;
import flash.display.SimpleButton;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class Life extends Sprite {
private var isMouseDown:Boolean = false;
private var timer:Timer;
private var game:LifeGameSprite;
private var start:TextField; // start/stop button
private var reset:TextField; // reset button
private var label:TextField;
public function Life() {
// timer
timer = new Timer(500);
// game
game = addChild(new LifeGameSprite(20, 20, 12)) as LifeGameSprite;
game.x = 100;
game.y = 0;
game.draw();
// start/stop button
start = addChild(createTextField("START", 1, 0)) as TextField;
// reset button
reset = addChild(createTextField("RESET", 1, 23)) as TextField;
// label
var text:String = "timer:" + timer.currentCount + "\ncount:" + game.count;
label = addChild(createTextField(text, 2, 46)) as TextField;
// event
timer.addEventListener(TimerEvent.TIMER, timerHandler);
start.addEventListener(MouseEvent.CLICK, startClickHandler);
reset.addEventListener(MouseEvent.CLICK, resetClickHandler);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
private function createTextField(text:String, lines:Number, y:Number):TextField {
var textFormat:TextFormat = new TextFormat();
textFormat.align = TextFormatAlign.CENTER;
textFormat.size = 12;
textFormat.font = "Verdana";
var textField:TextField = new TextField();
textField.defaultTextFormat = textFormat;
textField.text = text;
textField.border = true;
textField.width = 80;
textField.height = 18 * lines;
textField.x = 0;
textField.y = y;
textField.selectable = false;
return textField;
}
private function timerHandler(event:TimerEvent):void {
if (timer.currentCount >= 99999) {
timer.stop();
}
this.game.next();
label.text = "timer:" + timer.currentCount + "\ncount:" + game.count;
}
private function startClickHandler(event:MouseEvent):void {
if (timer.running) {
start.text = "START";
timer.stop();
} else {
start.text = "STOP";
timer.start();
}
}
private function resetClickHandler(event:MouseEvent):void {
timer.reset();
game.reset();
start.text = "START";
label.text = "timer:" + timer.currentCount + "\ncount:" + game.count;
}
private function mouseDownHandler(event:MouseEvent):void {
if (!timer.running && !isMouseDown) {
isMouseDown = true;
this.game.click(event.stageX, event.stageY);
}
}
private function mouseUpHandler(event:MouseEvent):void {
isMouseDown = false;
}
private function mouseMoveHandler(event:MouseEvent):void {
if (!timer.running && isMouseDown) {
this.game.click(event.stageX, event.stageY);
}
}
private function enterFrameHandler(event:Event):void {
this.game.draw();
}
}
}
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.Graphics;
class LifeGameSprite extends Sprite {
private var step:Number; // next 実行回数
private var lines:Array; // Cell からなる2次元配列
public function LifeGameSprite(cols:uint, rows:uint, size:Number) {
var margin:int = size / 3;
var lines:Array = new Array();
for (var row:int = 0; row < rows; row++) {
var line:Array = new Array();
for (var col:int = 0; col < cols; col++) {
var cell:Cell = new Cell(size, false);
cell.x = col * (size + margin);
cell.y = row * (size + margin);
line.push(cell);
addChild(cell); // 子にも追加
}
lines.push(line)
}
this.lines = lines;
this.step = 0;
}
public function draw():void {
lines.forEach(function(line:*, row:int, lines:Array):void {
line.forEach(function(cell:*, col:int, line:Array):void {
cell.draw();
}, this);
}, this);
}
// クリックされたCellを誕生させる
public function click(stageX:Number, stageY:Number):void {
lines.forEach(function(line:*, row:int, lines:Array):void {
line.forEach(function(cell:*, col:int, line:Array):void {
if (cell.hitTestPoint(stageX, stageY)) {
cell.live = true;
}
}, this);
}, this);
}
public function reset():void {
// lines のリセット
lines.forEach(function(line:*, row:int, lines:Array):void {
line.forEach(function(cell:*, col:int, line:Array):void {
cell.live = false;
}, this);
}, this);
// step のリセット
this.step = 0;
}
public function next():void {
// 生きているかのみを格納した配列の作成(状態更新の準備)
var afterLines:Array = lines.map(function(line:*, row:int, lines:Array):Array {
return line.map(function(cell:*, col:int, line:Array):Boolean {
// 周囲の生存数を取得
var liveCount:int = 0;
var pline:Array = lines[row - 1];
var nline:Array = lines[row + 1];
if (pline) {
if (pline[col - 1] && pline[col - 1].live) liveCount++;
if (pline[col + 0] && pline[col + 0].live) liveCount++;
if (pline[col + 1] && pline[col + 1].live) liveCount++;
}
if (line[col - 1] && line[col - 1].live) liveCount++;
if (line[col + 1] && line[col + 1].live) liveCount++;
if (nline) {
if (nline[col - 1] && nline[col - 1].live) liveCount++;
if (nline[col + 0] && nline[col + 0].live) liveCount++;
if (nline[col + 1] && nline[col + 1].live) liveCount++;
}
// 周囲の生存数が、3個なら無条件に生存、2個かつ生存でも生存、それ以外は死亡
return ((liveCount == 3) || (liveCount == 2 && cell.live));
}, this);
}, this);
// 状態の更新
lines.forEach(function(line:*, row:int, lines:Array):void {
line.forEach(function(cell:*, col:int, line:Array):void {
cell.live = afterLines[row][col];
}, this);
}, this);
}
public function get count():Number {
var count:Number = 0;
lines.forEach(function(line:*, row:int, lines:Array):void {
line.forEach(function(cell:*, col:int, line:Array):void {
count += (cell.live ? 1 : 0);
}, this);
}, this);
return count;
}
}
// getter/setter を使ってみた
class Cell extends Shape {
private var _live:Boolean;
private var size:Number;
public function Cell(size:Number, live:Boolean=true) {
this.size = size;
_live = live;
}
public function get live():Boolean {
return _live;
}
public function set live(value:Boolean):void {
_live = value;
}
public function draw():void {
graphics.clear();
graphics.lineStyle(1, 0x000000);
graphics.beginFill(0x000000, (_live ? 0.5 : 0));
graphics.drawRect(0, 0, size, size);
graphics.endFill();
}
}