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

法線マップ×パズル:その1

白い玉を白いエリア(左)へ
 黒い玉を黒いエリア(右)へ
 マウスで線を描いて導く。
/**
 * 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/tXS7
 */

/*
 白い玉を白いエリア(左)へ
 黒い玉を黒いエリア(右)へ
 マウスで線を描いて導く。

 
*/

package {
    import flash.display.Sprite;
import flash.events.*;
 
    public class FlashTest extends Sprite {
        public function FlashTest() {
            // write as3 code here..
            addChild(new GameMain());
        }
    }
}

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

internal class GameMain extends Sprite{
    //==Const==

    //Constもどき(Stageの幅から再計算する)
    static public var GOAL_W:int = 100;


    //==Var==

    //法線マップ保持用(そしてそのまま描画)
    public var m_BitmapData:BitmapData;


    //==Func==

    public function GameMain(){
        //Init Later (for Using "stage" etc.)
        addEventListener(Event.ADDED_TO_STAGE, Init);
    }
    public function Init(e:Event = null):void{
        //Init Once Only
        {
            removeEventListener(Event.ADDED_TO_STAGE, Init);
        }

        var W:int = stage.stageWidth;
        var H:int = stage.stageHeight;

        //Init Param
        {
            GOAL_W = W * 1/5;
        }

        //Create Bitmap
        {
            m_BitmapData = new BitmapData(W, H, false, Vector_to_Color(new Vector3D(0,0,1)));

            addChild(new Bitmap(m_BitmapData));
        }

        //Create Goal
        {
            var bmp:Bitmap;

            //White : Left
            {
                bmp = new Bitmap(new BitmapData(GOAL_W, H, false, 0xFFFFFF));
                bmp.x = 0;
                addChild(bmp);
            }

            //Black : Right
            {
                bmp = new Bitmap(new BitmapData(GOAL_W, H, false, 0x000000));
                bmp.x = W - GOAL_W;
                addChild(bmp);
            }
        }

        //Draw Nrm By Mouse
        {
            var draw_flag:Boolean = false;

            var mouseX_Old:int = 0;
            var mouseY_Old:int = 0;

            var shape:Shape = new Shape();
            var g:Graphics = shape.graphics;
            {
                shape.filters = [
                    new BlurFilter()
                ];
            }

            //Draw
            var draw:Function = function(in_X:int, in_Y:int, in_OldX:int, in_OldY:int):void{
                //Nrm
                var vec:Vector3D;
                {
                    const BASE_Z:Number = 10.0;

                    vec = new Vector3D(
                        in_X - in_OldX,
                        -(in_Y - in_OldY),
                        BASE_Z
                    );

                    vec.normalize();
                }

                //Nrm => Color
                var nrm_color:uint;
                {
                    nrm_color = Vector_to_Color(vec);
                }

                //draw circle
                {
                    const RAD:uint = 20;

                    g.clear();
                    g.lineStyle(RAD, nrm_color, 1.0);

                    g.moveTo(in_OldX, in_OldY);
                    g.lineTo(in_X, in_Y);

                    m_BitmapData.draw(shape);
                }
            };

            //Down
            addEventListener(
                MouseEvent.MOUSE_DOWN,
                function(e:MouseEvent):void{
                    //Flag On
                    {
                        draw_flag = true;
                    }

                    //Mouse Pos
                    {
                        mouseX_Old = mouseX;
                        mouseY_Old = mouseY;
                    }

                    //Draw Nrm
                    {
                        draw(mouseX, mouseY, mouseX_Old, mouseY_Old);
                    }
                }
            );

            //Move
            stage.addEventListener(
                MouseEvent.MOUSE_MOVE,
                function(e:MouseEvent):void{
                    //Check
                    {
                        if(! draw_flag){
                            return;
                        }
                    }

                    //Draw Nrm
                    {
                        draw(mouseX, mouseY, mouseX_Old, mouseY_Old);
                    }

                    //Mouse Pos
                    {
                        mouseX_Old = mouseX;
                        mouseY_Old = mouseY;
                    }
                }
            );

            //Up
            stage.addEventListener(
                MouseEvent.MOUSE_UP,
                function(e:MouseEvent):void{
                    //Flag Off
                    {
                        draw_flag = false;
                    }
                }
            );
        }

        //Create Obj
        {
/*
            const Num:int = 100;

            for(var i:int = 0; i < Num; i++){
                addChild(new PointObject(PointObject.TYPE_WHITE, W*Math.random(), H*Math.random(), m_BitmapData));
            }
//*/

//*
            const Num:int = 10;

            const line_w:int = W*1/5;

            var vec:Vector3D = new Vector3D(0,0.5,1);
            vec.normalize();

            var rect:Rectangle = new Rectangle(0,0, W/2, H);

            var i:int;
            var line_x:int;

            //Black
            {
                line_x = W * 2/5;

                //Side
                rect.x = 0;
                m_BitmapData.fillRect(rect, Vector_to_Color(vec));

                //Obj
                for(i = 0; i < Num; i++){
                    addChild(new PointObject(PointObject.TYPE_BLACK, line_x, H * i/Num, m_BitmapData));
                }
            }

            //White
            {
                line_x = W * 3/5;

                //Line
                rect.x = W/2;
                vec.y = -vec.y;//方向反転
                m_BitmapData.fillRect(rect, Vector_to_Color(vec));

                //Obj
                for(i = 0; i < Num; i++){
                    addChild(new PointObject(PointObject.TYPE_WHITE, line_x, H * i/Num, m_BitmapData));
                }
            }
//*/
        }

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

    public function Update(e:Event):void{
    }

    //Utility
    public function Vector_to_Color(in_Nrm:Vector3D):uint{
        var color:uint;
        {//初期状態で静止可能にするため、0xFE/2が速度0の時の値になるように変更
            var r:uint = 0xFE * (0.5 + 0.5*in_Nrm.x);
            var g:uint = 0xFE * (0.5 + 0.5*in_Nrm.y);
            var b:uint = 0xFE * (0.5 + 0.5*in_Nrm.z);

            color = (r << 16) | (g << 8) | (b << 0);
        }

        return color;
    }
}

class PointObject extends Sprite
{
    //static var
    //未ゴールのObj数
    static public var m_ObjCount:int = 0;

    //const
    static public const RAD:int = 5;
    static public const VEL:int = 10;

    static public var TypeIter:int = 0;
    static public const TYPE_WHITE:int = TypeIter++;
    static public const TYPE_BLACK:int = TypeIter++;

    static public const COLOR:Array = [
        0xFFFFFF,//TYPE_WHITE
        0x000000 //TYPE_BLACK
    ];

    //var
    public var m_BitmapData:BitmapData;
    public var m_Vel:Vector3D = new Vector3D(0, 0);
    public var m_Type:int = TYPE_WHITE;

    //Init
    public function PointObject(in_Type:int, in_X:int, in_Y:int, in_BitmapData:BitmapData){
        //Count++
        {
            m_ObjCount++;
        }

        //Type
        {
            m_Type = in_Type;
        }

        //Pos
        {
            this.x = in_X;
            this.y = in_Y;
        }

        //Nrm
        {
            m_BitmapData = in_BitmapData;
        }

        //Graphic
        {
            var shape:Shape = new Shape();
            {//Draw Circle
                var g:Graphics = shape.graphics;
                g.beginFill(COLOR[m_Type], 1.0);
                g.drawCircle(0, 0, RAD);
            }
            {//Add Filter
                shape.filters = [
                    new BlurFilter(),
                    new GlowFilter(COLOR[m_Type])
                ];
            }

            addChild(shape);
        }

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

    public function Update(e:Event=null):void{
        //法線マップから得られる速度
        var NrmVel:Vector3D;
        {
            NrmVel = Color_to_Vector(m_BitmapData.getPixel(this.x, this.y));
            NrmVel.scaleBy(VEL);
        }

        //現在の速度とマージ
        {
            // var ratio:Number = 0.1;
            var ratio:Number = 1 - NrmVel.z/VEL;//速度指定がないようなら今の速度を維持する

            m_Vel.x = lerp(m_Vel.x, NrmVel.x, ratio);
            m_Vel.y = lerp(m_Vel.y, NrmVel.y, ratio);
        }

        //Move
        {
            this.x += m_Vel.x;
            this.y += m_Vel.y;

            if(this.x < 0){this.x += m_BitmapData.width;}
            if(this.x >= m_BitmapData.width){this.x -= m_BitmapData.width;}
            if(this.y < 0){this.y += m_BitmapData.height;}
            if(this.y >= m_BitmapData.height){this.y -= m_BitmapData.height;}
        }

        //Check Goal
        {
            var GoodEndFlag:Boolean = false;
            var BadEndFlag:Boolean = false;
            {
                //判定はGameMain側でやるべき気がするが
                if(this.x < GameMain.GOAL_W){
                    switch(m_Type){
                    case TYPE_WHITE:
                        //White : Left
                        GoodEndFlag = true;
                        break;
                    case TYPE_BLACK:
                        //Black : Right
                        BadEndFlag = true;//逆サイドに入ってしまった
                        break;
                    }
                }
                if(this.x > stage.stageWidth - GameMain.GOAL_W){
                    switch(m_Type){
                    case TYPE_WHITE:
                        //White : Left
                        BadEndFlag = true;//逆サイドに入ってしまった
                        break;
                    case TYPE_BLACK:
                        //Black : Right
                        GoodEndFlag = true;
                        break;
                    }
                }
            }

            if(GoodEndFlag){//ゴールに入った
                //Kill(相当)
                {
                    parent.removeChild(this);
                    removeEventListener(Event.ENTER_FRAME, Update);
                }

                //Count--
                {
                    m_ObjCount--;

                    if(m_ObjCount == 0){
                        //全てOBJがゴールしたらクリア処理

                        //めんどうだからもらったBitmapDataにらくがきしてしらせちゃえー
                        var shape:Shape = new Shape();
                        var g:Graphics = shape.graphics;
                        g.lineStyle(10, 0xFFFFFF, 1.0);
                        g.drawCircle(m_BitmapData.width/2, m_BitmapData.height/2, 100);
                        m_BitmapData.draw(shape);
                    }
                }
            }else{
                if(BadEndFlag){//逆サイドに入ってしまった
                    //めんどうなのでUpdateしないだけにする
                    removeEventListener(Event.ENTER_FRAME, Update);
                }
            }
        }
    }

    //Utility
    public function Color_to_Vector(in_Color:uint):Vector3D{
        var dir:Vector3D;
        {
            dir = new Vector3D(
                2 * ((in_Color >> 16) & 0xFF) / 254.0 - 1,
                -(2 * ((in_Color >>  8) & 0xFF) / 254.0 - 1),
                2 * ((in_Color >>  0) & 0xFF) / 254.0 - 1
            );
        }

        return dir;
    }

    public function lerp(in_Src:Number, in_Dst:Number, in_Ratio:Number):Number{
        return (in_Src * (1 - in_Ratio)) + (in_Dst * in_Ratio);
    }
}