// forked from Nao_u's 波紋+環境マップ // forked from Nao_u's テクスチャ生成実験 // // 反応拡散系のシミュレーション // // クリックで発生 // カーソルキー上下でパラメータ変更 // r でリセット // i でランダムな初期化 // // 解説など: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; var ResetCnt:int = 0; var RandomInit:int = 0; function keyCheckDown(event:KeyboardEvent):void { switch (event.keyCode){ case Keyboard.UP: No++; break; case Keyboard.DOWN: No--; break; case 82: ResetCnt++; break; case 73: RandomInit++; 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(); if(! MouseData ) return; 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 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 ); } } HeightIdxSrc1=1; HeightIdxDst=2; } public function draw():void{ for( var i:int=0; i<6; i++ ){ HeightIdxSrc1++; HeightIdxDst++; if( HeightIdxSrc1 > 2 ) HeightIdxSrc1 = 0; if( HeightIdxDst > 2 ) HeightIdxDst = 0; if( ResetCnt > 0){ reset(); ResetCnt = 0; break; } if( RandomInit > 0 ){ random_init(); RandomInit = 0; ClickCnt = 10; MouseData = 0; break; } 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; } } } // reset public function reset():void{ var idx:int, idxU:int, idxD:int, idxL:int, idxR:int; // for( var HeightIdx:int=1; HeightIdx < 3 ; HeightIdx++){ for( var x:int=0; x<Width; x++ ){ for( var y:int=0; y<Height; y++ ){ var bufU:Vector.<Number> = HeightBufU[HeightIdxDst]; var bufV:Vector.<Number> = HeightBufV[HeightIdxDst]; idx = (x+1) + (y+1)*BufWidth; bufU[idx] = 0.0; bufV[idx] = 0.0; } } // } } // random init public function random_init():void{ var v:Number = 1; var len:int = 10; var r:int = 10; var bufU:Vector.<Number> = HeightBufU[HeightIdxDst]; var bufV:Vector.<Number> = HeightBufV[HeightIdxDst]; reset(); // for( var px:int=0; px<Width; px += len ){ // for( var py:int=0; py<Height; py += len ){ for( var i:int = 0; i < 20; i++){ var px:int = Math.random() * Width; var py:int = Math.random() * Height; v = Math.random(); // r = Math.random() * 20; 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 && d > 3) { 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; bufU[idx] = 0.01; //v * 30 / (d + 1) + 0.5 ; bufV[idx] = x*x * Math.random();//7 * Math.random() + 1; } } } // len = Math.random() * 20; } // } } } 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; } forked from: 反応拡散系のシミュレーション