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

砂鮫

ブロックの中を泳ぐAct(の試作)
Get Adobe Flash player
by o_healer 05 Oct 2010
/**
 * 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/iLmJ
 */

/*
 「砂ザメ」
 ・壁を潜るアクションゲーム
  ・の試作

 概要
 ・たまに「砂漠で泳ぐサメ」という敵をみかけるよね
  ・ということで、ブロックを泳ぐナニカを作ってみた

 操作方法
 ・十字キー
  ・移動(空中では入力がほぼきかない)

 その他
 ・特にゴールはないぞ!
  ・飽きた時が終わる時だぞ!
 ・ForkしてMAPをいじればステージエディットできるけど、面白いのは作りにくいぞ!
  ・トゲブロックに対応してないから幅も狭いぞ!
 ・プレイヤーのグラフィックがしょぼいのは目を瞑るんだぞ!
  ・サメの絵なんて描けないぞ!
 ・できれば「ヒレ」を使ったアクションを組み込みたかったけど今回は保留だぞ!
  ・ヒレで「斬る」とか「運ぶ」とかできそうだけど余裕がないぞ!
*/


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

        //==Const==

//*
        static public const URL_BLOCKS:String = "http://assets.wonderfl.net/images/related_images/f/fc/fc7a/fc7aa813ed7e2cc347cf70a6588198d5ab165cfd";
        static public const URL_PLAYER:String = "http://assets.wonderfl.net/images/related_images/f/f2/f288/f288385987606d20278a44bf9b826d43ff74f971";
/*/
        static public const URL_BLOCKS:String = "Blocks.png";
        static public const URL_PLAYER:String = "Player.png";
//*/
        //マップ
        static public var m_MapIter:int = 0;
        static public const O:int = m_MapIter++;//空白
        static public const W:int = m_MapIter++;//壁
        static public const X:int = m_MapIter++;//トゲ(未対応)
        static public const P:int = m_MapIter++;//プレイヤー

        static public const MAP:Array = [
            [O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, W, W, O, W, W, W, W, W, O, O, O, O, O, O, O, O],
            [O, O, O, O, P, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, W, W, O, W, W, W, W, W, O, O, O, O, O, O, O, O],
            [O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
            [O, O, O, W, W, W, O, O, O, O, O, O, O, W, W, O, O, W, W, O, O, O, O, O, O, W, W, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
            [O, O, O, O, O, O, O, O, O, O, O, O, O, W, W, O, O, W, W, O, O, O, O, O, O, W, W, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
            [O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, W, O],
            [O, W, W, W, W, W, W, W, W, W, W, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, W, O, O],
            [O, W, W, W, W, W, W, W, W, W, W, O, O, W, W, W, W, W, W, O, O, O, O, O, O, W, W, O, O, O, O, O, O, O, O, O, O, W, O, O, O],
            [O, W, W, W, W, W, O, O, O, W, W, O, O, W, W, W, W, W, W, O, O, O, O, O, O, W, W, O, O, O, O, O, O, O, O, O, W, O, O, O, O],
            [O, W, W, W, W, W, O, O, O, W, W, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, W, O, O, O, O, W, O, O, O, O, O],
            [O, W, W, W, W, W, O, O, O, W, W, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, W, O, O, O, W, O, O, O, O, O, O],
            [O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, O, O, W, W, W, W, W, W, O, O, W, W, O, O, O, W, O, O, W, O, O, O, O, O, O, O],
            [O, W, W, W, W, W, W, W, W, W, W, W, W, W, W, O, O, W, W, W, W, W, W, O, O, W, W, O, O, O, W, W, W, O, O, O, O, O, O, O, O],
            [O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
            [O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O],
        ];

        //1マスの大きさ
        static public const PANEL_LEN:int = 32;

        //マップのサイズ
        static public const MAP_NUM_X:int = MAP[0].length;
        static public const MAP_NUM_Y:int = MAP.length;

        //マップの大きさ
        static public const MAP_W:int = PANEL_LEN * MAP_NUM_X;
        static public const MAP_H:int = PANEL_LEN * MAP_NUM_Y;


        //==Var==

        //Pseudo Singleton
        static public var Instance:GameMain;

        //レイヤー
        public var m_Layer_Root:Sprite = new Sprite();
        public var  m_Layer_BG:Sprite = new Sprite();
        public var  m_Layer_Player:Sprite = new Sprite();
        public var  m_Layer_Block:Sprite = new Sprite();

        //画像
        public var m_BitmapData_BG:BitmapData = new BitmapData(MAP_W, MAP_H, false, 0x000000);
        public var m_BitmapData_Block:BitmapData = new BitmapData(MAP_W, MAP_H, true, 0x00000000);

        //プレイヤー
        public var m_Player:Player = new Player();


        //==Function==

        //Init
        public function GameMain():void {
            //Pseudo Singleton
            {
                Instance = this;
            }

            //Layer
            {
                //Root
                addChild(m_Layer_Root);

                {
                    //背景
                    m_Layer_Root.addChild(m_Layer_BG);

                    //ブロック
                    m_Layer_Root.addChild(m_Layer_Block);

                    //プレイヤー
                    m_Layer_Root.addChild(m_Layer_Player);
                }
            }

            //背景
            {
                m_Layer_BG.addChild(new Bitmap(m_BitmapData_BG));
            }

            //ブロック
            {
                m_Layer_Block.addChild(new Bitmap(m_BitmapData_Block));
            }

            //プレイヤー
            {
                m_Layer_Player.addChild(m_Player);
            }

            //MAPに応じた処理
            {
                var rect:Rectangle = new Rectangle(0,0, PANEL_LEN,PANEL_LEN);
                for(var y:int = 0; y < MAP_NUM_Y; y++){
                    rect.y = y * PANEL_LEN;
                    for(var x:int = 0; x < MAP_NUM_X; x++){
                        rect.x = x * PANEL_LEN;

                        switch(MAP[y][x]){
                        case W:
                            //ロード前用の仮描画
                            m_BitmapData_Block.fillRect(rect, 0xFF444444);
                            break;
                        case P:
                            //プレイヤーの位置指定
                            m_Player.SetPos(
                                (x+0.5) * PANEL_LEN,
                                (y+0.5) * PANEL_LEN
                            );
                            break;
                        }
                    }
                }
            }

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

            //画像ロード開始
            {
                const LoadFunc:Function = function(in_URL:String, in_OnLoad:Function):void{
                    var loader:Loader = new Loader();
                    loader.load(new URLRequest(in_URL), new LoaderContext(true));//画像のロードを開始して
                    loader.contentLoaderInfo.addEventListener(
                        Event.COMPLETE,//ロードが完了したら
                        function(e:Event):void{
                            in_OnLoad(loader.content);//初期化に入る
                        }
                    );
                }

                LoadFunc(URL_BLOCKS, OnLoadEnd_Blocks);
                LoadFunc(URL_PLAYER, OnLoadEnd_Player);
            }
        }

        public function OnLoadEnd_Blocks(in_Graphic:DisplayObject):void{
            //Init ImageManager
            {
                ImageManager.Init(in_Graphic);//それを保持した後
            }

            //背景描画
            {
                ImageManager.DrawBG(MAP_NUM_X, MAP_NUM_Y, m_BitmapData_BG);
            }

            //ブロック描画
            {
                ImageManager.DrawBlocks(MAP, m_BitmapData_Block);
            }
        }

        public function OnLoadEnd_Player(in_Graphic:DisplayObject):void{
            //プレイヤー
            {
                //Clear
                m_Player.m_BitmapData_Player.fillRect(m_Player.m_BitmapData_Player.rect, 0x00000000);
                //Draw
                m_Player.m_BitmapData_Player.draw(in_Graphic);
            }
        }

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

            //Player
            {
                m_Player.Update(DeltaTime);
            }

            //Camera
            {
                Update_Camera();
            }
        }

        //Update : Camera
        public function Update_Camera():void{
            var CAMERA_W:int = stage.stageWidth;
            var CAMERA_H:int = stage.stageHeight;

            var PlayerX:int = m_Player.x;
            var PlayerY:int = m_Player.y;

            var CameraLX:int = PlayerX - CAMERA_W*0.5;
            var CameraUY:int = PlayerY - CAMERA_H*0.5;

            var RootX:int;
            {
                RootX = -CameraLX;
                if(RootX < -MAP_W + CAMERA_W){
                    RootX = -MAP_W + CAMERA_W;
                }
                if(RootX > 0){
                    RootX = 0;
                }
            }

            var RootY:int;
            {
                RootY = -CameraUY;
                if(RootY < -MAP_H + CAMERA_H){
                    RootY = -MAP_H + CAMERA_H;
                }
                if(RootY > 0){
                    RootY = 0;
                }
            }

            m_Layer_Root.x = RootX;
            m_Layer_Root.y = RootY;
        }
    }
}


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


class Player extends Sprite
{
    //==Const==

    //移動まわりのパラメータ
    static public const VEL:Number = 250.0;
    static public const GRAVITY:Number = 250.0;

    //湾曲まわりのパラメータ
    static public const DIS_RAD:int = GameMain.PANEL_LEN*2;

    //入力方向(下のマッピングに対応する形)
    static public const INPUT_DIR_LU:int = 0;
    static public const INPUT_DIR_U:int  = 1;
    static public const INPUT_DIR_RU:int = 2;
    static public const INPUT_DIR_L:int  = 3;
    static public const INPUT_DIR_C:int  = 4;
    static public const INPUT_DIR_R:int  = 5;
    static public const INPUT_DIR_LD:int = 6;
    static public const INPUT_DIR_D:int  = 7;
    static public const INPUT_DIR_RD:int = 8;

    //入力の方向から速度へのマッピング
    static public const INPUT_to_VEL:Array = [
        new Point(-VEL / Math.sqrt(2), -VEL / Math.sqrt(2)),  new Point(0, -VEL),  new Point(VEL / Math.sqrt(2), -VEL / Math.sqrt(2)),
        new Point(-VEL,                 0),                   new Point(0,  0),    new Point(VEL,                 0),
        new Point(-VEL / Math.sqrt(2),  VEL / Math.sqrt(2)),  new Point(0,  VEL),  new Point(VEL / Math.sqrt(2),  VEL / Math.sqrt(2)),
    ];

    //Utility
    static public const POS_ZERO:Point = new Point(0,0);

    //==Var==

    //移動まわりのパラメータ
    public var m_Pos:Point = new Point(0,0);
    public var m_Vel:Point = new Point(0,0);

    //入力
    public var m_InputL:Boolean = false;
    public var m_InputR:Boolean = false;
    public var m_InputU:Boolean = false;
    public var m_InputD:Boolean = false;

    //プレイヤーのオリジナル画像
    public var m_BitmapData_Player:BitmapData = new BitmapData(3*24, GameMain.PANEL_LEN, true, 0x00000000);

    //プレイヤーの回転込み画像
    public var m_Graphic_Player:Sprite = new Sprite();

    //画像(湾曲したブロック込み)
    public var m_BitmapData:BitmapData = new BitmapData(2*DIS_RAD, 2*DIS_RAD, true, 0x00000000);

    //歪ませフィルター
    public var m_DispFilter:DisplacementMapFilter;

    //処理用内部変数
    public var m_BitmapData_Disp:BitmapData = new BitmapData(2*DIS_RAD, 2*DIS_RAD, true, 0x00000000);
    public var rect:Rectangle = new Rectangle(0,0, 2*DIS_RAD,2*DIS_RAD);
    public var mtx:Matrix = new Matrix(1,0,0,1, DIS_RAD-GameMain.PANEL_LEN/2, DIS_RAD-GameMain.PANEL_LEN/2);
    public var m_Rot:Number = Math.PI;


    //==Function==

    //Init
    public function Player(){
        //Input
        {
            addEventListener(
                Event.ADDED_TO_STAGE,//ステージに追加されたら
                function(e:Event):void{
                    //キー入力を見る
                    stage.addEventListener(KeyboardEvent.KEY_DOWN, OnKeyDown);
                    stage.addEventListener(KeyboardEvent.KEY_UP, OnKeyUp);
                }
            );
        }

        //プレイヤーグラフィックの仮画像
        {
            var shape:Shape = new Shape();
            var g:Graphics = shape.graphics;
            g.lineStyle(0,0,0);
            g.beginFill(0x000088, 1.0);
            g.drawCircle(24*3/2, GameMain.PANEL_LEN/2, GameMain.PANEL_LEN/4);
            g.endFill();
            m_BitmapData_Player.draw(shape);
        }

        //表示画像の登録
        {
            var bmp:Bitmap = new Bitmap(m_BitmapData);
            bmp.x = -DIS_RAD;
            bmp.y = -DIS_RAD;
            addChild(bmp);
        }

        //計算しやすいように、中心位置を保持したものを作成
        {
            var bmp_ori:Bitmap = new Bitmap(m_BitmapData_Player);
            bmp_ori.x = -24 * 3/2;
            bmp_ori.y = -GameMain.PANEL_LEN/2;
            m_Graphic_Player.addChild(bmp_ori);
        }

        //歪み
        {
            //オフセットから色を計算
            const calc_color:Function = function(in_GapX:int, in_GapY:int):uint{
                var r:uint = 0x00;
                var g:uint = 0x80 + in_GapX;
                var b:uint = 0x80 + in_GapY;
                return (r << 16) | (g << 8) | (b << 0);
            };

            //オフセット値を格納したBitmap
            var bmd_sampling:BitmapData = new BitmapData(2*DIS_RAD, 2*DIS_RAD, false, calc_color(0,0));

            //歪めるための計算
            for(var y:int = 0; y < 2*DIS_RAD; y++){
                var GapY:int = (2*DIS_RAD-1)/2 - y;
                for(var x:int = 0; x < 2*DIS_RAD; x++){
                    var GapX:int = (2*DIS_RAD-1)/2 - x;
                    var distance:Number = Math.sqrt(GapX*GapX + GapY*GapY);

                    if(distance < DIS_RAD){
                        var ratio:Number = 1 - distance/DIS_RAD;
                        //ratio = 0.5 - 0.5*Math.cos(Math.PI * ratio);
                        ratio = 0.5 *(0.5 - 0.5*Math.cos(Math.PI * ratio));
                        bmd_sampling.setPixel(x, y, calc_color(GapX*ratio, GapY*ratio));
                    }
                }
            }

            m_DispFilter = new DisplacementMapFilter(
                bmd_sampling,//Sampling : Bitmap
                null,//Sampling : Point
                BitmapDataChannel.GREEN,//X
                BitmapDataChannel.BLUE,//Y
                0x100,//ScaleX
                0x100,//ScaleY
                DisplacementMapFilterMode.COLOR,//Mode
                0x000000,//color
                0//alpha
            );
        }
    }

    //Init : Pos
    public function SetPos(in_X:int, in_Y:int):void{
        this.x = m_Pos.x = in_X;
        this.y = m_Pos.y = in_Y;
    }

    //Update : Input
    private function OnKeyDown(event:KeyboardEvent):void{
        if(event.keyCode == Keyboard.LEFT){    m_InputL = true;}
        if(event.keyCode == Keyboard.RIGHT){m_InputR = true;}
        if(event.keyCode == Keyboard.UP){    m_InputU = true;}
        if(event.keyCode == Keyboard.DOWN){    m_InputD = true;}
    }
    private function OnKeyUp(event:KeyboardEvent):void{
        if(event.keyCode == Keyboard.LEFT){    m_InputL = false;}
        if(event.keyCode == Keyboard.RIGHT){m_InputR = false;}
        if(event.keyCode == Keyboard.UP){    m_InputU = false;}
        if(event.keyCode == Keyboard.DOWN){    m_InputD = false;}
    }

    //Update
    public function Update(in_DeltaTime:Number):void{
        //移動
        Update_Move(in_DeltaTime);

        //描画(歪み含む)
        Redraw();
    }

    //Update : Move
    public function Update_Move(in_DeltaTime:Number):void{
        //壁の中に居るか
        var IsInWall:Boolean = false;//デフォルト:範囲外の時の値
        {
            var IndexX:int = m_Pos.x / GameMain.PANEL_LEN;
            var IndexY:int = m_Pos.y / GameMain.PANEL_LEN;

            if(0 <= IndexX && IndexX < GameMain.MAP_NUM_X){
                if(0 <= IndexY && IndexY < GameMain.MAP_NUM_Y){
                    if(GameMain.MAP[IndexY][IndexX] == GameMain.W){
                        IsInWall = true;
                    }
                }
            }
        }

        //入力による制御
        {
            //入力方向
            var InputDir:int = INPUT_DIR_C;
            {
                if(m_InputL){InputDir -= 1;}
                if(m_InputR){InputDir += 1;}
                if(m_InputU){InputDir -= 3;}
                if(m_InputD){InputDir += 3;}
            }

            //目標速度ベクトル
            var TrgVel:Point = INPUT_to_VEL[InputDir];

            //入力の採用率
            var Ratio:Number;
            if(IsInWall){
                if(InputDir == INPUT_DIR_C){//無入力の時だけ、慣性を優先する
                    Ratio = 0.2;
                }else{
                    Ratio = 0.3;
                }
            }else{
                Ratio = 0.005;//空中ではほぼ制御不能
            }

            //速度変更
            m_Vel.x = (m_Vel.x * (1 - Ratio)) + (TrgVel.x * Ratio);
            m_Vel.y = (m_Vel.y * (1 - Ratio)) + (TrgVel.y * Ratio);
        }

        //壁の外:勢いのまま重力で落下
        if(! IsInWall){
            m_Vel.y += GRAVITY * in_DeltaTime;
        }

        //移動
        {
            m_Pos.x += m_Vel.x * in_DeltaTime;
            m_Pos.y += m_Vel.y * in_DeltaTime;

            this.x = m_Pos.x;
            this.y = m_Pos.y;
        }

        //Aim
        {
            const HALF_AIM_VEL:Number = 10.0;//この速度の時Ratioが半分になる(不要っぽい)

            var VelLen:Number = m_Vel.length;
            if(VelLen > 0.1){
                var AimRatio:Number = 1;//1 - HALF_AIM_VEL/(HALF_AIM_VEL + VelLen);

                var TrgRot:Number = Math.atan2(m_Vel.x, -m_Vel.y);
                if(TrgRot < m_Rot-Math.PI){TrgRot += Math.PI;}
                if(TrgRot > m_Rot+Math.PI){TrgRot -= Math.PI;}

                m_Rot = (TrgRot * AimRatio) + (m_Rot * (1 - AimRatio));

                mtx.a =  Math.cos(m_Rot); mtx.b = Math.sin(m_Rot); mtx.tx = DIS_RAD;
                mtx.c = -Math.sin(m_Rot); mtx.d = Math.cos(m_Rot); mtx.ty = DIS_RAD;
            }
        }
    }

    //Redraw
    public function Redraw():void{
        //ブロック画像を歪ませたものを描画
        {
            //ブロック画像
            var bmd_block:BitmapData = GameMain.Instance.m_BitmapData_Block;

            //歪ませる部分をコピー
            rect.x = this.x - DIS_RAD;
            rect.y = this.y - DIS_RAD;
            m_BitmapData_Disp.copyPixels(bmd_block, rect, POS_ZERO);

            //歪ませる
            m_BitmapData_Disp.applyFilter(m_BitmapData_Disp, bmd_block.rect, POS_ZERO, m_DispFilter);
        }

        //
        {
            //Clear
/*
            //透明→これだと元のブロックが残っておかしくなる
            m_BitmapData.fillRect(m_BitmapData.rect, 0x00000000);
/*/
            //背景でClear(余分なブロックを背景で塗りつぶす)
            var bmd_bg:BitmapData = GameMain.Instance.m_BitmapData_BG;
            m_BitmapData.copyPixels(bmd_bg, rect, POS_ZERO);
//*/

            //本体描画
            m_BitmapData.draw(m_Graphic_Player, mtx);

            //歪ませたブロックで上書き
            m_BitmapData.draw(m_BitmapData_Disp);
        }
    }
}


class ImageManager
{
    //==Const==

    //#Graphic
    static public var m_GraphicIndexIter:int = 0;

    static public const GRAPHIC_INDEX_BG:int            = m_GraphicIndexIter++;

    static public const GRAPHIC_INDEX_WALL:int            = m_GraphicIndexIter++;
    static public const GRAPHIC_INDEX_WALL_X:int        = m_GraphicIndexIter++;
    static public const GRAPHIC_INDEX_WALL_Y:int        = m_GraphicIndexIter++;
    static public const GRAPHIC_INDEX_WALL_XorY:int        = m_GraphicIndexIter++;
    static public const GRAPHIC_INDEX_WALL_XandY:int    = m_GraphicIndexIter++;

    static public const GRAPHIC_INDEX_NEEDLE:int        = m_GraphicIndexIter++;
    static public const GRAPHIC_INDEX_NEEDLE_X:int        = m_GraphicIndexIter++;
    static public const GRAPHIC_INDEX_NEEDLE_Y:int        = m_GraphicIndexIter++;
    static public const GRAPHIC_INDEX_NEEDLE_XY:int        = m_GraphicIndexIter++;

    static public const GRAPHIC_INDEX_NUM:int            = m_GraphicIndexIter;


    //#enum:Quater
    static public const LU:int = 0;
    static public const RU:int = 1;
    static public const LD:int = 2;
    static public const RD:int = 3;

    //#enum:Pos
    static public const POS_X:int = 0;
    static public const POS_Y:int = 1;


    //#Graphic
    static public var m_BitmapData_View:BitmapData;

    //#Mapping
    static public var GRAPHIC_INDEX_TO_POS:Array;


    //#Palette
    static public var m_Palette_ForView:Array;


    //#Utility
    static public const POS_ZERO:Point = new Point(0,0);


    //==Function==

    //#Init
    static public function Init(in_Graphic:DisplayObject):void{
        var x:int, y:int, i:int;

        //m_BitmapData_View
        {
            m_BitmapData_View = new BitmapData(256, 256, false, 0x000000);
            m_BitmapData_View.draw(in_Graphic);
        }

        //GRAPHIC_INDEX_TO_POS
        {//GRAPHIC_INDEX_~から画像の位置へのマッピング(さらにどの隅での処理かも含む)(そして左から何マス目、上から何マス目、という指定)
            GRAPHIC_INDEX_TO_POS = new Array(GRAPHIC_INDEX_NUM);

            //[LU][RU][LD][RD]

            GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_BG]            = [[3,2], [3,2], [3,2], [3,2]];

            GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL]        = [[1,1], [1,1], [1,1], [1,1]];
            GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL_X]        = [[0,1], [2,1], [0,1], [2,1]];
            GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL_Y]        = [[1,0], [1,0], [1,2], [1,2]];
            GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL_XorY]    = [[0,0], [2,0], [0,2], [2,2]];
            GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL_XandY]    = [[3,0], [4,0], [3,1], [4,1]];

            GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_NEEDLE]        = [[3,3], [4,3], [3,4], [4,4]];
            GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_NEEDLE_X]    = [[0,4], [2,4], [0,4], [2,4]];
            GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_NEEDLE_Y]    = [[1,3], [1,3], [1,5], [1,5]];
            GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_NEEDLE_XY]    = [[0,3], [2,3], [0,5], [2,5]];
        }

        //m_Palette_ForView
        {
            m_Palette_ForView = new Array(256);

            var index_graphic:int = GRAPHIC_INDEX_BG;
            for(i = 0; i < 256; i++){
                //区切りごとにindexを変更。次の区切りまではその値をセット
                switch(i){
                case 0:
                case 6:
                case 18:
                case 24:
                    index_graphic = GRAPHIC_INDEX_BG; break;
                case 3:
                case 21:
                    index_graphic = GRAPHIC_INDEX_NEEDLE_Y; break;
                case 9:
                case 15:
                    index_graphic = GRAPHIC_INDEX_NEEDLE_X; break;
                case 12:
                    index_graphic = GRAPHIC_INDEX_NEEDLE_XY; break;
                case 27:
                    index_graphic = GRAPHIC_INDEX_NEEDLE; break;
                case 54:
                case 63:
                    index_graphic = GRAPHIC_INDEX_WALL_XorY; break;
                case 60:
                case 69:
                    index_graphic = GRAPHIC_INDEX_WALL_X; break;
                case 72:
                    index_graphic = GRAPHIC_INDEX_WALL_Y; break;
                case 78:
                    index_graphic = GRAPHIC_INDEX_WALL_XandY; break;
                case 80:
                    index_graphic = GRAPHIC_INDEX_WALL; break;
                }

                m_Palette_ForView[i] = index_graphic;
            }
        }
    }

    //#Draw : BG
    static public function DrawBG(in_NumX:int, in_NumY:int, out_BitmapData_View:BitmapData):void
    {
        var x:int, y:int, i:int;
        var mtx:Matrix = new Matrix();
        var rect:Rectangle = new Rectangle(0,0, 16,16);
        var NumX:int = in_NumX;
        var NumY:int = in_NumY;

        for(y = 0; y < NumY; y++){
            for(x = 0; x < NumX; x++){
                for(i = 0; i < 4; i++){
                    rect.x = x * 32 + 16 * ((i&1)>>0);
                    rect.y = y * 32 + 16 * ((i&2)>>1);

                    var index:int = GRAPHIC_INDEX_BG;

                    //#view
                    mtx.tx = rect.x - 16 * GRAPHIC_INDEX_TO_POS[index][i][POS_X];
                    mtx.ty = rect.y - 16 * GRAPHIC_INDEX_TO_POS[index][i][POS_Y];
                    out_BitmapData_View.draw(m_BitmapData_View, mtx, null, null, rect);
                }
            }
        }
    }

    //#Draw : Blocks
    static public function DrawBlocks(in_Map:Array, out_BitmapData_View:BitmapData):void
    {
        var x:int, y:int, i:int;
        var mtx:Matrix = new Matrix();

        var NumX:int = in_Map[0].length;
        var NumY:int = in_Map.length;

        //Map => Bitmap_Base
        //Mapの要素を元に、「0:空白」「1:トゲ」「2:壁」というBitmapを生成
        var BitmapData_Base:BitmapData;
        {
            BitmapData_Base = new BitmapData(NumX, NumY, false, 0x000000);
            for(y = 0; y < NumY; y++){
                for(x = 0; x < NumX; x++){
                    var index:int = 0;//default(O, P, G)
                    {
                        switch(in_Map[y][x]){
                        case GameMain.W:
                            index = 2;
                            break;
                        case GameMain.X:
                            index = 1;
                            break;
                        }
                    }

                    BitmapData_Base.setPixel(x, y, index);
                }
            }
        }

        //Bitmap_Base => Bitmap_LU,Bitmap_RU,Bitmap_LD,Bitmap_RD
        //Bitmap_Baseを元に、四隅の隣接状況をそれぞれ求める(Uniqueな値になるようにする)
        var BitmapData_Quater:Array = new Array(4);
        {
            //Create Filter
            const filter:Array = [
                new ConvolutionFilter(3,3,
                    [//LU
                        1,  3,  0,
                        9, 27,  0,
                        0,  0,  0,
                    ]
                ),
                new ConvolutionFilter(3,3,
                    [//RU
                        0,  3,  1,
                        0, 27,  9,
                        0,  0,  0,
                    ]
                ),
                new ConvolutionFilter(3,3,
                    [//LD
                        0,  0,  0,
                        9, 27,  0,
                        1,  3,  0,
                    ]
                ),
                new ConvolutionFilter(3,3,
                    [//RD
                        0,  0,  0,
                        0, 27,  9,
                        0,  3,  1,
                    ]
                ),
            ];

            for(i = 0; i < 4; i++){
                //Init
                BitmapData_Quater[i] = new BitmapData(NumX, NumY, false, 0x000000);

                //Apply Filter
                BitmapData_Quater[i].applyFilter(BitmapData_Base, BitmapData_Base.rect, POS_ZERO, filter[i]);
            }
        }

        //Bitmap_LU,Bitmap_RU,Bitmap_LD,Bitmap_RD => ForView
        //Uniqueな値から、対応するIndexへと変換する
        var BitmapData_ForView:Array = new Array(4);
        {
            for(i = 0; i < 4; i++){
                //Init
                BitmapData_ForView[i] = new BitmapData(NumX, NumY, false, 0x000000);

                //Apply Palette
                BitmapData_ForView[i].paletteMap(BitmapData_Quater[i], BitmapData_Quater[i].rect, POS_ZERO, null, null, m_Palette_ForView);
            }
        }


        //Draw
        //上で求めたIndexに基づき描画
        {
            var rect:Rectangle = new Rectangle(0,0, 16,16);

            for(y = 0; y < NumY; y++){
                for(x = 0; x < NumX; x++){
                    for(i = 0; i < 4; i++){
                        rect.x = x * 32 + 16 * ((i&1)>>0);
                        rect.y = y * 32 + 16 * ((i&2)>>1);

                        index = BitmapData_ForView[i].getPixel(x, y);

                        //今回は背景は飛ばす
                        if(index == GRAPHIC_INDEX_BG){
                            continue;
                        }

                        //#view
                        mtx.tx = rect.x - 16 * GRAPHIC_INDEX_TO_POS[index][i][POS_X];
                        mtx.ty = rect.y - 16 * GRAPHIC_INDEX_TO_POS[index][i][POS_Y];
                        out_BitmapData_View.draw(m_BitmapData_View, mtx, null, null, rect);
                    }
                }
            }
        }
    }
}