ライフゲーム

by shohei909 forked from 足し算をするセルオートマトン - celllular automaton do addition (diff: 479)
ライフゲーム
( http://ja.wikipedia.org/wiki/%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B2%E3%83%BC%E3%83%A0 )

SPACEを押せばライフゲーム開始
あとは,数字キーを押したり、
Zでズームしたりして遊ぶ。

LIFE GAME

start/stop: SPACE
reset: c
decel/accel: ← / →
random: x
zoom: z
stamp: 1-3
stamp reverse (x): +↑
stamp reverse (y): +↓
stamp reverse (x/y): +SHIHT
♥5 | Line 378 | Modified 2011-09-04 14:50:37 | MIT License
play

ActionScript3 source code

/**
 * Copyright shohei909 ( http://wonderfl.net/user/shohei909 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/4g7u
 */

// forked from shohei909's 足し算をするセルオートマン - celllular automaton,which do addition
package {
/*
* ライフゲーム
*     とりあえずSPACEを押せばライフゲーム開始
*    あとは,数字キーを押したり、
*    Zでズームしたりして遊ぶ。
*
* LIFE GAME
* 
* start/stop: SPACE
* reset: c
* decel/accel: ← / →
* random: x
* zoom: z
* stamp: 1-3
* stamp reverse (x): +↑
* stamp reverse (y): +↓
* stamp reverse (x/y): +SHIHT
*/
    import flash.events.KeyboardEvent;
    import flash.display.Sprite;
    import flash.events.Event;
    public class FlashTest extends Sprite {
        public var game:Game;
        public var zoom:Boolean = false;
        public var zoomX:int;
        public var zoomY:int;
        public var revX:Boolean = false;
        public var revY:Boolean = false;
        public function FlashTest() {
           game = new Game();
           stage.frameRate = 60;
           addChild(game);
           stage.addEventListener( KeyboardEvent.KEY_DOWN , onDown);
           stage.addEventListener( KeyboardEvent.KEY_UP , onUp);
           addEventListener( Event.ENTER_FRAME , onFrame);
        }
        public function onDown(e:KeyboardEvent):void{
            if(e.keyCode == 32){
                game.brain.player(null);
            }else if(e.keyCode == 67){
                game.brain.reset(null);
            }else if(e.keyCode == 88){
                game.brain.random(null);
            }else if(e.keyCode == 37){
                if(Game.SPAN < 256){Game.SPAN*=2;}
            }else if(e.keyCode == 39){
                if(Game.SPAN > 1){Game.SPAN/=2;}
            }else if(e.keyCode == 38){
                revX = true;
            }else if(e.keyCode == 40){
                revY = true;
            }else if(e.keyCode == 90 && zoom==false){
                zoom = true;
                zoomX = mouseX;
                zoomY = mouseY;
            }else if(e.keyCode >= 48 &&e.keyCode <= 57){
                //ショートカット1
                var num:int = e.keyCode-48;
                var i:int = game.brain.mouseX / Game._SCALE;
                var j:int = game.brain.mouseY  / Game._SCALE;
                if(revY){var dx:int = -1;}else{dx=1;}
                if(revX){var dy:int  = -1;}else{dy=1;}
                if(e.shiftKey){var r:Boolean  = true;}else{r=false;}
                game.brain.stamp(i,j,num,dx,dy,r);
            }
            
        }
         public function onUp(e:KeyboardEvent):void{
            if(e.keyCode == 90){
                zoom = false;
            }else if(e.keyCode == 38){
                revX = false;
            }else if(e.keyCode == 40){
                revY = false;
            }
        }
        public function onFrame(e:Event):void{
            if(zoom){
                game.scaleX = (4 + game.scaleX*7)/8;
                game.scaleY = game.scaleX;
            }else{
                game.scaleX = (1 + game.scaleX*7)/8;
                game.scaleY = game.scaleX;
            }
            
            zoomX = (31*zoomX + mouseX)/32;
            zoomY = (31*zoomY + mouseY)/32;
            game.x = zoomX - (game.scaleX * zoomX);
            game.y = zoomY - (game.scaleX * zoomY);
        }
    }
}

import flash.events.MouseEvent;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.events.Event;
import flash.display.*;
import mx.utils.*;

class Game extends Sprite{
    public static var _WIDTH:int = 116;
    public static var _HEIGHT:int = 116;
    public static var _SCALE:int = 4;
    public static var SPAN:int = 16;
    public static var ELECT:Boolean = false;
    public static var BIRTH_MIN:int = 3;
    public static var BIRTH_MAX:int = 3;
    public static var LIVE_MIN:int = 2;
    public static var LIVE_MAX:int = 3;
    
    
    
    public static var DATA:Array = [
        [[0,1,1],[1,1,0],[0,1,0]],
        [[1,0,0],[0,1,1],[1,1,0]],
        [[0,0,0,1,0],[0,0,0,0,1],[1,0,0,0,1],[0,1,1,1,1]],        
        [[0,0,1],[1,0,0,0,1],[0,0,0,0,0,1],[1,0,0,0,0,1],[0,1,1,1,1,1]],
        [[0,0,1,1],[1,0,0,0,0,1],[0,0,0,0,0,0,1],[1,0,0,0,0,0,1],[0,1,1,1,1,1,1]],
        [[1,1,1,1,1,1,1,1,1,1]],
        [
                [0,0,0,0,0,0,0,1,0],
                [0,0,0,0,0,0,1,0,1],
                [0,0,0,0,0,0,1,0,1],
                [0,0,0,0,0,0,0,1,1],
                [0,0,0,0,0,0,0,0,0,0,0,0,0,0],
                [0,0,1,1,1,0,0,0,0,0,0,1,1,0],
                [0,1,0,0,1,0,0,0,0,0,1,0,0,1],
                [0,0,1,1,0,0,0,0,0,0,1,1,1,0],
                [0,0,0,0,0,0,0,0,0,0,0,0,0,0],
                [0,0,0,0,0,0,1,1,0],
                [0,0,0,0,0,0,1,0,1],
                [0,0,0,0,0,0,1,0,1],
                [0,0,0,0,0,0,0,1,0]
        ],
        [
            [0,0,0,1,0],[0,0,0,0,1],[1,0,0,0,1],[0,1,1,1,1],
            [0],[0],[0],
            [1],[0,1,1],[0,0,1],[0,0,1],[0,1],
            [0],[0],
            [0,0,0,1,0],[0,0,0,0,1],[1,0,0,0,1],[0,1,1,1,1]
        ],
        [
            [0,0,1,0,0,0,0,1,0,0,0],
            [1,1,0,1,1,1,1,0,1,1,0],
            [0,0,1,0,0,0,0,1,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,1,1,1,1,0,1,1,0],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0]
        ],
        [
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
            [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
            [1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
            [1,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
        ]
    ];
    
    public var brain:Medium;
    public function Game():void{
        brain = new Medium();
        addChild(brain);
        addEventListener("mouseDown",onDown);
        addEventListener("enterFrame",loop);
    }
    public function onDown(e:MouseEvent):void{
        var i:int = e.target.mouseX / _SCALE;
        var j:int = e.target.mouseY  / _SCALE;
        brain.cells[i + _WIDTH*j].change(null);
    }
    private function loop(e:Event):void{
        brain.loop();
    }
}
 
class Medium extends Bitmap{
    public var w:int = 0;
    public var h:int = 0;
    public var cellSize:int = 25;
    public var play:Boolean = false;
    public var cells:Vector.<Cell>;
    public var electrons:Vector.<Electron>;
    private var count:int = 0;
    private var nowMap:BitmapData;
    
    public var eShape:EShape = new EShape();
    public function Medium(){
        w = Game._WIDTH; 
        h = Game._HEIGHT;
        cellSize = Game._SCALE;
        electrons = new Vector.<Electron>();
        cells = new Vector.<Cell>();
        for(var i:int=0;i<w;i++){
            for(var j:int=0;j<h;j++){
                cells[i*h + j] = new Cell(j,i);
            }
        }
        
        //ライフゲーム用---------------------------
        for(var n:int=0;n<w;n++){
            for(var m:int=0;m<h;m++){
                    for(var k:int= -1;k<2;k++){
                        for(var l:int= -1;l<2;l++){
                            i = n+k;
                            j = m+l;
                            if( i>=0 && i<h && (k!=0 || l!=0) ){
                                connect(n+m*w,i+j*w);
                            }
                        }
                    }
            }
        }
        
        //------------------------------------------
        
        nowMap = new BitmapData( w*cellSize+2, h*cellSize+2, false, 0x000000 );
        super(new BitmapData( w*cellSize+2, h*cellSize+2, false, 0x000000 ));
    }
    public function player(e:Event):void{ 
        play = (play == false);
    }
    public function reset(e:Event):void{
        for each(var cell:Cell in cells){
            cell.alive = false;
            cell.count = 0;
        }
    }
    public function random(e:Event):void{ 
        for(var i:int=0; i<cells.length/25; i++){
           var n:int = cells.length*Math.random();
           cells[n].alive = true;
        }
    }
    
    public function loop():void{
        drow();
        count++;
        if(count%Game.SPAN == 0 && play){
            for(var i:uint=0; i<w; i++){
                for(var j:uint=0; j<h; j++){
                    cell = cells[i+j*w];
                    if(cell.alive){
                        if(Game.ELECT){
                            for each(var syn:Synapse in cell.synapses){
                                var sx:int = (cell.x+1/2) * cellSize;
                                var sy:int = (cell.y+1/2) * cellSize;
                                var tx:int = (syn.target.x+1/2) * cellSize;
                                var ty:int = (syn.target.y+1/2) * cellSize;
                                for(var n:uint=0;n<syn.strength;n++){
                                    var el:Electron = new Electron(sx,sy,tx,ty,Game.SPAN);
                                    electrons.push(el);
                                }
                            }
                        }
                        cell.pass();
                    }
                }
            }
            for each(var cell:Cell in cells){
                cell.setting();
            }
        }
     }
     
     public function connect(st:int, en:int,s:int = 1):void{
        if(en>=0 && en < cells.length){
            cells[st].synapses.push( new Synapse(cells[en],s));
        }
     }
     public function drow():void{
        nowMap.lock();
        bitmapData.lock();
        for(var i:int=0; i<w; i++){
            for(var j:int=0; j<h; j++){
                var cell:Cell = cells[i+j*w];
                var rect:Rectangle = new Rectangle(i*cellSize+1,j*cellSize+1,cellSize-1,cellSize-1);
                if(cell.alive){
                    nowMap.fillRect(rect, cell.color);
                }else if(cell.over){        
                    nowMap.fillRect(rect, 0x191111 );
                }else{ 
                    nowMap.fillRect(rect, 0x111111);
                }
            }
        }    
        for( i=0;i< electrons.length;i++){
            var el:Electron = electrons[i];
            var mtr:Matrix = new Matrix();
            mtr.translate(el.x, el.y);
            nowMap.draw(eShape,mtr);
            if(el.life == 0){ 
                electrons.splice(i,1);
                i--;
            }else{ el.move(); }
        }
        rect = bitmapData.rect;
        var point:Point = new Point(0,0);
        var rate:uint = 0xE0;
        nowMap.unlock();
        bitmapData.merge(nowMap,rect,point,rate,rate,rate,rate);   
        nowMap.fillRect(rect,0x000000); 
        bitmapData.unlock();
    }
    public function stamp(j:int,i:int,num:int,dx:int=1,dy:int=1,rot:Boolean=false):void{
        var data:Array = Game.DATA[num];
        for(var n:int = 0; n < data.length;n++){
            for(var m:int = 0; m < data[n].length;m++){
               if(rot){
                   var an:int = m*dx+i; var am:int = n*dy+j;
               }else{
                   an= n*dx+i;am= m*dy+j;
               }
               if(an>=0 && an<w && am>=0 && am<h){
                   cells[an*h+am].alive=(data[n][m]>0);
               }
            }
        }
    }

}
 
class EShape extends Shape{
    public function EShape():void{
        filters = [new GlowFilter(0x00AAFF)];
        with(graphics){
            beginFill (0xFFFFFF, 1.0);
            drawCircle( 0, 0 ,2);
        }
    }
}

class Electron{
    public var x:int;
    public var y:int;
    public var targetX:int;
    public var targetY:int;
    public var life:int;
    
    private var r:Number;
    private var deg:Number;
    private var dv:Number;
    public function Electron(sx:int,sy:int,tx:int,ty:int,l:int){
        targetX = tx;
        targetY = ty;
        x = sx;
        y = sy;
        
        life = l;
        var lx:int = x-targetX;
        var ly:int = y-targetY;
        r = Math.sqrt( lx*lx + ly*ly)/life;
        deg = Math.atan2(ly, lx);
        dv = Math.random()*0.4-0.2;
    }
    public function move():void{
        var nr:Number = r * life;
        deg += dv;
        x = targetX + nr * Math.cos(deg);
        y = targetY + nr * Math.sin(deg);
        life--;
    }
}
class Cell{ 
    public var x:int;
    public var y:int;
    public var alive:Boolean = false;
    public var over:Boolean = false;
    public var count:int = 0;
    public var color:uint = 0;
    public var synapses:Vector.<Synapse>;
    public function Cell(px:int,py:int){
        x = px;
        y = py;
        synapses = new Vector.<Synapse>();
        changeColor();
    }
    public function changeColor():void{
        color = 0xFFFFFF*Math.random();
        color = ColorUtil.adjustBrightness2(color,-50);
        color = ColorUtil.adjustBrightness(color,100);
    }
    public function pass():void{
        changeColor();
        for each(var synapse:Synapse in synapses){synapse.pass();}
    }
    public function setting():void{
       over = (
               ( alive && (count > Game.LIVE_MAX ) ) 
               ||( (alive == false) && (count > Game.BIRTH_MAX ) ) 
           );
       alive = (
               ( alive && (count >= Game.LIVE_MIN ) && (count <= Game.LIVE_MAX ) ) 
               ||( (alive == false) && (count >= Game.BIRTH_MIN ) && (count <= Game.BIRTH_MAX ) ) 
           );
       count = 0;
       
    } 
    public function change(e:Event = null):void{
        alive = (alive == false);
    }
}
class Synapse{
    public var target:Cell;
    public var strength:int;
    public function Synapse( t:Cell, stg:int = 1){
        target=t; strength=stg;
    }
    public function pass():void{
        target.count += strength;
    }
}