In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: forked from: 反応拡散系のシミュレーション

Simulation of reaction-diffusion system
Explanations: http://game.g.hatena.ne.jp/Nao_u/20100111
added wanderer : http://wonderfl.net/c/ubO1
/**
 * Copyright aobyrne ( http://wonderfl.net/user/aobyrne )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/6YjR
 */

// forked from tmrtks's forked from: 反応拡散系のシミュレーション
// 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.*;      
    import flash.utils.Timer;
    [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="30")] 
         
 
    public class ReactionDiffusionWanderer extends Sprite {      
        public function ReactionDiffusionWanderer() {      
            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);
            var timer:Timer = new Timer(100);
            timer.addEventListener(TimerEvent.TIMER, doTimer);
            timer.start();
        }      
        
        private function doTimer(e:TimerEvent):void 
        {
            var timer:Timer = e.target as Timer;
            if (timer.currentCount%200==0) 
            {
                MouseData = MouseData==3?2:3;
            }
            if (timer.currentCount%401==0) 
            {
                No++;
                //ResetCnt++;
                //RandomInit++;
                MouseData = 3;
                setFTDv(No);
            }
        }
    }      
}          
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;

var wanderer:WanderingTarget = new WanderingTarget;

function initialize():void {
    wanderer.position = new Vector3D(465 * 0.5, 465 * 0.5);
    wanderer.boundsCentre = new Vector3D(465 * 0.5, 465 * 0.5);
    wanderer.boundsRadius = 465 * 0.5;
    MouseData = 3;
    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 = 125;
            Cg = 125;
            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;
    wanderer.wander();
    wanderer.update();
    //var mx:int = Main.mouseX * BITMAP_W / SCREEN_W; 
    var mx:int = wanderer.x * BITMAP_W / SCREEN_W; 
    //var my:int = Main.mouseY * BITMAP_H / SCREEN_H; 
    var my:int = wanderer.y * 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+" md:"+MouseData+" mx:"+mx+" my:"+my;    

}   

// テクスチャ生成クラス : Class texture generation; Procedural Texture
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 );     
    }


    // 設置/消去 Erase / installation
    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;
                    }
                } 
            }
        }
    }

    // 画像の生成 Image creation
    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, c2 + (((c2*Cg)>>8)<<8) + (((c2*Cr)>>8)<<16) );  
            }
        }    
        BmpData.unlock();
    }

    // 計算 Calculation
    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;    
}  

import flash.display.DisplayObject;
import flash.geom.Matrix3D;
import flash.geom.Point;
import flash.geom.Vector3D;

import org.papervision3d.cameras.Camera3D;
import org.papervision3d.objects.DisplayObject3D;

internal class WanderingTarget extends Point
{
    /** 
     * SEE http://blog.soulwire.co.uk/laboratory/flash/as3-flocking-steering-behaviors
     * SOUL WIRE
     */
    private var _matrix : Matrix3D;
    private var _maxForce : Number;
    private var _maxSpeed : Number;
    private var _distance : Number;
    private var _drawScale : Number;
    private var _maxForceSQ : Number;
    private var _maxSpeedSQ : Number;
    private var _velocity : Vector3D;
    private var _position : Vector3D;
    private var _oldPosition : Vector3D;
    private var _acceleration : Vector3D;
    private var _steeringForce : Vector3D;
    private var _screenCoords : Point;
    private var _renderData : DisplayObject;
    private var _edgeBehavior : String;
    private var _boundsRadius : Number;
    private var _boundsCentre : Vector3D = new Vector3D();
    private var _radius : Number = 10.0;
    private var _wanderTheta : Number = 0.0;
    private var _wanderRadius : Number = 16.0;
    private var _wanderDistance : Number = 60.0;
    private var _wanderStep : Number = 0.25;
    private var _lookAtTarget : Boolean = true;
    
    protected var _config : Object = {
        minForce:3.0,
        maxForce:6.0,
        minSpeed:6.0,
        maxSpeed:12.0,
        minWanderDistance:10.0,
        maxWanderDistance:100.0,
        minWanderRadius:5.0,
        maxWanderRadius:20.0,
        minWanderStep:0.1,
        maxWanderStep:0.9,
        boundsRadius:250,
        numBoids:120
    };
    
    public function WanderingTarget()
    {
        maxForce = 4;//random(_config.minForce, _config.maxForce);
        maxSpeed = 10//;random(_config.minSpeed, _config.maxSpeed);
        _wanderDistance = 25;//random(_config.minWanderDistance, _config.maxWanderDistance);
        _wanderRadius = 15;//random(_config.minWanderRadius, _config.maxWanderRadius);
        _wanderStep = 5;//random(_config.minWanderStep, _config.maxWanderStep);
        
        super();
        reset();
        //super(fov, near, far, useCulling, useProjection);
    }
    
    /**
     * Generates a random wandering force for the Boid. 
     * The results of this method can be controlled by the 
     * _wanderDistance, _wanderStep and _wanderRadius parameters
     * 
     * @param    multiplier
     * 
     * By multiplying the force generated by this behavior, 
     * more or less weight can be given to this behavior in
     * comparison to other behaviors being calculated by the 
     * Boid. To increase the weighting of this behavior, use 
     * a number above 1.0, or to decrease it use a number 
     * below 1.0
     */
    
    public function wander( multiplier : Number = 1.0 ) : void
    {
        _wanderTheta += Math.random() * _wanderStep;
        
        if ( Math.random() < 0.5 )
        {
            _wanderTheta = -_wanderTheta;
        }
        
        var pos : Vector3D = _velocity.clone();
        
        //trace(pos)
        
        pos.normalize();
        pos.scaleBy(_wanderDistance);
        pos.incrementBy(_position);
        
        var offset : Vector3D = new Vector3D();
        
        offset.x = _wanderRadius * Math.cos(_wanderTheta);
        offset.y = _wanderRadius * Math.sin(_wanderTheta);
        //offset.z = _wanderRadius * Math.tan(_wanderTheta);
        //    trace(offset)
        //trace(_wanderRadius, _wanderTheta, pos, offset)
        _steeringForce = steer(pos.add(offset));
        
        if ( multiplier != 1.0 )
        {
            _steeringForce.scaleBy(multiplier);
        }
        //    trace(_steeringForce)
        
        _acceleration.incrementBy(_steeringForce);
    }
    
    private function steer( target : Vector3D, ease : Boolean = false, easeDistance : Number = 100 ) : Vector3D
    {
        //trace(_steeringForce,target.clone());
        
        _steeringForce = target.clone();
        _steeringForce.decrementBy(_position);
        //trace(_steeringForce,target.clone());
        _distance = _steeringForce.normalize();
        //trace('ab', _distance)
        
        if ( _distance > 0.00001 )
        {
            if ( _distance < easeDistance && ease )
            {
                _steeringForce.scaleBy(_maxSpeed * ( _distance / easeDistance ));
            }
            else
            {
                _steeringForce.scaleBy(_maxSpeed);
            }
            
            _steeringForce.decrementBy(_velocity);
            
            if ( _steeringForce.lengthSquared > _maxForceSQ )
            {
                _steeringForce.normalize();
                _steeringForce.scaleBy(_maxForce);
            }
        }
        //trace(_steeringForce)
        
        return _steeringForce;
    }
    
    public function update() : void
    {
        _oldPosition.x = _position.x;
        _oldPosition.y = _position.y;
        _oldPosition.z = _position.z;
        
        _velocity.incrementBy(_acceleration);
        
        if ( _velocity.lengthSquared > _maxSpeedSQ )
        {
            _velocity.normalize();
            _velocity.scaleBy(_maxSpeed);
        }
        
        _position.incrementBy(_velocity);
        
        x = _position.x;
        y = _position.y;
        //z = _position.z;
        
        
        _acceleration.x = 0;
        _acceleration.y = 0;
        _acceleration.z = 0;
        
        if ( isNaN(_boundsRadius) )
        {
            trace( "isNaN(_boundsRadius) : " + isNaN(_boundsRadius) );
            return;
        }
        
        if( !_position.equals(_oldPosition) )
        {
            var distance : Number = Vector3D.distance(_position, _boundsCentre);
            
            if( distance > _boundsRadius + _radius )
            {
                    
                /**
                 * Move the boid to the edge of the boundary 
                 * then invert it's velocity and step it 
                 * forward back into the sphere 
                 */
                
                _position.decrementBy(_boundsCentre);
                _position.normalize();
                _position.scaleBy(_boundsRadius + _radius);
                
                _velocity.scaleBy(-1);
                _position.incrementBy(_velocity);
                _position.incrementBy(_boundsCentre);
                    
            }
        }
    }
    
    /**
     * Resets the Boid's position, velocity, acceleration and 
     * current steering force to zero
     */
    
    public function reset() : void
    {
        _velocity = new Vector3D();
        _position = new Vector3D();
        _oldPosition = new Vector3D();
        _acceleration = new Vector3D();
        _steeringForce = new Vector3D();
        _screenCoords = new Point();
    }
    
    /**
     * The maximum force available to the Boid when
     * calculating the steering force produced by 
     * the Boids steering bahaviors
     */
    
    public function get maxForce() : Number
    {
        return _maxForce;
    }
    
    public function set maxForce( value : Number ) : void
    {
        if ( value < 0 )
        {
            value = 0;
        }
        
        _maxForce = value;
        _maxForceSQ = value * value;
    }
    
    /**
     * The maximum speed the Boid can reach
     */
    
    public function get maxSpeed() : Number
    {
        return _maxSpeed;
    }
    
    public function set maxSpeed( value : Number ) : void
    {
        if ( value < 0 )
        {
            value = 0;
        }
        
        _maxSpeed = value;
        _maxSpeedSQ = value * value;
    }
    
    protected function random( min : Number, max : Number = NaN ) : Number
    {
        if ( isNaN(max) )
        {
            max = min;
            min = 0;
        }
        
        return Math.random() * ( max - min ) + min;
    }
    
    /**
     * The centrepoint of the Boids bounding sphere.
     * If the Boid travels futher than boundsRadius 
     * from this point the specified edge behavior 
     * will take affect.
     */

    public function get boundsCentre() : Vector3D
    {
        return _boundsCentre;
    }

    public function set boundsCentre( value : Vector3D ) : void
    {
        _boundsCentre = value;
    }

    /**
     * The maximum distance which this Boid can 
     * travel from it's boundsCentre before the 
     * specified edge behavior takes affect
     */

    public function get boundsRadius() : Number
    {
        return _boundsRadius;
    }

    public function set boundsRadius( value : Number ) : void
    {
        _boundsRadius = value;
    }    
    
    public function get position():Vector3D 
    {
        return _position;
    }
    
    public function set position(value:Vector3D):void 
    {
        _position = value;
    }
}