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

実験中:反応拡散×STG

反応拡散系をSTGに組み込めるか確認するための実験コード。

クリックで弾を発射。Shiftを押しながらマウスを動かすと連射。
/**
 * Copyright o_healer ( http://wonderfl.net/user/o_healer )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/ojot
 */

/*
 「反応拡散もどきをSTGに応用する実験」

 概要
 ・弾で反応拡散を消すとどうなるのかの確認コード。

 動作説明
 ・マウスで弾を発射し、それが当たると周囲を消す

*/

package {
    import flash.display.*;
    import flash.events.*;
    import flash.filters.*;
    import flash.geom.*;
    import flash.net.*;
    import flash.system.*;
    import flash.text.*;
    import flash.media.*;
 
    [SWF(width="465", height="465", frameRate="30", backgroundColor="0x000000")]
    public class GameMain extends Sprite {

        //==Const==

        //サイズ
        static public const SCL:int = 2;//4;//大きくすると荒くなる(高速化される)
        static public const BMD_W:int = 465/SCL;//100;
        static public const BMD_H:int = BMD_W/2;

        //速度
        static public const SPEED:int = 1;//試行回数(何倍速で実行するか)

        //Utility
        static public const BMD_RECT:Rectangle = new Rectangle(0,0,BMD_W,BMD_H);
        static public const POS_ZERO:Point = new Point(0,0);

/*
        //拡散反応もどき:乱数バージョン
        //Alphaが大きいと離れた位置に自然発生が起こり、小さいと四角い移動パターンになる
        //Betaが大きいと広がりやすく、小さいと広がりにくい
        //再現のため、乱数に桁数制限を入れてみる
        static public const Alpha:Number = 1;//1.0 - 4.0*int(Math.random()*100)/100;//1.0~-3.0:実際には2.1~-5くらいまでOK
        //閾値
        static public const A:Number = 5;
        //上下
        static public const B:Number = 2 + Alpha;
        static public const D:Number = -0.1 - Alpha;
        //斜め
        static public const C:Number = 0.2;
        static public const E:Number = -1.2 - 0.5*Alpha;
        static public const F:Number = -1 + Alpha;

        static public const Blur:Number = 4.5;//4.5;

        //左下にデバッグ表示
        static public const DEBUG_NUMBER_LEN:int = 3;//桁数表示制限
        static public const DEBUG_STR:String =
            "A:" + A.toFixed(DEBUG_NUMBER_LEN) + "  " +
            "B:" + B.toFixed(DEBUG_NUMBER_LEN) + "  " +
            "C:" + C.toFixed(DEBUG_NUMBER_LEN) + "  " +
            "D:" + D.toFixed(DEBUG_NUMBER_LEN) + "  " +
            "E:" + E.toFixed(DEBUG_NUMBER_LEN) + "  " +
            "F:" + F.toFixed(DEBUG_NUMBER_LEN);
/*/
        static public const DEBUG_STR:String = "";
//*/

        //==Var==

        //表示用
        public var m_BitmapData_View:BitmapData;
        public var PALLETE_MAP:Array;

        //拡散反応用
        public var m_BitmapData_Data:BitmapData;
        public var m_BitmapData_Mask_Before:BitmapData;
        public var m_BitmapData_Mask_After:BitmapData;

        //弾管理用
        public var m_Layer_Bullet:Sprite = new Sprite();

        //テキスト
        public var m_Text:TextField = new TextField();

        //==Function==

        //Init
        public function GameMain():void {
            //表示用
            {
                //画像
                {
                    m_BitmapData_View = new BitmapData(BMD_W, BMD_H, false, 0x000000);
                    var bmp_view:Bitmap = new Bitmap(m_BitmapData_View);
                    bmp_view.scaleX = SCL;
                    bmp_view.scaleY = SCL;
                    addChild(bmp_view);
                }

                //Palette
                {
                    const COLOR_00:uint = 0x111111;
                    const COLOR_FF:uint = 0xCCCC33;

                    const COLOR_00_R:uint = (COLOR_00 >> 16) & 0xFF;
                    const COLOR_00_G:uint = (COLOR_00 >>  8) & 0xFF;
                    const COLOR_00_B:uint = (COLOR_00 >>  0) & 0xFF;
                    const COLOR_FF_R:uint = (COLOR_FF >> 16) & 0xFF;
                    const COLOR_FF_G:uint = (COLOR_FF >>  8) & 0xFF;
                    const COLOR_FF_B:uint = (COLOR_FF >>  0) & 0xFF;

                    const Lerp:Function = function(in_Src:uint, in_Dst:uint, in_Ratio:Number):uint{
                        return (in_Src * (1-in_Ratio)) + (in_Dst * in_Ratio);
                    };

                    PALLETE_MAP = new Array(256);
                    for(var i:int = 0; i < 256; i++){
                        var ratio:Number = i / (255.0);
                        ratio = 0.5 - 0.5*Math.cos(Math.PI*ratio);//色をややくっきり分けてみる
                        ratio = 0.5 - 0.5*Math.cos(Math.PI*ratio);//さらにくっきり
                        ratio = 0.5 - 0.5*Math.cos(Math.PI*ratio);//さらにくっきり

                        var r:uint = Lerp(COLOR_00_R, COLOR_FF_R, ratio);
                        var g:uint = Lerp(COLOR_00_G, COLOR_FF_G, ratio);
                        var b:uint = Lerp(COLOR_00_B, COLOR_FF_B, ratio);

                        PALLETE_MAP[i] = (r << 16) | (g << 8) | (b << 0);
                    }
                }
            }

            //拡散反応用
            {
                //生成
                {
                    m_BitmapData_Data = new BitmapData(BMD_W, BMD_H, false, 0x000000);
                    m_BitmapData_Mask_Before = new BitmapData(BMD_W, BMD_H, false, 0x000000);
                    m_BitmapData_Mask_After = new BitmapData(BMD_W, BMD_H, false, 0x000000);
                }

                //初期値設定
                {
/*
                    //パーリンノイズ
                    m_BitmapData_Data.perlinNoise(BMD_W, BMD_H, 2, Math.random()*100, false, true, BitmapDataChannel.BLUE);
//*/
/*
                    //完全ランダム
                    m_BitmapData_Data.noise(Math.random()*100, 0x00,0xFF, BitmapDataChannel.BLUE);
//*/
//*
                    //中央に四角
                    m_BitmapData_Data.fillRect(new Rectangle(BMD_W*3/8, BMD_H*3/8, BMD_W/4, BMD_H/4), 0x0000FF);
//*/
/*
                    //中央に四角
                    m_BitmapData_Data.fillRect(new Rectangle(BMD_W/2-1, BMD_H/2-1, 2, 2), 0x0000FF);
//*/
                }
                {//m_BitmapData_Mask_Before
                    //移動させたくない部分にFFを描いてマスク
                    var mask_shape:Shape = new Shape();
                    var mask_g:Graphics = mask_shape.graphics;
                    mask_g.lineStyle(0,0,0);
/*
                    //左上隅
                    m_BitmapData_Mask_Before.fillRect(new Rectangle(0, 0, BMD_W/5, BMD_H/5), 0x0000FF);
//*/
//*
                    //円
                    mask_g.beginFill(0x000000, 1.0);
                    mask_g.drawCircle(BMD_W/2, BMD_H/2, BMD_H/2);
                    mask_g.endFill();
                    m_BitmapData_Mask_Before.fillRect(m_BitmapData_Mask_Before.rect, 0x0000FF);
                    m_BitmapData_Mask_Before.draw(mask_shape);
//*/
                }
                {//m_BitmapData_Mask_After
                    //上のやつを足してこいつを引くが、その際に上で描いたやつが少し拡散するので、引く際も少し拡散しておく
                    const Filter_Blur:BlurFilter = new BlurFilter(2,2);
                    m_BitmapData_Mask_After.applyFilter(m_BitmapData_Mask_Before, m_BitmapData_Mask_Before.rect, POS_ZERO, Filter_Blur);
                }
            }

            //Mouse
            {
                addEventListener(
                    Event.ADDED_TO_STAGE,
                    function(e:Event):void{
                        stage.addEventListener(
                            MouseEvent.MOUSE_DOWN,
                            function(event:MouseEvent):void{
                                //弾発射
                                m_Layer_Bullet.addChild(new Bullet(mouseX, mouseY, m_BitmapData_Data));
                            }
                        );
                        stage.addEventListener(
                            MouseEvent.MOUSE_MOVE,
                            function(event:MouseEvent):void{
                                //弾発射
                                if(event.buttonDown && event.shiftKey){//Shiftを押してる間は連射
                                    m_Layer_Bullet.addChild(new Bullet(mouseX, mouseY, m_BitmapData_Data));
                                }
                            }
                        );
                    }
                );
            }

            //Bullet
            {
                addChild(m_Layer_Bullet);
            }

            //Text
            {
                m_Text.selectable = false;
                m_Text.autoSize = TextFieldAutoSize.LEFT;
                m_Text.defaultTextFormat = new TextFormat('Verdana', 12, 0x00FFFF, true);
                m_Text.text = DEBUG_STR;
                m_Text.filters = [new GlowFilter(0x000000, 1.0, 4,4, 255)];
                m_Text.x = 0;
                m_Text.y = 465 - 24;

                addChild(m_Text);
            }

            //Update
            {
                addEventListener(Event.ENTER_FRAME, Update);
            }
        }

        //Update
        public function Update(e:Event=null):void{
            //var DeltaTime:Number = 1.0 / stage.frameRate;

            //弾管理
            {
                var num:int = m_Layer_Bullet.numChildren;
                for(i = 0; i < num; i++){
                    //
                    var obj:Bullet = m_Layer_Bullet.getChildAt(i) as Bullet;

                    //更新
                    obj.Update();

                    //Kill(removeChild)があった時用の対応
                    if(obj.parent == null){//登録が解除された
                        num -= 1;//更新
                        i--;//相殺
                        continue;
                    }
                }
            }

            //拡散反応処理
            for(var i:int = 0; i < SPEED; i++){
                Update_ReactionDiffusion();
            }

            //結果を可視化
            Redraw();
        }

        //Update:拡散反応(もどき)
        public function Update_ReactionDiffusion():void{
            //ライフゲーム相当

            //基本的な考え方
            //・隣接方向には拡大しようとする(中心に近い部分はプラス)
            //・まわりを全て囲まれたら消えようとする(配列の値を全て合計したらマイナス)
/*
            //ノーマル(曲がろうとする直線メイン、分離あり)
            const A:Number = 5;
            const B:Number = 1;
            const C:Number = 0.5;
            const D:Number = -1;
            const E:Number = -0.8;
            const F:Number = 0;

            const Blur:Number = 5.0;
//*/

/*
            //やや分離ありの直角メイン
            const A:Number = 5.82;
            const B:Number = 1;
            const C:Number = 0.2;
            const D:Number = -1;
            const E:Number = -0.71;
            const F:Number = 0;

            const Blur:Number = 5.0;
//*/

/*
            //分離あり
            const A:Number = 5.82;
            const B:Number = 1.1;
            const C:Number = 0.1;
            const D:Number = -0.88;
            const E:Number = -0.80;
            const F:Number = 0;

            const Blur:Number = 5.0;
//*/

//*
            //分離・合体
            const A:Number = 5.82;
            const B:Number = 2.2;
            const C:Number = 0.2;
            const D:Number = -0.1;
            const E:Number = -1.2;
            const F:Number = -1.25;

            const Blur:Number = 4.5;
//*/

/*
            //分離・合体2
            const A:Number = 5.82;
            const B:Number = 1.692;
            const C:Number = 0.2;
            const D:Number = 0.208;
            const E:Number = 1.046;
            const F:Number = -1.303;

            const Blur:Number = 4.5;
//*/

/*
            //遠隔発生
            const A:Number = 5.82;
            const B:Number = 4.0;
            const C:Number = 0.2;
            const D:Number = -2.1;
            const E:Number = -2.2;
            const F:Number = 1.0;

            const Blur:Number = 4.5;
//*/

/*
            //四角
            const A:Number = 5.82;
            const B:Number = -2.0;
            const C:Number = 0.2;
            const D:Number = 3.9;
            const E:Number = 0.8;
            const F:Number = -5.0;

            const Blur:Number = 4.5;
//*/

/*
            //振動は残るが、反応拡散系っぽい挙動を示す
            const A:Number = 16.5;
            const B:Number = 1;
            const C:Number = -5;

            const Blur:Number = 4.1;
//*/

/*
            //序盤だけ振動するが、後半は安定
            const A:Number = 16.7;//~16.99
            const B:Number = 1;
            const C:Number = -5;

            const Blur:Number = 4.0;
//*/

/*
            //枠のまま広がる
            const A:Number = 10.7;//~10.7
            const B:Number = 1;
            const C:Number = -3.5;

            const Blur:Number = 4.0;
//*/

/*
            //
            const A:Number = 6.7;
            const B:Number = 1;
            const C:Number = -2.5;

            const Blur:Number = 4.0;
//*/

/*
            //
            const A:Number = 8.7;//~16.99
            const B:Number = 3;
            const C:Number = -5;

            const Blur:Number = 4.0;
//*/

            //Mask : Before
            m_BitmapData_Data.draw(m_BitmapData_Mask_Before, null, null, BlendMode.ADD);

            const filter_conv:ConvolutionFilter = new ConvolutionFilter(
/*
                3,3,
                [
                    C, B, C,
                    B, A, B,
                    C, B, C,
                ]
/*/
                5,5,
                [
                    F, E, D, E, F,
                    E, C, B, C, E,
                    D, B, A, B, D,
                    E, C, B, C, E,
                    F, E, D, E, F,
                ],
                1, 0, true,
                false, 0x0000FF, 1.0//画面外はFFにしておき、避けるようにする
//*/
            );
            m_BitmapData_Data.applyFilter(m_BitmapData_Data, BMD_RECT, POS_ZERO, filter_conv);

            //拡散
            const filter_blur:BlurFilter = new BlurFilter(Blur, Blur);
            m_BitmapData_Data.applyFilter(m_BitmapData_Data, BMD_RECT, POS_ZERO, filter_blur);

            //Mask : After
            m_BitmapData_Data.draw(m_BitmapData_Mask_After, null, null, BlendMode.SUBTRACT);
        }

        //Redraw
        public function Redraw():void{
            //可視化
            {
                //m_BitmapData_Dataの可視化(Src側に今回の結果がフィードバックされているものとする)
                m_BitmapData_View.paletteMap(m_BitmapData_Data, BMD_RECT, POS_ZERO, null, null, PALLETE_MAP);
            }
        }
    }
}


import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import flash.text.*;

class Bullet extends Sprite
{
    static public const BOMB_RAD:int = 8;//16;

    static public var BOMB_SPRITE:Sprite;
    static public var BOMB_SHAPE:Shape;

    public var m_BitmapData_Nrm:BitmapData;

    public function Bullet(in_X:int, in_Y:int, in_BitmapData_Nrm:BitmapData){
        //Init Static
        {
            if(BOMB_SPRITE == null){
                BOMB_SPRITE = new Sprite();

                {
                    BOMB_SHAPE = new Shape();

                    var g:Graphics = BOMB_SHAPE.graphics;
                    g.lineStyle(0,0,0);
                    g.beginFill(0x000000, 1.0);
                    g.drawCircle(0,0, BOMB_RAD);
                    g.endFill();

                    BOMB_SPRITE.addChild(BOMB_SHAPE);
                }
            }
        }

        //Param
        {
            this.x = in_X;
            this.y = in_Y;
            m_BitmapData_Nrm = in_BitmapData_Nrm;
        }

        //Graphic
        {
            var shape:Shape = new Shape();
            g = shape.graphics;
            g.lineStyle(0,0,0);
            g.beginFill(0xFFFFFF, 1.0);
            g.drawCircle(0,0, 4);
            g.endFill();
            addChild(shape);
        }
    }

    public function Update(e:Event=null):void{
        //Move
        {
            this.y -= 5;
        }

        //Check
        {
            var index_x:int = this.x / GameMain.SCL;
            var index_y:int = this.y / GameMain.SCL;

            if(m_BitmapData_Nrm.rect.contains(index_x, index_y)){
                var color:uint = m_BitmapData_Nrm.getPixel(index_x, index_y);
                if((color & 0xFF) >= 0x40){
                    //Vanish
                    BOMB_SHAPE.x = index_x; BOMB_SHAPE.y = index_y;
                    m_BitmapData_Nrm.draw(BOMB_SPRITE);
                    //Kill
                    parent.removeChild(this);
                }
            }
        }
    }
}