Beautifl - Flash Gallery

Thumbnail : 反応拡散系のシミュレーション
反応拡散系のシミュレーション
Nao_u 2010-01-12 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

// forked from Nao_u's 波紋+環境マップ
// forked from Nao_u's テクスチャ生成実験
//   
// 反応拡散系のシミュレーション
//
// クリックで発生
// カーソルキー上下でパラメータ変更
//
//
// 解説など:http://game.g.hatena.ne.jp/Nao_u/20100111
//
package {      
    import flash.display.Sprite;      
    import flash.events.*;      
    [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="30")] 
         
    public class FlashTest extends Sprite {      
        public function FlashTest() {      
            Main = this;      
            initialize(); 
            stage.addEventListener(Event.ENTER_FRAME,update);       
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyCheckDown);       
            stage.addEventListener(MouseEvent.MOUSE_UP,    MouseCheckUp);     
            stage.addEventListener(MouseEvent.MOUSE_DOWN,  MouseCheckDown);     
        }      
    }      
}          
import flash.display.*;  
import flash.events.* 
import flash.text.TextField;      
import flash.geom.*; 
import flash.utils.getTimer; 
import flash.ui.Keyboard; 
import flash.net.*;  

var Main:Sprite;      
var SCREEN_W:Number = 465; 
var SCREEN_H:Number = 465; 
var Text:TextField     

var Tex:ProcTex; 
var BITMAP_W:int = 465/2; 
var BITMAP_H:int = 465/2; 
var TexData: BitmapData;  
var loaderA:Loader;  
var loaderB:Loader;  
var bLoad:Boolean = false; 
var ClickCnt:int = 0;

var F:Number = 0.030;
var K:Number = 0.085;
var Dv:Number = 0.350;

function initialize():void {  
    Tex = new ProcTex( BITMAP_W, BITMAP_H ); 
    Tex.Bmp.x = 0; 
    Tex.Bmp.y = 0; 

   Text = new TextField();      
   Text.text = "----";    
   Text.autoSize = "left"; 
   Text.textColor = 0xFFFFFF;
   Main.addChild(Text);       
   bLoad = true; 
   setFTDv(No);
}  


var No:int = 0;
var NoMax:int = 9;
function keyCheckDown(event:KeyboardEvent):void {       
    switch (event.keyCode){       
        case Keyboard.UP:    No++; break;     
        case Keyboard.DOWN:  No--; break; 
    }      
    if( No < 0 )      No = NoMax-1; 
    if( No >= NoMax ) No = 0; 
    
    setFTDv(No);
}  

var Cr:int = 0;
var Cg:int = 0;
var Str:String = "";
function setFTDv( No:int ):void{
    switch(No){
        case 0:
            Str = "標準";
            F = 0.030;
            K = 0.085;
            Dv = 0.350;
            Cr = 0;
            Cg = 255;
            break;
        case 1:
            Str = "細胞分裂";
              F = 0.0095;
            K = 0.065;
            Dv = 0.300;
            Cr = 255;
            Cg = 128;
            break;
        case 2:
	   Str = "BZ反応風";
              F = 0.014;
            K = 0.054;
            Dv = 0.450;
            Cr = 128;
            Cg = 128;
            break;

        case 3:
            Str = "たくさんの玉が消滅しながら飛び交う";
            F = 0.01;
            K = 0.06;
            Dv = 0.45;
            Cr = 255;
            Cg = 0;
            break;

        case 4:
	   Str = "変形しながら拡大1";
            F = 0.046;
            K = 0.107;
            Dv = 0.45;
            Cr = 120;
            Cg = 135;
            break;

        case 5:
	   Str = "変形しながら拡大2";
            F = 0.03;
            K = 0.085;
            Dv = 0.55;
            Cr = 220;
            Cg = 135;
            break;

        case 6:
	   Str = "不定形・迷路";
              F = 0.04;
            K = 0.10;
            Dv = 0.45;
            Cr = 35;
            Cg = 120;
            break;


        case 7:
            Str = "粗い網目";
            F = 0.035;
            K = 0.09;
            Dv = 0.4;
            Cr = 100;
            Cg = 225;
            break;

        case 7:
            Str = "もっと粗い網目";
              F = 0.055;
            K = 0.116;
            Dv = 0.49;
            Cr = 135;
            Cg = 155;
            break;

        case 8:
            Str = "小さい迷路";
              F = 0.045;
            K = 0.105;
            Dv = 0.2;
            Cr = 105;
            Cg = 105;
            break;
    }
}

// 更新
var mxPrev:int; 
var myPrev:int; 
var Pow:Number = 1.0; 
function update(e :Event):void{      
    var time:int = getTimer();  
        
    Tex.draw(); 
    var mx:int = Main.mouseX * BITMAP_W / SCREEN_W; 
    var my:int = Main.mouseY * BITMAP_H / SCREEN_H; 
    Pow += Math.abs(mx - mxPrev) + Math.abs(my - myPrev);
    if( Pow > 1.0 ) Pow = 1.0;
    Tex.addPower( mx, my, Pow*1 );
    Pow *= 0.5;
    mxPrev = mx;
    myPrev = my;

    var endTime:int = getTimer() - time; 
//    Text.text = " 生成時間:" + endTime + "[ms]";    
    Text.text = "Type "+ No + ":"+Str+"   F="+F+"  K="+K+"  Dv="+Dv;    

}   

// テクスチャ生成クラス
class ProcTex{ 
    public var BmpData:BitmapData;  
    public var TmpBmpData:BitmapData;  
    public var Bmp:Bitmap; 
    public var Width:int; 
    public var Height:int; 
    public var HeightBufU:Array;  
    public var HeightBufV:Array;  
    public var HeightIdxDst:int;
    public var HeightIdxSrc0:int;
    public var HeightIdxSrc1:int;
    public var BufWidth:int; 
    public var BufHeight:int; 
        

    public function ProcTex( w:int, h:int ){ 
        Width = w; 
        Height = h; 
        BmpData = new BitmapData(Width, Height, false, 0xffffff);  
        Bmp = new Bitmap(BmpData);  
        Bmp.scaleX = 2.0; 
        Bmp.scaleY = 2.0; 
        Main.addChild(Bmp);       

        // バッファの生成
         HeightBufU = new Array;  
        HeightBufV = new Array;  
        BufWidth = Width+2;
        BufHeight = Height+2;
        HeightBufU[0] = new Vector.<Number>;
        HeightBufV[0] = new Vector.<Number>;
        HeightBufU[1] = new Vector.<Number>;
        HeightBufV[1] = new Vector.<Number>;
        HeightBufU[2] = new Vector.<Number>;
        HeightBufV[2] = new Vector.<Number>;
        for( var x:int=-1; x<Width+1; x++ ){  
            for( var y:int=-1; y<Height+1; y++ ){
                var idx:int = (x+1) + (y+1)*BufWidth;
                HeightBufU[0].push( 0 );
                HeightBufV[0].push( 0 );
                HeightBufU[1].push( 0 );
                HeightBufV[1].push( 0 );
                HeightBufU[2].push( 0 );
                HeightBufV[2].push( 0 );
            }
        }
        HeightIdxSrc0=0;
        HeightIdxSrc1=1;
        HeightIdxDst=2;
    } 

    public function draw():void{ 
        for( var i:int=0; i<6; i++ ){
            HeightIdxSrc0++;
            HeightIdxSrc1++;
            HeightIdxDst++;
            if( HeightIdxSrc0 > 2 ) HeightIdxSrc0 = 0;
            if( HeightIdxSrc1 > 2 ) HeightIdxSrc1 = 0;
            if( HeightIdxDst  > 2 ) HeightIdxDst  = 0;
            calc();     
        }
        createBmp( HeightIdxDst );     
    }


    // 設置/消去
    public function addPower( px:int, py:int, pow:Number ):void{ 
        if( MouseData & MOUSE_LEFT ){
            ClickCnt = 30;
        }
        var r:int = 10;
        if( ClickCnt > 0 ){
            r = 6;
            ClickCnt--;
            if( ClickCnt < 15 ) return;
        }
        var buf:Vector.<Number> = HeightBufU[HeightIdxDst];
        var buf2:Vector.<Number> = HeightBufV[HeightIdxDst];
        for( var lx:int=-r; lx<=r; lx++ ){  
            for( var ly:int=-r; ly<=r; ly++ ){
                const d:Number = Math.sqrt(lx*lx+ly*ly); 
                if (d < r) { 
                    var p:Number = Math.cos(Math.PI/2 * d/r); 
                    var x:int = px + lx;  
                    var y:int = py + ly;  
                    if( x < 0 || x >= Width || y < 0 || y >= Height ) break;
                    var idx:int = (x+1) + (y+1)*BufWidth;
                    
                    if( ClickCnt > 0 ){
                        buf[idx] += 0.01*pow * p;
                        buf2[idx] += 0.05;
                    }else{
                        buf2[idx] = 0.0;
                    }
                } 
            }
        }
    }

    // 画像の生成
    public function createBmp( idx:int ):void{ 
        var buf:Vector.<Number> = HeightBufU[HeightIdxDst];
        var buf2:Vector.<Number> = HeightBufV[HeightIdxDst];
        var col:Number, col2:Number, colU:Number, colL:Number, vecX:Number, vecY:Number; 
        var idx:int, ix:int, iy:int;
        var c:int;
        var c2:int;
        BmpData.lock();
        for( var x:int=0; x<Width; x++ ){  
            for( var y:int=0; y<Height; y++ ){
                idx = (x+1) + (y+1)*BufWidth;
                c = (buf[idx]) * 255.0;
                c2 = (buf2[idx]) * 455.0;
                if( c > 255 ) c = 255;
                if( c < 0 ) c = 0;
                if( c2 > 255 ) c2 = 255;
                if( c2 < 0 ) c2 = 0; 
                BmpData.setPixel(x, y, c + (((c2*Cg)>>8)<<8) + (((c2*Cr)>>8)<<16) );  
            }
        }    
        BmpData.unlock();
    }

    // 計算
    public function calc():void{ 
        var Du:Number = 0.99;
        var srcBuf1U:Vector.<Number> = HeightBufU[HeightIdxSrc1];
        var srcBuf1V:Vector.<Number> = HeightBufV[HeightIdxSrc1];
        var dstBufU:Vector.<Number> = HeightBufU[HeightIdxDst];
        var dstBufV:Vector.<Number> = HeightBufV[HeightIdxDst];
        var idx:int, idxU:int, idxD:int, idxL:int, idxR:int;

        var difU:Number,difV:Number;
        var cntU:Number,cntV:Number;
        var reaU:Number,reaV:Number, dd:Number;
        for( var x:int=0; x<Width; x++ ){  
            for( var y:int=0; y<Height; y++ ){
                idx  = (x+1) + (y+1)*BufWidth;
                idxU = (x+1) + (y  )*BufWidth;
                idxD = (x+1) + (y+2)*BufWidth;
                idxL = (x  ) + (y+1)*BufWidth;
                idxR = (x+2) + (y+1)*BufWidth;

                cntU = srcBuf1U[idx]
                cntV = srcBuf1V[idx]
                difU = srcBuf1U[idxU] + srcBuf1U[idxD] + srcBuf1U[idxL] + srcBuf1U[idxR];
                difV = srcBuf1V[idxU] + srcBuf1V[idxD] + srcBuf1V[idxL] + srcBuf1V[idxR];

                reaU = cntU + Du * (difU * 0.25 - cntU );
                reaV = cntV + Dv * (difV * 0.25 - cntV );
		
                dd = reaU * reaV * reaV;
                if( dd > reaU ) dd = reaU;
                reaU += -dd + F*(1-reaU);
                reaV +=  dd - K*reaV;
                if( reaV > 10 ) reaV = 10;

                dstBufU[idx] = reaU;
                dstBufV[idx] = reaV;
            }
        }    
    } 
}

var MOUSE_LEFT:int = 0x01;    
var MOUSE_LEFT_TRG:int = 0x02;    
var MouseData:int;    
function MouseCheckDown(event:MouseEvent):void{    
    MouseData |= MOUSE_LEFT;    
    MouseData |= MOUSE_LEFT_TRG;    
}             

function MouseCheckUp(event:MouseEvent):void{    
    MouseData &= ~MOUSE_LEFT;    
}             

function MouseUpdate():void{    
    MouseData &= ~MOUSE_LEFT_TRG;    
}