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

ピタゴラ・アクト(Pitagola Act)

ダッシュパネルを配置して、ボールをゴールまで運ぶピタゴラ装置風ゲーム


操作方法(How To Play)
・ドラッグ&ドロップ(Drag & Drop)
 ・ダッシュパネルの配置(Set dash-panel)

比較用
・Android版(Air)
 ・https://play.google.com/store/apps/details?id=air.showohealer.game.airprototype
Get Adobe Flash player
by o_healer 13 Jul 2012
/**
 * 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/bPZ0
 */

/*
 ピタゴラ・アクト(Pitagola Act)
 ・ダッシュパネルを配置して、ボールをゴールまで運ぶピタゴラ装置風ゲーム

 操作方法(How To Play)
 ・ドラッグ&ドロップ(Drag & Drop)
  ・ダッシュパネルの配置(Set dash-panel)

 比較用
 ・Android版(Air)
  ・https://play.google.com/store/apps/details?id=air.showohealer.game.airprototype
*/


/*
ToDo


*/


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 DragAndDropAct extends Sprite {
        //==File==
//*
        static public const BITMAP_URL:String = "http://assets.wonderfl.net/images/related_images/7/7e/7ef9/7ef964ba40e4df1db26038f5dd8023c843ff0fef";
/*/
        [Embed(source='Image.png')]
         private static var Bitmap_Graphic: Class;
//*/

        //==Const==

        //画面の大きさ
        static public const VIEW_W:int = 465;
        static public const VIEW_H:int = 465;

        //リストの高さ
        static public const FOOTER_H:int = 49;//465 - 32*14

        //アイコンの大きさ
        static public const ITEM_W:int = 48;

        //アイテムの種類
        public const ITEM_VAL:Vector.<int> = new <int>[
            ActGameEngine.DL,
            ActGameEngine.DU,
            ActGameEngine.DR,
        ];

        //Map
        static public var MAP:Array;


        //==Var==

        //Pseudo Singleton
        static public var Instance:DragAndDropAct;

        //Engine
        public var m_ActGameEngine:ActGameEngine = new ActGameEngine();

        //Layer
        public var m_Layer_GameRoot:Sprite = new Sprite();
        public var m_Layer_InterfaceRoot:Sprite = new Sprite();

        //Footer
        public var m_Item:Vector.<Sprite>;

        //Dragまわり
        public var m_DragIndex:int = -1;
        public var m_DragSrcX:int = 0;
        public var m_DragSrcY:int = 0;
        public var m_DragBitmap:Bitmap = new Bitmap();
        public var m_DropCrossGraphic:Sprite = new Sprite();
        public var m_DragHelpView:Bitmap;


        //==Function==

        //Init
        public function DragAndDropAct() {
            //Load
//*
            //wonderfl用:Bitmapを外部からロードする場合

            //Load
            var loader:Loader = new Loader();
            loader.load(new URLRequest(BITMAP_URL), new LoaderContext(true));//画像のロードを開始して
            loader.contentLoaderInfo.addEventListener(
                Event.COMPLETE,//ロードが完了したら
                function(e:Event):void{
                    OnLoad(loader.content);//それを保持した後
                }
            );
/*/
            //ローカル用:Bitmapを事前ロードできる場合

            //ブロック画像のセット(&その他初期化)
            OnLoad(new Bitmap_Graphic());
//*/
        }

        public function OnLoad(in_Graphic:DisplayObject):void
        {
            //Static Init
            {
                ImageManager.Init(in_Graphic);
            }

            //Init
            {
                if(stage != null){
                    Init(null);
                }else{
                    addEventListener(
                        Event.ADDED_TO_STAGE,//ステージに追加されたら
                        Init
                    );
                }
            }
        }

        public function Init(e:Event):void
        {
            var i:int;
            var bmp:Bitmap;
            var bmd:BitmapData;

            const HideColor:uint = 0x88000000;
            const AppearColor:uint = 0x00000000;

            //Pseudo Singleton
            {
                Instance = this;
            }

            //BG
            {
                addChild(new Bitmap(new BitmapData(VIEW_W, VIEW_H, false, 0x808080)));
            }

            //Layer
            {
                addChild(m_Layer_GameRoot);
                addChild(m_Layer_InterfaceRoot);
            }

            //Clippnig
            {
                m_Layer_GameRoot.scrollRect = new Rectangle(0,0, VIEW_W, VIEW_H-FOOTER_H);
            }

            //m_DragHelpView
            {
                bmd = new BitmapData(VIEW_W, VIEW_H, true, HideColor);

                var text:TextField = new TextField();
                text.selectable = false;
                text.autoSize = TextFieldAutoSize.LEFT;
                text.defaultTextFormat = new TextFormat('Verdana', 64, 0xFFFFFF, true);
                text.text = "Drag & Drop\n    ↑  ↑  ↑";
                var mtx:Matrix = new Matrix(1,0,0,1, VIEW_W/2 - text.textWidth/2, VIEW_H/2);
                bmd.draw(text, mtx);

                m_DragHelpView = new Bitmap(bmd);

                m_Layer_InterfaceRoot.addChild(m_DragHelpView);
                //m_DragHelpView.visible = false;
            }

            //Footer
            {
                var footer:Sprite = new Sprite();
                footer.y = VIEW_H - FOOTER_H;
                m_Layer_InterfaceRoot.addChild(footer);

                //Window
                footer.addChild(new Bitmap(new BitmapData(VIEW_W, FOOTER_H, false, 0xFFFFFF)));

                //Item
                var item:Sprite;

                var ItemNum:int = ITEM_VAL.length;
                m_Item = new Vector.<Sprite>(ItemNum);
                for(i = 0; i < ItemNum; ++i){
                    bmp = new Bitmap(ImageManager.GetDashPanelGraphic(ITEM_VAL[i]));
                    bmp.x = -ActGameEngine.PANEL_W/2;
                    bmp.y = -ActGameEngine.PANEL_W/2;

                    item = new Sprite();
                    item.addChild(bmp);
                    item.x = VIEW_W/2 + (i - 1) * VIEW_W/4;
                    item.y = FOOTER_H/2;
                    item.scaleX = item.scaleY = 1.0 * ITEM_W / ActGameEngine.PANEL_W;

                    footer.addChild(item);

                    m_Item[i] = item;
                }
            }

            //m_DragBitmap
            {
                m_Layer_InterfaceRoot.addChild(m_DragBitmap);
                m_DragBitmap.visible = false;
            }

            //Touch
            {
                stage.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDown);
                stage.addEventListener(MouseEvent.MOUSE_MOVE, OnMouseMove);
                stage.addEventListener(MouseEvent.MOUSE_UP,   OnMouseUp);
            }

            //Engine
            {
                const O:int = ActGameEngine.O;//空白
                const W:int = ActGameEngine.W;//地形
                const P:int = ActGameEngine.P;//プレイヤー位置(生成後は空白として扱われる)
                const G:int = ActGameEngine.G;//ゴール位置(基本的には空白として扱われる)
                const X:int = ActGameEngine.X;//トゲブロック
                const C:int = ActGameEngine.L;//連結ブロック
                const B:int = ActGameEngine.B;//壊せる箱
                const U:int = ActGameEngine.DU;//ダッシュブロック
                const D:int = ActGameEngine.DD;//ダッシュブロック
                const L:int = ActGameEngine.DL;//ダッシュブロック
                const R:int = ActGameEngine.DR;//ダッシュブロック
                MAP = [
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,X,X,X,X,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,O,O,O,O,O,O,O,O,O,C,O,C,O,C,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,O,W,W,W,W,W,W,R,R,R,R,R,R,O,W,W,W,W,W,W,W,W,C,W,W,C,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,C,W,W,W,W,W,W,W,W,C,W,W,C,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,O,W,W,W,W,W,W,W,W,C,W,W,C,W,W,W,O,O,O,O,W,O,O,O,O,O,O,O,W,O,O,O,O,O,O,O,C,O,O,O,O,W],
[W,B,W,W,W,W,W,W,W,O,O,O,O,O,C,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,O,W,W,O,W,L,L,L,W,W,W,W,L,O,W],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,C,C,C,C,C,W,W,O,W,W,O,W,W,W,W,W,W,W,W,W,O,W],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,W,W,W,W,W,W,W,O,W,W,O,W,W,W,W,W,W,W,W,W,O,U],
[W,B,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,X,X,X,X,W,W,W,W,W,W,W,C,C,C,O,W,W,W,W,W,W,W,W,W,O,U],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,W,W,O,W,W,W,W,W,W,W,W,W,O,U],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,W,W,O,W,W,W,W,W,W,W,W,W,O,U],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,W,W,W,W,W,W,W,W,W,O,U],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,W,W,W,W,W,W,W,W,W,O,U],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,O,W,W,W,W,W,W,O,O,W,W,W,W,W,W,O,O,O,B,O,O,O,W,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,O,W,W,W,W,W,W,O,O,W,W,W,W,W,W,O,O,O,B,O,O,O,W,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,B,O,O,B,B,B,B,O,O,W,W,W,W,W,W,O,O,O,B,O,O,O,W,W,O,O,O,O,G,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,W,W,W,W,W,W,W,B,W,W,W,W,W,W,W,O,O,O,B,O,O,O,W,W,O,O,O,O,W,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,W,W,W,W,W,W,W,O,W,W,W,W,W,W,W,O,O,O,B,O,O,O,W,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,O,O,O,O,W,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,W,W,W,R,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,O,O,O,O,O,O,O,O,O,O,O,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,O,P,O,O,W,W,W,W,W,O,O,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,U],
[W,W,W,W,W,W,W,O,O,O,O,O,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,U,U,U,U,U,U,W,W,W,W,W,W,U,U,U,U,U,U,W,W,W,W,W,W,W,W,W,O,U],
[W,W,W,W,W,W,W,O,O,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,W],
[W,W,W,W,W,W,W,O,O,O,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,W],
[W,W,W,W,W,W,W,O,O,O,O,O,O,O,O,O,X,W,W,W,W,W,W,W,W,W,W,U,O,O,O,O,W,W,W,W,W,W,W,W,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,X,X,X,X,W,W,W,W,W,W,W,W,X,X,X,X,W,W,W,W,W,W,W,W,W,W,W,W],
                ];

                m_ActGameEngine = new ActGameEngine();
                m_Layer_GameRoot.addChild(m_ActGameEngine);
                m_ActGameEngine.Init(MAP, VIEW_W, VIEW_H - FOOTER_H);
            }

            //Graphic : Drop Cross
            {
                var TileNumX:int = VIEW_W / ActGameEngine.PANEL_W + 1;
                var TileNumY:int = VIEW_H / ActGameEngine.PANEL_W + 1;

                var BmdW:int = TileNumX + 1 + TileNumX;
                var BmdH:int = TileNumY + 1 + TileNumY;

                bmd = new BitmapData(BmdW, BmdH, true, HideColor);
                bmd.fillRect(new Rectangle(TileNumX, 0, 1, BmdH), AppearColor);
                bmd.fillRect(new Rectangle(0, TileNumY, BmdW, 1), AppearColor);
                
                bmp = new Bitmap(bmd);
                bmp.x -= TileNumX;
                bmp.y -= TileNumY;
                
                m_DropCrossGraphic.addChild(bmp);
                m_ActGameEngine.m_Root_Game.addChild(m_DropCrossGraphic);
                m_DropCrossGraphic.scaleX = m_DropCrossGraphic.scaleY = ActGameEngine.PANEL_W;

                m_DropCrossGraphic.visible = false;
            }

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

            //OnEnd
            {
                addEventListener(Event.REMOVED_FROM_STAGE, Finish);
            }
        }

        //Finish
        public function Finish(e:Event):void{
            removeEventListener(Event.ADDED_TO_STAGE, Init);
            removeEventListener(Event.ENTER_FRAME, Update);
            removeEventListener(Event.REMOVED_FROM_STAGE, Finish);
        }

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

            //何かをドラッグ中ならゲーム画面は停止する
            if(0 <= m_DragIndex){
                return;
            }

            m_ActGameEngine.Update(DeltaTime);
        }

        //Touch
        private function OnMouseDown(e:MouseEvent):void{
            //Alias
            const PANEL_W:int = ActGameEngine.PANEL_W;

            //すでに何かドラッグしていたらムシ
            if(0 <= m_DragIndex){
                return;
            }

            //どのパネルかをタッチしているのならドラッグ開始
            var num:int = m_Item.length;
            for(var i:int = 0; i < num; ++i){
                var item:Sprite = m_Item[i];

                //タッチの範囲チェック
                var rel_x:int = item.mouseX;
                var rel_y:int = item.mouseY;
                if(rel_x < -ITEM_W/2 || ITEM_W/2 < rel_x || rel_y < -ITEM_W/2 || ITEM_W/2 < rel_y){
                    continue;//範囲外
                }

                //タッチされたのでドラッグ開始
                m_DragIndex = i;
                m_DragSrcX = mouseX;
                m_DragSrcY = mouseY;
                m_DragBitmap.bitmapData = ImageManager.GetDashPanelGraphic(ITEM_VAL[m_DragIndex]);
                //!!画面を白黒化して時間停止
                //→ドラッグ先の強調と合わせて「ラインの幅だけ透明で、他が黒半透明のBitmap」をかぶせる(ラインが範囲外になるようにしつつ)
                // ・さらにサイズなどの削減のため、ラインは1ドットにしておいてPANEL_Wだけ拡大
                m_DragHelpView.visible = true;
                m_ActGameEngine.m_Root_Game.removeChild(m_DropCrossGraphic);
                m_ActGameEngine.m_Root_Game.addChild(m_DropCrossGraphic);//再登録して他のやつより上に表示

                break;
            }
        }
        private function OnMouseMove(e:MouseEvent):void{
            //ドラッグしているものがなければムシ
            if(m_DragIndex < 0){
                return;
            }

            //まだフッタ上にあるなら何もしない
            if(VIEW_H - FOOTER_H < mouseY){
                return;
            }

            //ドラッグ先のラインを光らせて強調
            var IndexX:int = m_ActGameEngine.m_Root_Game.mouseX / ActGameEngine.PANEL_W;//Round
            var IndexY:int = m_ActGameEngine.m_Root_Game.mouseY / ActGameEngine.PANEL_W;
            m_DropCrossGraphic.x = IndexX * ActGameEngine.PANEL_W;
            m_DropCrossGraphic.y = IndexY * ActGameEngine.PANEL_W;
            m_DragBitmap.x = m_Layer_InterfaceRoot.mouseX - ActGameEngine.PANEL_W/2;
            m_DragBitmap.y = m_Layer_InterfaceRoot.mouseY - ActGameEngine.PANEL_W/2;
            m_DragBitmap.visible = true;
            m_DropCrossGraphic.visible = true;
            m_DragHelpView.visible = false;
        }
        private function OnMouseUp(e:MouseEvent):void{
            //ドラッグしているものがなければムシ
            if(m_DragIndex < 0){
                return;
            }

            //Clear
            var MapVal:int = ITEM_VAL[m_DragIndex];
            m_DropCrossGraphic.visible = false;
            m_DragHelpView.visible = false;
            m_DragBitmap.visible = false;
            m_DragIndex = -1;

            //フッタ上にあるならキャンセル扱い
            if(VIEW_H - FOOTER_H < mouseY){
                return;
            }

            //ドラッグ先に配置
            var IndexX:int = m_ActGameEngine.m_Root_Game.mouseX / ActGameEngine.PANEL_W;//Round
            var IndexY:int = m_ActGameEngine.m_Root_Game.mouseY / ActGameEngine.PANEL_W;

            //範囲制限
            var NumX:int = MAP[0].length;
            var NumY:int = MAP.length;
            if(IndexX < 0){IndexX = 0;}
            if(NumX <= IndexX){IndexX = NumX-1;}
            if(IndexY < 0){IndexY = 0;}
            if(NumY <= IndexY){IndexY = NumY-1;}

            //壁かすでにパネルのある箇所のみ設置可能
            switch(MAP[IndexY][IndexX]){
            case ActGameEngine.W:
            case ActGameEngine.DU:
            case ActGameEngine.DD:
            case ActGameEngine.DL:
            case ActGameEngine.DR:
                break;
            default:
                return;
            }

            var obj:DashPanel = DashPanel.CreateOrChange(IndexX, IndexY, MapVal, m_ActGameEngine.m_PhysWorld);
            if(obj != null){
                m_ActGameEngine.m_GameObject.push(obj);
                m_ActGameEngine.m_Root_Game.addChild(obj);
            }
        }
    }
}


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

//Box2D
import Box2D.Dynamics.*;
import Box2D.Dynamics.Contacts.*;
import Box2D.Dynamics.Joints.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
//import General.*;


//Engine
class ActGameEngine extends Sprite
{
    //==Const==

    //パネルの大きさ
    static public const PANEL_W:int = 32;

    //重力
    static public const GRAVITY:Number = 10.0;

    //マップの要素
    static public var s_BlockIndexIter:int = 0;
    static public const O:int = s_BlockIndexIter++;//空白
    static public const W:int = s_BlockIndexIter++;//地形
    static public const P:int = s_BlockIndexIter++;//プレイヤー位置(生成後は空白として扱われる)
    static public const G:int = s_BlockIndexIter++;//ゴール位置(基本的には空白として扱われる)
    static public const X:int = s_BlockIndexIter++;//トゲブロック
    static public const L:int = s_BlockIndexIter++;//連結ブロック
    static public const B:int = s_BlockIndexIter++;//壊せる箱
    static public const DU:int = s_BlockIndexIter++;//ダッシュブロック
    static public const DD:int = s_BlockIndexIter++;//ダッシュブロック
    static public const DL:int = s_BlockIndexIter++;//ダッシュブロック
    static public const DR:int = s_BlockIndexIter++;//ダッシュブロック

    //Box2Dとのスケーリング変換
    static public const PHYS_SCALE:Number = 100.0;

    //表示サイズ(外部から指定)
    static public var VIEW_W:int = 0;
    static public var VIEW_H:int = 0;

    //マップ(外部から指定)
    static public var MAP:Array;
    static public var MAP_W:int = 0;
    static public var MAP_H:int = 0;

    //==Var==

    //Phys World
    public var m_PhysWorld:b2World;

    //All GameObject List
    public var m_GameObject:Vector.<GameObject> = new Vector.<GameObject>();

    //Layer
    public var m_Root        :Sprite = new Sprite();
    public var  m_Root_Game    :Sprite = new Sprite();
    public var  m_Root_UI    :Sprite = new Sprite();

    //BG
    public var m_BG:BackGround;

    //Player
    public var m_Player:Player;

    //Goal
    public var m_Goal:Goal;

    //Text
    public var m_Text:TextField;

    //Flag
    public var m_IsGameOver:Boolean = false;


    //==Function==

    //Init
    public function Init(in_Map:Array, in_ViewW:int, in_ViewH:int):void{
        var i:int;
        var num:int;

        //Const
        {
            VIEW_W = in_ViewW;
            VIEW_H = in_ViewH;

            MAP = in_Map;
            MAP_W = in_Map[0].length * PANEL_W;
            MAP_H = in_Map.length * PANEL_W;
        }

        //Physics
        {
            //AABB
            const RANGE_LX:Number = -10 * PANEL_W;
            const RANGE_UY:Number = -10 * PANEL_W;
            const RANGE_RX:Number = 110 * PANEL_W;
            const RANGE_DY:Number = 110 * PANEL_W;
            var worldAABB:b2AABB = new b2AABB();
            worldAABB.lowerBound.Set(RANGE_LX/PHYS_SCALE, RANGE_UY/PHYS_SCALE);
            worldAABB.upperBound.Set(RANGE_RX/PHYS_SCALE, RANGE_DY/PHYS_SCALE);
            //Gravity
            var g:b2Vec2 = new b2Vec2(0.0, GRAVITY);
            //Sleep
            var useSleep:Boolean = true;
            //World
            m_PhysWorld = new b2World(worldAABB, g, useSleep);
        }

        //Layer
        {
            addChild(m_Root);
            m_Root.addChild(m_Root_Game);
            m_Root.addChild(m_Root_UI);
        }

        //BG
        {
            m_BG = BackGround.Create(in_Map, m_PhysWorld);
            m_GameObject.push(m_BG);

            m_Root_Game.addChild(m_BG);
        }

        //Goal
        {
            m_Goal = Goal.Create(in_Map, m_PhysWorld);
            m_GameObject.push(m_Goal);

            m_Root_Game.addChild(m_Goal);
        }

        //Needle
        {
            var needle_arr:Vector.<Needle> = Needle.Create(in_Map, m_PhysWorld);
            //グラフィックがないので描画登録はなし
        }

        //Breakable Box
        {
            var box_arr:Vector.<BreakableBox> = BreakableBox.Create(in_Map, m_PhysWorld);
            num = box_arr.length;
            for(i = 0; i < num; ++i){
                m_GameObject.push(box_arr[i]);
                m_Root_Game.addChild(box_arr[i]);
            }
        }

        //Dash Panel
        {
            var dash_arr:Vector.<DashPanel> = DashPanel.Create(in_Map, m_PhysWorld);
            num = dash_arr.length;
            for(i = 0; i < num; ++i){
                m_GameObject.push(dash_arr[i]);
                m_Root_Game.addChild(dash_arr[i]);
            }
        }

        //Block
        {
            var block_arr:Vector.<Block> = Block.Create(in_Map, m_PhysWorld);
            num = block_arr.length;
            for(i = 0; i < num; ++i){
                m_GameObject.push(block_arr[i]);
                m_Root_Game.addChild(block_arr[i]);
            }
        }

        //Player
        {
            m_Player = Player.Create(in_Map, m_PhysWorld);
            m_GameObject.push(m_Player);

            m_Root_Game.addChild(m_Player);
        }

        //Text
        {
            m_Text = new TextField();

            m_Text.selectable = false;
            m_Text.autoSize = TextFieldAutoSize.CENTER;
            m_Text.defaultTextFormat = new TextFormat('Verdana', 64, 0xFFFFFF, true);
            m_Text.text = "";
//            m_Text.filters = [new GlowFilter(0x00FFFF,1.0, 8,8)];
            m_Text.x = in_ViewW/2;
            m_Text.y = in_ViewH/2;

            m_Root_UI.addChild(m_Text);
        }

        //Camera
        {
            Update_Camera(0.0);
        }

/*
        //Debug
        {
            var m_DebugLayer:Sprite = new Sprite();
            addChild(m_DebugLayer);

            // デバッグオブジェクト
            var debug:b2DebugDraw = new b2DebugDraw();
            
            debug.m_sprite            = m_DebugLayer;
            debug.m_drawScale        = PHYS_SCALE;
            debug.m_fillAlpha        = 0.3;
            debug.m_lineThickness    = 1.0;
            debug.m_drawFlags        = b2DebugDraw.e_shapeBit;
            
            // デバッグ描画
            m_PhysWorld.SetDebugDraw(debug);
        }
//*/
    }

    //Update
    public function Update(in_DeltaTime:Number):void{
        //Check
        {
            if(m_IsGameOver){
                return;
            }
        }

        //Phys
        Update_Phys(in_DeltaTime);

        //GameObj
        Update_GameObj(in_DeltaTime);

        //Camera
        Update_Camera(in_DeltaTime);

        //End Check
        Check_GameOver();
    }

    //Update : Phys
    public function Update_Phys(in_DeltaTime:Number):void{
        {
            //あまり「動くコリジョン」は使わないので、贅沢にたくさん処理して良いことにする(ちゃんとしたコリジョン排斥のため)
            var iterations:int = 50;
            m_PhysWorld.Step(in_DeltaTime, iterations);
        }

        //Phys => GameObj
        {
            for(var iter:b2Contact = m_PhysWorld.m_contactList; iter != null; iter = iter.GetNext()){
                if(iter.GetManifoldCount() == 0){
                    continue;
                }

                var Obj1:GameObject = iter.GetShape1().m_body.m_userData as GameObject;
                var Obj2:GameObject = iter.GetShape2().m_body.m_userData as GameObject;

                var Nrm_Phys:b2Vec2 = iter.GetManifolds()[0].normal;
                var Nrm:Vector3D = new Vector3D(Nrm_Phys.x, Nrm_Phys.y);
                var Nrm_Neg:Vector3D = new Vector3D(-Nrm_Phys.x, -Nrm_Phys.y);
                Nrm.normalize();
                Nrm_Neg.normalize();

                Obj1.OnContact_Common(Obj2, Nrm);
                Obj2.OnContact_Common(Obj1, Nrm_Neg);

                Obj1.OnContact(Obj2, Nrm);
                Obj2.OnContact(Obj1, Nrm_Neg);
            }

            //Physics→GameObjectへの位置の反映
            {
                for(var bb:b2Body = m_PhysWorld.m_bodyList; bb; bb = bb.m_next) {
                    var Obj:GameObject = bb.m_userData as GameObject;
                    if(Obj != null){
                        Obj.Phys2Obj();
                    }
                }
            }
        }
    }

    //Update : GameObj
    public function Update_GameObj(in_DeltaTime:Number):void{
        var num:int = m_GameObject.length;
        for(var i:int = 0; i < num; ++i){
            m_GameObject[i].Update(in_DeltaTime);
            m_GameObject[i].Update_Post();
        }
    }

    //Update : Camera
    public function Update_Camera(in_DeltaTime:Number):void{
        //プレイヤー位置
        var PlayerX:int;
        var PlayerY:int;
        {
            PlayerX = m_Player.x;
            PlayerY = m_Player.y;
        }

        //プレイヤーを中心にした時の画面の左上の座標
        var TrgX:int;
        var TrgY:int;
        {
            TrgX = PlayerX - VIEW_W/2;
            TrgY = PlayerY - VIEW_H/2;
        }

        //カメラの左上の位置
        var CameraX:int;
        var CameraY:int;
        {
            CameraX = TrgX;
            CameraY = TrgY;

            //画面外を移さないようにする
            if(CameraX + VIEW_W > MAP_W){CameraX = MAP_W - VIEW_W;}
            if(CameraX < 0){CameraX = 0;}
            if(CameraY + VIEW_H > MAP_H){CameraY = MAP_H - VIEW_H;}
            if(CameraY < 0){CameraY = 0;}
        }

        //カメラ位置に合わせて、ステージの位置を変更する
        {
            m_Root_Game.x = -CameraX;
            m_Root_Game.y = -CameraY;
        }
    }

    //Check : GameOver
    public function Check_GameOver():void{
        //Goal
        if(m_Goal.m_GoalFlag){
            OnGoal();
            return;
        }

        //Dead End
        if(m_Player.m_HP <= 0){
            OnDead();
            return;
        }
    }

    //GameOver : Dead
    public function OnDead():void{
        m_IsGameOver = true;

        m_Text.text = "Game Over";
    }

    //GameOver : Goal
    public function OnGoal():void{
        m_IsGameOver = true;

        m_Text.text = "GOAL";
    }
}


//GameObject : Interface
class GameObject extends Sprite
{
    //==Const==

    static public const PHYS_SCALE:Number = ActGameEngine.PHYS_SCALE;


    //==Var==

    //Pyhsics
    //!!

    //Phys World
    public var m_PhysWorld:b2World;

    //Phys
    public var m_PhysBody:b2Body;
    public var m_Friction:Number = 0;//0.05;

    //
    public var m_GamePosX_Prev:Number = 0;
    public var m_GamePosY_Prev:Number = 0;
    public var m_GameVelX_Prev:Number = 0;
    public var m_GameVelY_Prev:Number = 0;

    //HP
    public var m_HP:int = 1;

    //Flag
    public var m_UseSleep:Boolean = true;
    public var m_GroundFlag:Boolean = false;


    //==Function==

    //#Common

    //Update
    public function Update(in_DeltaTime:Number):void{
    }
    public function Update_Post():void{
        if(m_PhysBody != null)
        {
            //Vel
            {
                //PhysPos
                var PhysPos:b2Vec2;
                {
                    PhysPos = m_PhysBody.GetPosition();
                }

                //PhysPos => GamePos
                {
                    m_GamePosX_Prev = PhysPos.x * ActGameEngine.PHYS_SCALE;
                    m_GamePosY_Prev = PhysPos.y * ActGameEngine.PHYS_SCALE;
                }
            }

            //Vel
            {
                //PhysVel
                var PhysVel:b2Vec2;
                {
                    PhysVel = m_PhysBody.GetLinearVelocity();
                }

                //PhysVel => GameVel
                {
                    m_GameVelX_Prev = PhysVel.x * ActGameEngine.PHYS_SCALE;
                    m_GameVelY_Prev = PhysVel.y * ActGameEngine.PHYS_SCALE;
                }
            }
        }
    }


    //Damage
    public function OnDamage(in_Val:int):void{
    }


    //#Physics

    //Ready : Body
    public function ReadyBody():void{
        //Check
        if(m_PhysBody != null){
            return;
        }

        //Definition
        var physBodyDef:b2BodyDef = new b2BodyDef();
        physBodyDef.position.Set(this.x / PHYS_SCALE, this.y / PHYS_SCALE);
        physBodyDef.fixedRotation = true;
        physBodyDef.allowSleep = m_UseSleep;
        physBodyDef.userData = this;

        //Create
        m_PhysBody = m_PhysWorld.CreateBody(physBodyDef);
    }

    //Create : Fix : Box
    public function CreateCollision_Fix_Box(lx:int, uy:int, w:int, h:int):void{
        //Bodyの用意
        ReadyBody();

        var shapeDef:b2PolygonDef = new b2PolygonDef();
        shapeDef.SetAsOrientedBox(w/2/PHYS_SCALE, h/2/PHYS_SCALE, new b2Vec2((lx+w/2)/PHYS_SCALE, (uy+h/2)/PHYS_SCALE));
        shapeDef.density = 0;//Fix
        shapeDef.friction = m_Friction;
        shapeDef.restitution = 0.3;//0.5;
//        shapeDef.filter.categoryBits = i_Param.category_bits;
//        shapeDef.filter.maskBits = i_Param.mask_bits;

        m_PhysBody.CreateShape(shapeDef);
    }

    //Create : Dynamic : Box
    public function CreateCollision_Dynamic_Box(lx:int, uy:int, w:int, h:int):void{
        //Bodyの用意
        ReadyBody();

        var shapeDef:b2PolygonDef = new b2PolygonDef();
        shapeDef.SetAsOrientedBox(w/2/PHYS_SCALE, h/2/PHYS_SCALE, new b2Vec2((lx+w/2)/PHYS_SCALE, (uy+h/2)/PHYS_SCALE));
        shapeDef.density = 0.1;
        shapeDef.friction = m_Friction;
//        shapeDef.restitution = i_Param.restitution;
//        shapeDef.filter.categoryBits = i_Param.category_bits;
//        shapeDef.filter.maskBits = i_Param.mask_bits;

        m_PhysBody.CreateShape(shapeDef);

        m_PhysBody.SetMassFromShapes();
    }

    //Create : Dynamic : Circle
    public function CreateCollision_Dynamic_Circle(rad:Number):void{
        //Bodyの用意
        ReadyBody();

        var shapeDef:b2CircleDef = new b2CircleDef();
        shapeDef.radius = rad / PHYS_SCALE;
        shapeDef.density = 0.1;
        shapeDef.friction = m_Friction;
//        shapeDef.restitution = i_Param.restitution;
//        shapeDef.filter.categoryBits = i_Param.category_bits;
//        shapeDef.filter.maskBits = i_Param.mask_bits;

        m_PhysBody.CreateShape(shapeDef);

        m_PhysBody.SetMassFromShapes();
    }

    //Create : Sensor : Box
    public function CreateSensor_Box(lx:int, uy:int, w:int, h:int):void{
        //Bodyの用意
        ReadyBody();

        var shapeDef:b2PolygonDef = new b2PolygonDef();
        shapeDef.SetAsOrientedBox(w/2/PHYS_SCALE, h/2/PHYS_SCALE, new b2Vec2((lx+w/2)/PHYS_SCALE, (uy+h/2)/PHYS_SCALE));
        shapeDef.density = 0;//Fix
        shapeDef.friction = m_Friction;
//        shapeDef.restitution = i_Param.restitution;
//        shapeDef.filter.categoryBits = i_Param.category_bits;
//        shapeDef.filter.maskBits = i_Param.mask_bits;
        shapeDef.isSensor = true;

        m_PhysBody.CreateShape(shapeDef);
    }

    //Contact : Common
    public function OnContact_Common(in_Obj:GameObject, in_Nrm:Vector3D):void{
        //コリジョンに接触したら必ず呼ばれる

        //コリジョンの接地判定
        {//将来的に「横方向にぶつかってる」などの判定が必要になるかもしれないので、Ground以外にも用意しておく
            var Vel:b2Vec2 = m_PhysBody.GetLinearVelocity();

            //L
            {
                if(in_Nrm.x < -0.7){
                    if(Vel.x <= 0){
                    }
                }
            }

            //R
            {
                if(in_Nrm.x >  0.7){
                    if(Vel.x >= 0){
                    }
                }
            }

            //U
            {
                if(in_Nrm.y < -0.7){
                    if(Vel.y <= 0){
                    }
                }
            }

            //D
            {
                if(in_Nrm.y >  0.7){
//                        if(Vel.y >= 0)//これだけだと、「一緒に落下しているとき」や「めりこんで上昇してるとき」が入らないので、もっと良い判定が望まれる
                    {
                        //接地フラグを立てる
                        m_GroundFlag = true;
                    }
                }
            }
        }
    }

    //Contact : 
    public function OnContact(in_Obj:GameObject, in_Nrm:Vector3D):void{
        //こっちはオーバーライドして各自で使う
    }

    //Sync : Physics=>Obj
    public function Phys2Obj():void{
        //コリジョンの位置を実際の位置として採用する

        //Check
        {
            if(m_PhysBody == null){
                return;
            }
        }

        //Pos
        {
            this.x = m_PhysBody.GetPosition().x * PHYS_SCALE;
            this.y = m_PhysBody.GetPosition().y * PHYS_SCALE;
        }

        //Rot
        {
            this.rotation = m_PhysBody.GetAngle() * 360/(2*Math.PI);
        }
    }
}


//GameObject : BG
class BackGround extends GameObject
{
    //==Static==

    //Create
    static public function Create(in_Map:Array, in_PhysWorld:b2World):BackGround{
        var bg:BackGround = new BackGround();

        //Set Param
        {
            bg.m_PhysWorld = in_PhysWorld;
        }

        //Graphic
        {
            bg.addChild(ImageManager.CreateBackGroundGraphic(in_Map));
        }

        //Physics
        {
            CreateTerrainCollision(in_Map, bg);
        }

        return bg;
    }

    //Create : Collision
    static public function CreateTerrainCollision(in_Map:Array, bg:BackGround):void{
        var x:int;
        var y:int;
        var iter_x:int;
        var iter_y:int;

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

        //Alias
        const W:int = ActGameEngine.W;
        const O:int = ActGameEngine.O;
        const X:int = ActGameEngine.X;
        const PANEL_W:int = ActGameEngine.PANEL_W;

        var CopyMap:Array;
        {
            CopyMap = new Array(NumY);

            for(y = 0; y < NumY; y += 1){
                CopyMap[y] = new Array(NumX);

                for(x = 0; x < NumX; x += 1){
                    var m:int = in_Map[y][x];
                    switch(m){
                    case ActGameEngine.X:
                    case ActGameEngine.DU:
                    case ActGameEngine.DD:
                    case ActGameEngine.DL:
                    case ActGameEngine.DR:
                        m = W;
                        break;
                    }
                    CopyMap[y][x] = m;
                }
            }
        }

        //左右に一列になってるブロックを探して連結
        //さらに、それらの下もブロックだったら連結
        for(y = 0; y < NumY; y += 1){

            var lx:int = -1;
            var rx:int = -1;

            for(x = -1; x < NumX+1; x += 1){

                //範囲外は空白とみなす
                var map:int;
                {
                    if(x < 0){map = O;}
                    else
                    if(x >= NumX){map = O;}
                    else
                    {map = CopyMap[y][x];}
                }

                //必要な処理をしつつ、ブロックの生成が必要になったらフラグを立てて伝達
                var CreateBlockFlag:Boolean = true;
                {
                    switch(map){
                    case ActGameEngine.W:
                        {
                            if(lx < 0){lx = x;}
                            rx = x;
                        }

                        //このブロックの上も元々ブロックであれば、横に長くせず、縦に長くする
                        {
                            //上がブロックじゃない時だけフラグを戻す。そうでなければ、下のブロック生成に移行する
                            if(y == 0){CreateBlockFlag = false;}//マップの上辺なら上がブロックなわけはない
                            else
                            if(in_Map[y-1][x] != W && in_Map[y-1][x] != X){CreateBlockFlag = false;}//一つ上がブロックでなければすぐには生成しない
                        }

                        break;
                    }
                }

                //必要ならブロックを生成
                {
                    if(CreateBlockFlag)
                    {
                        //左右に連結してるのがあれば、下方向を連結した後、採用
                        if(lx >= 0)
                        {//yの段のlx~rxが連結されている
                            //lx~rx, uy~dyを一つのブロックとみなす

                            //uyとdyを求める

                            var uy:int;
                            {
                                uy = y;//今の行が上辺
                            }

                            var dy:int;
                            {
                                var break_flag:Boolean = false;
                                for(dy = uy+1; dy < NumY; dy += 1){
                                    for(iter_x = lx; iter_x <= rx; iter_x += 1){
                                        if(CopyMap[dy][iter_x] != W){
                                            break_flag = true;
                                        }

                                        if(break_flag){break;}
                                    }
                                    if(break_flag){break;}
                                }
                                dy -= 1;
                            }

                            //ブロックを実際に生成
                            {
                                bg.CreateCollision_Fix_Box(lx * PANEL_W, uy * PANEL_W, (rx-lx+1) * PANEL_W, (dy-uy+1) * PANEL_W);
//                                var block:Block_Fix = new Block_Fix();
//                                block.Init(lx, rx, uy, dy);
                            }

                            //CopyMap上から、該当ブロックを消す
                            {
                                for(iter_y = uy; iter_y <= dy; iter_y += 1){
                                    for(iter_x = lx; iter_x <= rx; iter_x += 1){
                                        CopyMap[iter_y][iter_x] = O;
                                    }
                                }
                            }

                            //reset
                            {
                                lx = rx = -1;
                            }
                        }//lx >= 0
                    }//CreateBlockFlag
                }//Scope : Create Block
            }//loop x
        }//loop y
    }
}


//GameObject : Block
class Block extends GameObject
{
    //==Static==

    //Create
    static public function Create(in_Map:Array, in_PhysWorld:b2World):Vector.<Block>{
        var result:Vector.<Block> = new Vector.<Block>();

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

        //Temp
        var xx:int;
        var yy:int;

        //m_Mapの内容をコピーして、連結したものは消せるようにしておく
        var CopyMap:Vector.<Vector.<int> >;
        {
            CopyMap = new Vector.<Vector.<int> >(NumY);

            for(yy = 0; yy < NumY; yy += 1){
                CopyMap[yy] = new Vector.<int>(NumX);

                for(xx = 0; xx < NumX; xx += 1){
                    CopyMap[yy][xx] = in_Map[yy][xx];
                }
            }
        }

        //連結ブロック
        {
            var link_info:Vector.<Point> = new Vector.<Point>();

            const MAP_W_MAX:int = 100;
            const MAP_H_MAX:int = 100;

            var link_lx:int = MAP_W_MAX;
            var link_rx:int = 0;
            var link_uy:int = MAP_H_MAX;
            var link_dy:int = 0;

            const gather_link_block:Function = function(in_X:int, in_Y:int):void{
                //Check
                {//L以外は飛ばす
                    if(CopyMap[in_Y][in_X] != ActGameEngine.L){
                        return;
                    }
                }

                //Lがあったので、これと連結しているLを全て集めて連結ブロックを生成

                //まずは自分を追加
                {
                    link_info.push(new Point(in_X, in_Y));
                }

                //ここは確認したので消す
                {
                    CopyMap[in_Y][in_X] = ActGameEngine.O;
                }

                //Lのある範囲を求める
                {
                    if(in_X < link_lx){link_lx = in_X;}
                    if(link_rx < in_X){link_rx = in_X;}
                    if(in_Y < link_uy){link_uy = in_Y;}
                    if(link_dy < in_Y){link_dy = in_Y;}
                }

                //上下左右について確認
                {
                    if(in_Y > 0){gather_link_block(in_X, in_Y-1);}
                    if(in_Y < NumY-1){gather_link_block(in_X, in_Y+1);}
                    if(in_X > 0){gather_link_block(in_X-1, in_Y);}
                    if(in_X < NumX-1){gather_link_block(in_X+1, in_Y);}
                }
            };

            for(yy = 0; yy < NumY; ++yy){
                for(xx = 0; xx < NumX; ++xx){
                    //
                    gather_link_block(xx, yy);

                    //
                    if(link_info.length > 0){
                        //Create
                        {
                            var block:Block = Create_One(link_info, link_lx, link_rx, link_uy, link_dy, in_PhysWorld);

                            result.push(block);
                        }

                        //Reset
                        {
                            link_info = new Vector.<Point>();

                            link_lx = MAP_W_MAX;
                            link_rx = 0;
                            link_uy = MAP_H_MAX;
                            link_dy = 0;
                        }
                    }
                }
            }
        }

        return result;
    }

    //Create : Solo
    static public function Create_One(in_PointList:Vector.<Point>, in_LX:int, in_RX:int, in_UY:int, in_DY:int, in_PhysWorld:b2World):Block{
        var Num:int = in_PointList.length;
        var NumX:int = in_RX - in_LX + 1;
        var NumY:int = in_DY - in_UY + 1;
        var i:int;
        var xx:int;
        var yy:int;

        var OffsetX:int = -in_LX * ActGameEngine.PANEL_W;
        var OffsetY:int = -in_UY * ActGameEngine.PANEL_W;

        //CopyMap
        var CopyMap:Array;
        {
            //Init
            {
                CopyMap = new Array(NumY);
                for(yy = 0; yy < NumY; yy++){
                    CopyMap[yy] = new Array(NumX);
                    for(xx = 0; xx < NumX; xx++){
                        CopyMap[yy][xx] = ActGameEngine.O;
                    }
                }
            }

            //Set
            {
                for(i = 0; i < Num; i++){
                    var point:Point = in_PointList[i];

                    xx = point.x - in_LX;
                    yy = point.y - in_UY;

                    CopyMap[yy][xx] = ActGameEngine.L;
                }
            }
        }


        //まずはコリジョンのRectangleのリストを求める
        var col_rect_list:Vector.<Rectangle> = new Vector.<Rectangle>();
        {//横方向に並んでるものはまとめて、さらに縦も同じ位置・同じ幅であればまとめる

            //まとめるための関数
            const clustering:Function = function(in_LX:int, in_RX:int, in_Y:int):void{
                //今回の分の範囲
                var rect:Rectangle = new Rectangle(in_LX, in_Y, in_RX-in_LX+1, 1);

                //すでに求めた範囲のやつと一体化できるなら一体化する
                var col_num:int = col_rect_list.length;
                for(i = 0; i < col_num; i++){
                    //検証対象
                    var trg_rect:Rectangle = col_rect_list[i];

                    //一体化できるか
                    var union_flag:Boolean = true;
                    {
                        //幅が違えば一体化しない
                        if(trg_rect.x != rect.x || trg_rect.width != rect.width){
                            union_flag = false;
                        }

                        //自分の一つ上でなければ一体化しない
                        {
                            var trg_next_y:int = trg_rect.y + trg_rect.height;
                            if(trg_next_y != in_Y){
                                union_flag = false;
                            }
                        }
                    }

                    //一体化
                    if(union_flag){
                        trg_rect.height += 1;//下にくっつけたことにすればOKのはず

                        return;//一体化したので新規登録はせずに終了
                    }
                }

                //一体化できるものがなければ、新規登録
                col_rect_list.push(rect);
            }

            //まとめ中かそうでないかのフラグ
            var NowClustering:Boolean = false;

            //イテレーション開始
            var lx:int, rx:int;
            for(yy = 0; yy < NumY; yy++){
                for(xx = 0; xx < NumX; xx++){
                    var IsBlock:Boolean = (CopyMap[yy][xx] == ActGameEngine.L);

                    if(! NowClustering){//Lをまだ見つけていない
                        if(! IsBlock){//今回のもLじゃない
                            //何もせず次へ進む
                        }else{//Lを見つけた
                            //クラスタリング開始
                            NowClustering = true;
                            //左端はここ
                            lx = xx;
                            //右端もここ
                            rx = xx;
                        }
                    }else{//Lをすでに見つけていて、それを連結中
                        if(IsBlock){//今回のもLだった
                            //右端を伸ばす
                            rx = xx;
                        }else{//Lが途切れた
                            //前回位置までをクラスタリング
                            clustering(lx, rx, yy);
                            //クラスタリング終了
                            NowClustering = false;
                        }
                    }
                }

                if(NowClustering){//右端までLだった
                    //まとめる
                    rx = xx-1;
                    clustering(lx, rx, yy);
                    //クラスタリング終了
                    NowClustering = false;
                }
            }
        }

        //原点の調整をしつつ実際にコリジョンを生成
        var block:Block = new Block();
        {
            //Create
            {
                block.x = -OffsetX;
                block.y = -OffsetY;
                block.m_PhysWorld = in_PhysWorld;
                block.ReadyBody();
            }

            //Add Shape
            {
                var shapeDef:b2PolygonDef = new b2PolygonDef();
                shapeDef.density = 0.1;
                shapeDef.friction = 0.1;//0.3;
//                shapeDef.restitution = ColParam.restitution;
//                shapeDef.filter.categoryBits = ColParam.category_bits;
//                shapeDef.filter.maskBits = ColParam.mask_bits;

                var center:b2Vec2 = new b2Vec2();

                var col_num:int = col_rect_list.length;
                for(i = 0; i < col_num; i++){
                    var rect:Rectangle = col_rect_list[i];

                    //W
                    var w:Number = (rect.width/2 * ActGameEngine.PANEL_W - 0.01) / ActGameEngine.PHYS_SCALE;
                    var h:Number = (rect.height/2 * ActGameEngine.PANEL_W - 0.01) / ActGameEngine.PHYS_SCALE;

                    //center
                    center.x = (ActGameEngine.PANEL_W * (in_LX + (rect.left + rect.right)/2) + OffsetX) / ActGameEngine.PHYS_SCALE;
                    center.y = (ActGameEngine.PANEL_W * (in_UY + (rect.top + rect.bottom)/2) + OffsetY) / ActGameEngine.PHYS_SCALE;

/*
                    shapeDef.SetAsOrientedBox(w, h, center);
/*/
                    {//八角形
                        var d:Number = 4.0 / ActGameEngine.PHYS_SCALE;//削り取る角の辺の長さ

                        shapeDef.vertexCount = 8;
                        //時計回りに頂点を設定
                        shapeDef.vertices[0].Set(center.x + w-d, center.y - h);//北北東
                        shapeDef.vertices[1].Set(center.x + w,   center.y - h+d);//東北東
                        shapeDef.vertices[2].Set(center.x + w,   center.y + h-d);//東南東
                        shapeDef.vertices[3].Set(center.x + w-d, center.y + h);//南南東
                        shapeDef.vertices[4].Set(center.x - w+d, center.y + h);//南南西
                        shapeDef.vertices[5].Set(center.x - w,   center.y + h-d);//西南西
                        shapeDef.vertices[6].Set(center.x - w,   center.y - h+d);//西北西
                        shapeDef.vertices[7].Set(center.x - w+d, center.y - h  );//北北西
                    }
//*/

                    block.m_PhysBody.CreateShape(shapeDef);
                }

                block.m_PhysBody.SetMassFromShapes();
            }
        }

        //画像
        {
            var bmp:Bitmap = ImageManager.CreateBlockGraphic(CopyMap);
            block.addChild(bmp);
        }

        return block;
    }
}


//GameObject : Needle
class Needle extends GameObject
{
    //==Static==

    //Create
    static public function Create(in_Map:Array, in_PhysWorld:b2World):Vector.<Needle>{
        var result:Vector.<Needle> = new Vector.<Needle>();

        //
        var num_x:int = in_Map[0].length;
        var num_y:int = in_Map.length;
        for(var yy:int = 0; yy < num_y; ++yy){
            for(var xx:int = 0; xx < num_x; ++xx){
                if(in_Map[yy][xx] == ActGameEngine.X){
                    var obj:Needle = new Needle(xx, yy, in_PhysWorld);
                    result.push(obj);
                }
            }
        }

        return result;
    }

    //==Function==

    //Init
    public function Needle(in_IndexX:int, in_IndexY:int, in_PhysWorld:b2World){
        //Alias
        const PANEL_W:int = ActGameEngine.PANEL_W;

        //Param
        {
            m_PhysWorld = in_PhysWorld;

            this.x = in_IndexX * PANEL_W;
            this.y = in_IndexY * PANEL_W;
        }

        //Collision
        {
            CreateSensor_Box(-PANEL_W/16, -PANEL_W/16, PANEL_W*18/16, PANEL_W*18/16);
        }

        //No Graphic
    }

    //Contact :
    override public function OnContact(in_Obj:GameObject, in_Nrm:Vector3D):void{
        //Check
        if(! (in_Obj is Player)){
            return;
        }

        //
        const DamageVal:int = 1;
        in_Obj.OnDamage(DamageVal);
    }
}


//GameObject : Player
class Player extends GameObject
{
    //==Static==

    //Create
    static public function Create(in_Map:Array, in_PhysWorld:b2World):Player{
        var player:Player = new Player();

        //Set Param
        {
            player.m_PhysWorld = in_PhysWorld;
            player.m_UseSleep = false;

            var num_x:int = in_Map[0].length;
            var num_y:int = in_Map.length;
            for(var yy:int = 0; yy < num_y; ++yy){
                for(var xx:int = 0; xx < num_x; ++xx){
                    if(in_Map[yy][xx] == ActGameEngine.P){
                        player.x = (xx + 0.5) * ActGameEngine.PANEL_W;
                        player.y = (yy + 0.5) * ActGameEngine.PANEL_W;
                    }
                }
            }
        }

        //Init
        {
            player.Init();
        }

        return player;
    }


    //==Const==


    //==Var==


    //==Function==

    //Init
    public function Init():void{
        //Alias
        const PANEL_W:int = ActGameEngine.PANEL_W;

        //グラフィック
        {
            var bmp:Bitmap = new Bitmap(ImageManager.GetPlayerGraphic());

            bmp.x = -PANEL_W/2;
            bmp.y = -PANEL_W/2;
            addChild(bmp);
        }

        //コリジョン
        {
            CreateCollision_Dynamic_Circle((PANEL_W-1) * 0.5);
        }
    }

    //Update
    override public function Update(in_DeltaTime:Number):void{
    }

    //Damage
    override public function OnDamage(in_Val:int):void{
        if(m_HP <= 0){
            return;
        }

        m_HP -= in_Val;
    }
}


//GameObject : Goal
class Goal extends GameObject
{
    //==Static==

    //Create
    static public function Create(in_Map:Array, in_PhysWorld:b2World):Goal{
        var goal:Goal = new Goal();

        //Set Param
        {
            goal.m_PhysWorld = in_PhysWorld;
            goal.m_UseSleep = false;

            var num_x:int = in_Map[0].length;
            var num_y:int = in_Map.length;
            for(var yy:int = 0; yy < num_y; ++yy){
                for(var xx:int = 0; xx < num_x; ++xx){
                    if(in_Map[yy][xx] == ActGameEngine.G){
                        goal.x = xx * ActGameEngine.PANEL_W;
                        goal.y = yy * ActGameEngine.PANEL_W;
                    }
                }
            }
        }

        //Init
        {
            goal.Init();
        }

        return goal;
    }


    //==Var==

    public var m_GoalFlag:Boolean = false;


    //==Function==

    //Init
    public function Init():void{
        //Alias
        const PANEL_W:int = ActGameEngine.PANEL_W;

        //Collision
        {
            CreateSensor_Box(PANEL_W*2/16, PANEL_W*2/16, PANEL_W*12/16, PANEL_W*12/16);
        }

        //Graphic
        {
            //this.blendMode = BlendMode.ADD;
            addChild(ImageManager.CreateGoalGraphic());
        }
    }

    //Contact :
    override public function OnContact(in_Obj:GameObject, in_Nrm:Vector3D):void{
        //Check
        if(! (in_Obj is Player)){
            return;
        }

        //
        m_GoalFlag = true;
    }
}


//DashPanel
class DashPanel extends GameObject
{
    //==Static==
    static public var s_GameObjMap:Vector.<Vector.<DashPanel> >;
    static public function Create(in_Map:Array, in_PhysWorld:b2World):Vector.<DashPanel>{
        //
        var result:Vector.<DashPanel> = new Vector.<DashPanel>();
        var obj:DashPanel;

        var xx:int, yy:int;

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

            s_GameObjMap = new Vector.<Vector.<DashPanel> >(NumY);
            for(yy = 0; yy < NumY; ++yy){
                s_GameObjMap[yy] = new Vector.<DashPanel>(NumX);
                for(xx = 0; xx < NumX; ++xx){
                    s_GameObjMap[yy][xx] = null;

                    var map:int = in_Map[yy][xx];
                    switch(map){
                    case ActGameEngine.DU:
                    case ActGameEngine.DD:
                    case ActGameEngine.DL:
                    case ActGameEngine.DR:
                        obj = CreateOrChange(xx, yy, map, in_PhysWorld);
                        result.push(obj);
                        break;
                    }
                }
            }
        }

        return result;
    }
    static public function CreateOrChange(in_X:int, in_Y:int, in_MapVal:int, in_PhysWorld:b2World):DashPanel{
        //新規追加の場合のみインスタンスを返し、すでにあるやつの変更になるならNullを返す
        var obj:DashPanel = s_GameObjMap[in_Y][in_X];
        if(obj == null){
            //新規
            obj = new DashPanel();
            obj.m_PhysWorld = in_PhysWorld;
            obj.x = in_X * ActGameEngine.PANEL_W;
            obj.y = in_Y * ActGameEngine.PANEL_W;
            obj.Init(in_MapVal)
            s_GameObjMap[in_Y][in_X] = obj;
            return obj;
        }else{
            //変更
            obj.ChangeDir(in_MapVal);
            return null;
        }
    }

    //==Const==

    static public const MOVE_POW_X:Number = 1100.0;
//    static public const MOVE_POW_Y:Number = 5100.0;
    static public const MOVE_VEL_Y:Number = 420.0;
    static public const DEC_RATIO:Number = 0.7;


    //==Var==

    public var m_MapVal:int = ActGameEngine.DU;

    public var m_Bitmap:Bitmap = new Bitmap();


    //==Function==
    //Init
    public function Init(in_MapVal:int):void{
        //Alias
        const PANEL_W:int = ActGameEngine.PANEL_W;

        //Phys
        {
            CreateSensor_Box(-PANEL_W/16, -PANEL_W/16, PANEL_W*18/16, PANEL_W*18/16);
        }

        //Graphic
        {
            addChild(m_Bitmap);
        }

        //Dir
        {
            ChangeDir(in_MapVal);
        }
    }
    //Change : Dir
    public function ChangeDir(in_MapVal:int):void{
        //Param
        {
            m_MapVal = in_MapVal;
        }

        //Graphic
        {
            m_Bitmap.bitmapData = ImageManager.GetDashPanelGraphic(m_MapVal);
        }
    }
    //OnContact
    override public function OnContact(in_Obj:GameObject, in_Nrm:Vector3D):void{
        //対象の速度の変更

        var body:b2Body = in_Obj.m_PhysBody;
        if(body == null){return;}

        var DeltaTime:Number = 1.0 / stage.frameRate;

        //PhysVel
        var PhysVel:b2Vec2;
        {
            PhysVel = body.GetLinearVelocity();
        }

        //PhysVel => GameVel
        var GameVX:Number;
        var GameVY:Number;
        {
            GameVX = PhysVel.x * ActGameEngine.PHYS_SCALE;
            GameVY = PhysVel.y * ActGameEngine.PHYS_SCALE;
        }

        //GameVelの補正
        {
            var GameAX:Number;
            var GameAY:Number;
            switch(m_MapVal){
            case ActGameEngine.DU:
            case ActGameEngine.DD:
//                GameAY = (m_MapVal != ActGameEngine.DU)? MOVE_POW_Y: -MOVE_POW_Y;
//                GameVY += GameAY * DeltaTime;
//                GameVY *= Math.pow(DEC_RATIO, 10.0*DeltaTime);
                GameVY = (m_MapVal != ActGameEngine.DU)? MOVE_VEL_Y: -MOVE_VEL_Y;
                break;
            case ActGameEngine.DL:
            case ActGameEngine.DR:
                GameAX = (m_MapVal != ActGameEngine.DL)? MOVE_POW_X: -MOVE_POW_X;
                GameVX += GameAX * DeltaTime;
                GameVX *= Math.pow(DEC_RATIO, 10.0*DeltaTime);
                break;
            }
        }

        //上矢印の吸着だけ特殊処理(バウンドを抑える)
        {
            if(m_MapVal == ActGameEngine.DU && in_Obj is Player)
            {
                if(this.y + ActGameEngine.PANEL_W < in_Obj.y)
                {
                    if(this.x <= in_Obj.x && in_Obj.x < this.x + ActGameEngine.PANEL_W)
                    {//真下
                        GameVY = -200;
                        in_Obj.y = this.y + ActGameEngine.PANEL_W * 1.5;
                        var PhysPos:b2Vec2 = body.GetPosition();
                        PhysPos.y = in_Obj.y / ActGameEngine.PHYS_SCALE;
                        body.GetXForm().position.SetV(PhysPos);
                    }
                    else
                    {//斜め下
                        //GameVY = -200;
                        GameVY = PhysVel.y * ActGameEngine.PHYS_SCALE;
                    }
                }
            }
        }

        //GameVel => PhysVel
        {
            PhysVel.x = GameVX / ActGameEngine.PHYS_SCALE;
            PhysVel.y = GameVY / ActGameEngine.PHYS_SCALE;
        }

        //Apply
        {
            body.SetLinearVelocity(PhysVel);
        }

        //相手のスリープを解除
        {
            body.WakeUp();
        }
    }
}


class BreakableBox extends GameObject
{
    //==Const==

    static public const BREAK_VEL_THRESHOLD:Number = 50;

    static public const GAP_VEL_RATIO_MIN:Number = 10.0;
    static public const GAP_VEL_RATIO_MAX:Number = 10.0;
    static public const ROT_VEL_MAX:Number = 3.0 * 360;

    static public const PIECE_RECT:Vector.<Rectangle> = new <Rectangle>[
        new Rectangle( 0, 0, 32, 4),//U
        new Rectangle( 0,28, 32, 4),//D
        new Rectangle( 0, 0,  4,32),//L
        new Rectangle(28, 0,  4,32),//R
        new Rectangle( 4, 4, 24, 4),//Inner
        new Rectangle( 4, 8, 12, 4),
        new Rectangle(16, 8, 12, 4),
        new Rectangle( 4,12, 24, 4),//
        new Rectangle( 4,16, 12, 4),
        new Rectangle(16,16, 12, 4),
        new Rectangle( 4,20, 24, 4),//
        new Rectangle( 4,24, 12, 4),
        new Rectangle(16,24, 12, 4),
    ];

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


    //==Static==
    static public function Create(in_Map:Array, in_PhysWorld:b2World):Vector.<BreakableBox>{
        var result:Vector.<BreakableBox> = new Vector.<BreakableBox>();

        //
        var num_x:int = in_Map[0].length;
        var num_y:int = in_Map.length;
        for(var yy:int = 0; yy < num_y; ++yy){
            for(var xx:int = 0; xx < num_x; ++xx){
                if(in_Map[yy][xx] == ActGameEngine.B){
                    var obj:BreakableBox = new BreakableBox(xx, yy, in_PhysWorld);
                    result.push(obj);
                }
            }
        }

        return result;
    }

    //==Var==

    public var m_Bitmap_Box:Bitmap;
    public var m_Piece:Vector.<BoxPiece> = null;


    //==Function==

    //Init
    public function BreakableBox(in_IndexX:int, in_IndexY:int, in_PhysWorld:b2World){
        //Alias
        const PANEL_W:int = ActGameEngine.PANEL_W;

        //Param
        {
            m_PhysWorld = in_PhysWorld;

            this.x = in_IndexX * PANEL_W;
            this.y = in_IndexY * PANEL_W;
        }

        //Collision
        {
            CreateCollision_Fix_Box(0, 0, PANEL_W, PANEL_W);
        }

        //Graphic
        {
            m_Bitmap_Box = new Bitmap(ImageManager.GetBreakableBoxGraphic());
            addChild(m_Bitmap_Box);
        }
    }

    //Update
    override public function Update(in_DeltaTime:Number):void{
        if(m_Piece != null){
            var num:int = PIECE_RECT.length;
            for(var i:int = 0; i < num; ++i){
                m_Piece[i].Update(in_DeltaTime);
            }
        }
    }

    //Contact :
    override public function OnContact(in_Obj:GameObject, in_Nrm:Vector3D):void{
        //Check
        if(! (in_Obj is Player)){
            return;
        }

        //Check Vel
        {
            //Check
            {
                var Dot:Number = in_Obj.m_GameVelX_Prev * in_Nrm.x + in_Obj.m_GameVelY_Prev * in_Nrm.y;
                if(Math.abs(Dot) < BREAK_VEL_THRESHOLD){
                    return;
                }
            }
        }

        //自滅
        const DamageVal:int = 1;
        OnDamage(DamageVal);
        if(m_HP <= 0){
            CreatePieces(in_Obj.m_GameVelX_Prev, in_Obj.m_GameVelY_Prev);
        }
    }

    //Damage
    override public function OnDamage(in_Val:int):void{
        if(m_HP <= 0){
            return;
        }

        m_HP -= in_Val;
    }

    //Create : Pieces
    public function CreatePieces(in_HitVX:Number, in_HitVY:Number):void{
        //Alias
        const PANEL_W:int = ActGameEngine.PANEL_W;

        //Graphic : Box : Hide
        {
            removeChild(m_Bitmap_Box);
        }

        //Create Pieces
        {
            var num:int = PIECE_RECT.length;
            m_Piece = new Vector.<BoxPiece>(num);
            for(var i:int = 0; i < num; ++i)
            {
                var rect:Rectangle = PIECE_RECT[i];
                var bmd:BitmapData = new BitmapData(rect.width, rect.height, false, 0x000000);
                bmd.copyPixels(m_Bitmap_Box.bitmapData, rect, POS_ZERO);

                var CenterX:Number = rect.x + rect.width/2;
                var CenterY:Number = rect.y + rect.height/2;
                var GapX:Number = CenterX - PANEL_W/2;
                var GapY:Number = CenterY - PANEL_W/2;

                var piece:BoxPiece = new BoxPiece(bmd);
                piece.x = CenterX;
                piece.y = CenterY;
                piece.vx = in_HitVX + GapX * Lerp(GAP_VEL_RATIO_MIN, GAP_VEL_RATIO_MIN, Math.random());
                piece.vy = in_HitVY + GapY * Lerp(GAP_VEL_RATIO_MIN, GAP_VEL_RATIO_MIN, Math.random());
                piece.rotv = Lerp(-ROT_VEL_MAX, ROT_VEL_MAX, Math.random());

                addChild(piece);
                m_Piece[i] = piece;
            }
        }

        //Collision
        {
            m_PhysWorld.DestroyBody(m_PhysBody);
            m_PhysBody = null;
        }
    }

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


//BoxPiece
class BoxPiece extends Sprite
{
    //==Const==
    static public const GRAVITY:Number = 1000;

    //==Var==
    public var vx:Number = 0;
    public var vy:Number = 0;
    public var rotv:Number = 0;

    //==Function==
    //Init
    public function BoxPiece(in_BMD:BitmapData){
        var bmp:Bitmap = new Bitmap(in_BMD);
        bmp.x = -in_BMD.width/2;
        bmp.y = -in_BMD.height/2;
        addChild(bmp);
    }
    //Update
    public function Update(in_DeltaTime:Number):void{
        this.x += vx * in_DeltaTime;
        this.y += vy * in_DeltaTime + 0.5*GRAVITY*in_DeltaTime*in_DeltaTime;
        vy += GRAVITY*in_DeltaTime;

        this.rotation = rotv * in_DeltaTime;
    }
}


//ImageManager
class ImageManager
{
    //==Const==

    //Alias
    static public const PANEL_W:int = ActGameEngine.PANEL_W;
    static public const TILE_W:int    = PANEL_W / 2;


    //#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_Ori:BitmapData;

    static public var m_BitmapData_DashPanel:Vector.<BitmapData> = new Vector.<BitmapData>(4);
    static public var m_BitmapData_BreakableBox:BitmapData;
    static public var m_BitmapData_Player:BitmapData;
    static public var m_BitmapData_Goal:BitmapData;

    //#Mapping
    static public var m_Rect_Ground    :Vector.<Vector.<Rectangle> >;
    static public var m_Rect_Block    :Vector.<Vector.<Rectangle> >;
    static public var m_Rect_Needle    :Vector.<Vector.<Rectangle> >;


    //Filter
    static public const divisor:Number = 1.0;
    static public const bias:Number = 0.0;
    static public const preserveAlpha:Boolean = true;
    static public const clamp:Boolean = false;
    static public const m_ConvFilter:Vector.<ConvolutionFilter> = new <ConvolutionFilter>[
        new ConvolutionFilter(3,3,
            [//LU
                1, 2, 0,
                4, 8, 0,
                0, 0, 0,
            ],divisor,bias,preserveAlpha,clamp
        ),
        new ConvolutionFilter(3,3,
            [//RU
                0, 2, 1,
                0, 8, 4,
                0, 0, 0,
            ],divisor,bias,preserveAlpha,clamp
        ),
        new ConvolutionFilter(3,3,
            [//LD
                0, 0, 0,
                4, 8, 0,
                1, 2, 0,
            ],divisor,bias,preserveAlpha,clamp
        ),
        new ConvolutionFilter(3,3,
            [//RD
                0, 0, 0,
                0, 8, 4,
                0, 2, 1,
            ],divisor,bias,preserveAlpha,clamp
        ),
    ];

    //Rect
    //- Empty
    static public const RECT_EMPTY            :Rectangle = new Rectangle( 4 * TILE_W,  2 * TILE_W, TILE_W, TILE_W);
    //- BG
    static public const RECT_BG                :Rectangle = new Rectangle( 3 * TILE_W,  2 * TILE_W, TILE_W, TILE_W);
    //- Goal
    static public const RECT_GOAL            :Rectangle = new Rectangle( 8 * TILE_W,  3 * TILE_W, PANEL_W, PANEL_W);
    //- Wall
    static public const RECT_WALL            :Rectangle = new Rectangle( 1 * TILE_W,  1 * TILE_W, TILE_W, TILE_W);
    static public const RECT_WALL_L            :Rectangle = new Rectangle( 0 * TILE_W,  1 * TILE_W, TILE_W, TILE_W);
    static public const RECT_WALL_R            :Rectangle = new Rectangle( 2 * TILE_W,  1 * TILE_W, TILE_W, TILE_W);
    static public const RECT_WALL_U            :Rectangle = new Rectangle( 1 * TILE_W,  0 * TILE_W, TILE_W, TILE_W);
    static public const RECT_WALL_D            :Rectangle = new Rectangle( 1 * TILE_W,  2 * TILE_W, TILE_W, TILE_W);
    static public const RECT_WALL_LorU        :Rectangle = new Rectangle( 0 * TILE_W,  0 * TILE_W, TILE_W, TILE_W);
    static public const RECT_WALL_RorU        :Rectangle = new Rectangle( 2 * TILE_W,  0 * TILE_W, TILE_W, TILE_W);
    static public const RECT_WALL_LorD        :Rectangle = new Rectangle( 0 * TILE_W,  2 * TILE_W, TILE_W, TILE_W);
    static public const RECT_WALL_RorD        :Rectangle = new Rectangle( 2 * TILE_W,  2 * TILE_W, TILE_W, TILE_W);
    static public const RECT_WALL_LandU        :Rectangle = new Rectangle( 3 * TILE_W,  0 * TILE_W, TILE_W, TILE_W);
    static public const RECT_WALL_RandU        :Rectangle = new Rectangle( 4 * TILE_W,  0 * TILE_W, TILE_W, TILE_W);
    static public const RECT_WALL_LandD        :Rectangle = new Rectangle( 3 * TILE_W,  1 * TILE_W, TILE_W, TILE_W);
    static public const RECT_WALL_RandD        :Rectangle = new Rectangle( 4 * TILE_W,  1 * TILE_W, TILE_W, TILE_W);
    //- Block
    static public const RECT_BLOCK            :Rectangle = new Rectangle( 1 * TILE_W,  4 * TILE_W, TILE_W, TILE_W);
    static public const RECT_BLOCK_L        :Rectangle = new Rectangle( 0 * TILE_W,  4 * TILE_W, TILE_W, TILE_W);
    static public const RECT_BLOCK_R        :Rectangle = new Rectangle( 2 * TILE_W,  4 * TILE_W, TILE_W, TILE_W);
    static public const RECT_BLOCK_U        :Rectangle = new Rectangle( 1 * TILE_W,  3 * TILE_W, TILE_W, TILE_W);
    static public const RECT_BLOCK_D        :Rectangle = new Rectangle( 1 * TILE_W,  5 * TILE_W, TILE_W, TILE_W);
    static public const RECT_BLOCK_LorU        :Rectangle = new Rectangle( 0 * TILE_W,  3 * TILE_W, TILE_W, TILE_W);
    static public const RECT_BLOCK_RorU        :Rectangle = new Rectangle( 2 * TILE_W,  3 * TILE_W, TILE_W, TILE_W);
    static public const RECT_BLOCK_LorD        :Rectangle = new Rectangle( 0 * TILE_W,  5 * TILE_W, TILE_W, TILE_W);
    static public const RECT_BLOCK_RorD        :Rectangle = new Rectangle( 2 * TILE_W,  5 * TILE_W, TILE_W, TILE_W);
    static public const RECT_BLOCK_LandU    :Rectangle = new Rectangle( 3 * TILE_W,  3 * TILE_W, TILE_W, TILE_W);
    static public const RECT_BLOCK_RandU    :Rectangle = new Rectangle( 4 * TILE_W,  3 * TILE_W, TILE_W, TILE_W);
    static public const RECT_BLOCK_LandD    :Rectangle = new Rectangle( 3 * TILE_W,  4 * TILE_W, TILE_W, TILE_W);
    static public const RECT_BLOCK_RandD    :Rectangle = new Rectangle( 4 * TILE_W,  4 * TILE_W, TILE_W, TILE_W);
    //- Needle
    static public const RECT_STEEL            :Rectangle = new Rectangle( 6 * TILE_W,  1 * TILE_W, TILE_W, TILE_W);
    static public const RECT_STEEL_L        :Rectangle = new Rectangle( 5 * TILE_W,  1 * TILE_W, TILE_W, TILE_W);
    static public const RECT_STEEL_R        :Rectangle = new Rectangle( 7 * TILE_W,  1 * TILE_W, TILE_W, TILE_W);
    static public const RECT_STEEL_U        :Rectangle = new Rectangle( 6 * TILE_W,  0 * TILE_W, TILE_W, TILE_W);
    static public const RECT_STEEL_D        :Rectangle = new Rectangle( 6 * TILE_W,  2 * TILE_W, TILE_W, TILE_W);
    static public const RECT_STEEL_LorU        :Rectangle = new Rectangle( 5 * TILE_W,  0 * TILE_W, TILE_W, TILE_W);
    static public const RECT_STEEL_RorU        :Rectangle = new Rectangle( 7 * TILE_W,  0 * TILE_W, TILE_W, TILE_W);
    static public const RECT_STEEL_LorD        :Rectangle = new Rectangle( 5 * TILE_W,  2 * TILE_W, TILE_W, TILE_W);
    static public const RECT_STEEL_RorD        :Rectangle = new Rectangle( 7 * TILE_W,  2 * TILE_W, TILE_W, TILE_W);
    static public const RECT_STEEL_LandU    :Rectangle = new Rectangle( 8 * TILE_W,  0 * TILE_W, TILE_W, TILE_W);
    static public const RECT_STEEL_RandU    :Rectangle = new Rectangle( 9 * TILE_W,  0 * TILE_W, TILE_W, TILE_W);
    static public const RECT_STEEL_LandD    :Rectangle = new Rectangle( 8 * TILE_W,  1 * TILE_W, TILE_W, TILE_W);
    static public const RECT_STEEL_RandD    :Rectangle = new Rectangle( 9 * TILE_W,  1 * TILE_W, TILE_W, TILE_W);
    static public const RECT_NEEDLE_L        :Rectangle = new Rectangle( 5 * TILE_W,  4 * TILE_W, TILE_W, TILE_W);
    static public const RECT_NEEDLE_R        :Rectangle = new Rectangle( 7 * TILE_W,  4 * TILE_W, TILE_W, TILE_W);
    static public const RECT_NEEDLE_U        :Rectangle = new Rectangle( 6 * TILE_W,  3 * TILE_W, TILE_W, TILE_W);
    static public const RECT_NEEDLE_D        :Rectangle = new Rectangle( 6 * TILE_W,  5 * TILE_W, TILE_W, TILE_W);
    static public const RECT_NEEDLE_LorU    :Rectangle = new Rectangle( 5 * TILE_W,  3 * TILE_W, TILE_W, TILE_W);
    static public const RECT_NEEDLE_RorU    :Rectangle = new Rectangle( 7 * TILE_W,  3 * TILE_W, TILE_W, TILE_W);
    static public const RECT_NEEDLE_LorD    :Rectangle = new Rectangle( 5 * TILE_W,  5 * TILE_W, TILE_W, TILE_W);
    static public const RECT_NEEDLE_RorD    :Rectangle = new Rectangle( 7 * TILE_W,  5 * TILE_W, TILE_W, TILE_W);


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


    //Static Init
    static public function Init(in_Graphic:DisplayObject):void
    {
        var x:int, y:int, i:int, j:int, index:int, SrcRect:Rectangle;

        //m_BitmapData_Ori
        {
            m_BitmapData_Ori = new BitmapData(256, 256, true, 0x00000000);
            m_BitmapData_Ori.draw(in_Graphic);
        }

        //DashPanel
        {
            for(i = 0; i < 4; ++i){
                SrcRect = new Rectangle(16*10, 0, 32, 32);
                if((i & 1) != 0){SrcRect.x += 32;}
                if((i & 2) != 0){SrcRect.y += 32;}
                m_BitmapData_DashPanel[i] = new BitmapData(32, 32, true, 0x00000000);
                m_BitmapData_DashPanel[i].copyPixels(m_BitmapData_Ori, SrcRect, POS_ZERO);
            }
        }

        //Breakable Box
        {
            SrcRect = new Rectangle(16*14, 0, 32, 32);
            m_BitmapData_BreakableBox = new BitmapData(32, 32, true, 0x00000000);
            m_BitmapData_BreakableBox.copyPixels(m_BitmapData_Ori, SrcRect, POS_ZERO);
        }

        //Player
        {
            SrcRect = new Rectangle(0, 16*6, 32, 32);
            m_BitmapData_Player = new BitmapData(32, 32, true, 0x00000000);
            m_BitmapData_Player.copyPixels(m_BitmapData_Ori, SrcRect, POS_ZERO);
        }

        //Goal
        {
            SrcRect = new Rectangle(16*14, 32, 32, 32);
            m_BitmapData_Goal = new BitmapData(32, 32, true, 0x00000000);
            m_BitmapData_Goal.copyPixels(m_BitmapData_Ori, SrcRect, POS_ZERO);
        }

        //m_Rect_Ground
        {
            m_Rect_Ground = new Vector.<Vector.<Rectangle> >(16);

            for(i = 0; i < 16; ++i){
                m_Rect_Ground[i] = new Vector.<Rectangle>(4);

                switch(i){
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                    //Empty
                    for(j = 0; j < 4; ++j){
                        m_Rect_Ground[i][j] = RECT_EMPTY;
                    }
                    break;

                case 8:
                case 9:
                    //XorY
                    m_Rect_Ground[i][0] = RECT_WALL_LorU;
                    m_Rect_Ground[i][1] = RECT_WALL_RorU;
                    m_Rect_Ground[i][2] = RECT_WALL_LorD;
                    m_Rect_Ground[i][3] = RECT_WALL_RorD;
                    break;

                case 10:
                case 11:
                    //X
                    m_Rect_Ground[i][0] = RECT_WALL_L;
                    m_Rect_Ground[i][1] = RECT_WALL_R;
                    m_Rect_Ground[i][2] = RECT_WALL_L;
                    m_Rect_Ground[i][3] = RECT_WALL_R;
                    break;

                case 12:
                case 13:
                    //U
                    m_Rect_Ground[i][0] = RECT_WALL_U;
                    m_Rect_Ground[i][1] = RECT_WALL_U;
                    m_Rect_Ground[i][2] = RECT_WALL_D;
                    m_Rect_Ground[i][3] = RECT_WALL_D;
                    break;

                case 14:
                    //XandY
                    m_Rect_Ground[i][0] = RECT_WALL_LandU;
                    m_Rect_Ground[i][1] = RECT_WALL_RandU;
                    m_Rect_Ground[i][2] = RECT_WALL_LandD;
                    m_Rect_Ground[i][3] = RECT_WALL_RandD;
                    break;

                case 15:
                    //Default
                    for(j = 0; j < 4; ++j){
                        m_Rect_Ground[i][j] = RECT_WALL;
                    }
                    break;
                }
            }
        }

        //m_Rect_Block
        {
            m_Rect_Block = new Vector.<Vector.<Rectangle> >(16);

            for(i = 0; i < 16; ++i){
                m_Rect_Block[i] = new Vector.<Rectangle>(4);

                switch(i){
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                    //Empty
                    for(j = 0; j < 4; ++j){
                        m_Rect_Block[i][j] = RECT_EMPTY;
                    }
                    break;

                case 8:
                case 9:
                    //XorY
                    m_Rect_Block[i][0] = RECT_BLOCK_LorU;
                    m_Rect_Block[i][1] = RECT_BLOCK_RorU;
                    m_Rect_Block[i][2] = RECT_BLOCK_LorD;
                    m_Rect_Block[i][3] = RECT_BLOCK_RorD;
                    break;

                case 10:
                case 11:
                    //X
                    m_Rect_Block[i][0] = RECT_BLOCK_L;
                    m_Rect_Block[i][1] = RECT_BLOCK_R;
                    m_Rect_Block[i][2] = RECT_BLOCK_L;
                    m_Rect_Block[i][3] = RECT_BLOCK_R;
                    break;

                case 12:
                case 13:
                    //U
                    m_Rect_Block[i][0] = RECT_BLOCK_U;
                    m_Rect_Block[i][1] = RECT_BLOCK_U;
                    m_Rect_Block[i][2] = RECT_BLOCK_D;
                    m_Rect_Block[i][3] = RECT_BLOCK_D;
                    break;

                case 14:
                    //XandY
                    m_Rect_Block[i][0] = RECT_BLOCK_LandU;
                    m_Rect_Block[i][1] = RECT_BLOCK_RandU;
                    m_Rect_Block[i][2] = RECT_BLOCK_LandD;
                    m_Rect_Block[i][3] = RECT_BLOCK_RandD;
                    break;

                case 15:
                    //Default
                    for(j = 0; j < 4; ++j){
                        m_Rect_Block[i][j] = RECT_BLOCK;
                    }
                    break;
                }
            }
        }

        //m_Rect_Needle
        {
            m_Rect_Needle = new Vector.<Vector.<Rectangle> >(16);

            for(i = 0; i < 16; ++i){
                m_Rect_Needle[i] = new Vector.<Rectangle>(4);

                switch(i){
                case 0:
                case 1:
                    //Empty
                    for(j = 0; j < 4; ++j){
                        m_Rect_Needle[i][j] = RECT_EMPTY;
                    }
                    break;

                case 2:
                case 3:
                    //NeedleY
                    m_Rect_Needle[i][0] = RECT_NEEDLE_U;
                    m_Rect_Needle[i][1] = RECT_NEEDLE_U;
                    m_Rect_Needle[i][2] = RECT_NEEDLE_D;
                    m_Rect_Needle[i][3] = RECT_NEEDLE_D;
                    break;
                case 4:
                case 5:
                    //NeedleX
                    m_Rect_Needle[i][0] = RECT_NEEDLE_L;
                    m_Rect_Needle[i][1] = RECT_NEEDLE_R;
                    m_Rect_Needle[i][2] = RECT_NEEDLE_L;
                    m_Rect_Needle[i][3] = RECT_NEEDLE_R;
                    break;
                case 6:
                case 7:
                    //NeedleXorY
                    m_Rect_Needle[i][0] = RECT_NEEDLE_LorU;
                    m_Rect_Needle[i][1] = RECT_NEEDLE_RorU;
                    m_Rect_Needle[i][2] = RECT_NEEDLE_LorD;
                    m_Rect_Needle[i][3] = RECT_NEEDLE_RorD;
                    break;

                case 8:
                case 9:
                    //XorY
                    m_Rect_Needle[i][0] = RECT_STEEL_LorU;
                    m_Rect_Needle[i][1] = RECT_STEEL_RorU;
                    m_Rect_Needle[i][2] = RECT_STEEL_LorD;
                    m_Rect_Needle[i][3] = RECT_STEEL_RorD;
                    break;

                case 10:
                case 11:
                    //X
                    m_Rect_Needle[i][0] = RECT_STEEL_L;
                    m_Rect_Needle[i][1] = RECT_STEEL_R;
                    m_Rect_Needle[i][2] = RECT_STEEL_L;
                    m_Rect_Needle[i][3] = RECT_STEEL_R;
                    break;

                case 12:
                case 13:
                    //U
                    m_Rect_Needle[i][0] = RECT_STEEL_U;
                    m_Rect_Needle[i][1] = RECT_STEEL_U;
                    m_Rect_Needle[i][2] = RECT_STEEL_D;
                    m_Rect_Needle[i][3] = RECT_STEEL_D;
                    break;

                case 14:
                    //XandY
                    m_Rect_Needle[i][0] = RECT_STEEL_LandU;
                    m_Rect_Needle[i][1] = RECT_STEEL_RandU;
                    m_Rect_Needle[i][2] = RECT_STEEL_LandD;
                    m_Rect_Needle[i][3] = RECT_STEEL_RandD;
                    break;

                case 15:
                    //Default
                    for(j = 0; j < 4; ++j){
                        m_Rect_Needle[i][j] = RECT_STEEL;
                    }
                    break;
                }
            }
        }
    }



    //==BG==
    static public function CreateBackGroundGraphic(in_Map:Array):Bitmap
    {
        //Alias
        var NumX:int = in_Map[0].length;
        var NumY:int = in_Map.length;

        //最終的な画像
        var bmd:BitmapData = new BitmapData(NumX * PANEL_W, NumY * PANEL_W, true, 0x00000000);

        bmd.lock();

        //まずは遠景でクリア
        FillBG(bmd);

        //トゲ描画
        DrawNeedle(bmd, in_Map);

        //地形描画
        DrawGround(bmd, in_Map);

        bmd.unlock();

        return new Bitmap(bmd);

    }
    //遠景によるクリア
    static public function FillBG(io_BMD:BitmapData):void
    {
        var W:int = io_BMD.width;
        var H:int = io_BMD.height;

        var SrcRect:Rectangle = RECT_BG;
        var DstPoint:Point = new Point();
        for(var yy:int = 0; yy < H; yy += TILE_W){
            DstPoint.y = yy;
            for(var xx:int = 0; xx < W; xx += TILE_W){
                DstPoint.x = xx;
                io_BMD.copyPixels(m_BitmapData_Ori, SrcRect, DstPoint, null, null, true);
            }
        }
    }
    //トゲ描画
    static public function DrawNeedle(io_BMD:BitmapData, in_Map:Array):void
    {
        //Alias
        var NumX:int = in_Map[0].length;
        var NumY:int = in_Map.length;

        var xx:int, yy:int, i:int;

        //Map => Bitmap_Base
        //Mapの要素を元に、「0:空白」「1:地形」というBitmapを生成
        var BitmapData_Base:BitmapData;
        {
            BitmapData_Base = new BitmapData(NumX, NumY, false, 0x0);
            BitmapData_Base.lock();
            for(yy = 0; yy < NumY; yy++){
                for(xx = 0; xx < NumX; xx++){
                    switch(in_Map[yy][xx]){
                    case ActGameEngine.X:
                        BitmapData_Base.setPixel(xx, yy, 1);
                        break;
                    }
                }
            }
        }

        //Bitmap_Base => Bitmap_LU,Bitmap_RU,Bitmap_LD,Bitmap_RD
        //Bitmap_Baseを元に、四隅の隣接状況をそれぞれ求める(Uniqueな値になるようにする)
        //Uniqueな値から、対応するIndexへと変換する
        var BitmapData_Quater:Vector.<BitmapData> = new Vector.<BitmapData>(4);
        {
            var rect:Rectangle = BitmapData_Base.rect;

            //
            for(i = 0; i < 4; i++){
                //Init
                var bmd:BitmapData = new BitmapData(NumX, NumY, false, 0x000000);
                bmd.lock();

                bmd.applyFilter(BitmapData_Base, rect, POS_ZERO, m_ConvFilter[i]);

                BitmapData_Quater[i] = bmd;
            }
        }

        //Draw
        //上で求めたIndexに基づき描画
        {
            var DstPoint:Point = new Point(0,0);
            var SrcRect:Rectangle = new Rectangle(0,0,TILE_W,TILE_W);
            for(yy = 0; yy < NumY; yy++){
                for(xx = 0; xx < NumX; xx++){
                    for(i = 0; i < 4; i++){
                        DstPoint.x = xx * PANEL_W + ((i&1)>>0) * TILE_W;
                        DstPoint.y = yy * PANEL_W + ((i&2)>>1) * TILE_W;

                        SrcRect = m_Rect_Needle[BitmapData_Quater[i].getPixel(xx, yy)][i];

                        io_BMD.copyPixels(m_BitmapData_Ori, SrcRect, DstPoint, null, null, true);
                    }
                }
            }
        }
    }
    //地形描画
    static public function DrawGround(io_BMD:BitmapData, in_Map:Array):void
    {
        //Alias
        var NumX:int = in_Map[0].length;
        var NumY:int = in_Map.length;

        var xx:int, yy:int, i:int;

        //Map => Bitmap_Base
        //Mapの要素を元に、「0:空白」「1:地形」というBitmapを生成
        var BitmapData_Base:BitmapData;
        {
            BitmapData_Base = new BitmapData(NumX, NumY, false, 0x0);
            BitmapData_Base.lock();
            for(yy = 0; yy < NumY; yy++){
                for(xx = 0; xx < NumX; xx++){
                    switch(in_Map[yy][xx]){
                    case ActGameEngine.W:
                    case ActGameEngine.DU:
                    case ActGameEngine.DD:
                    case ActGameEngine.DL:
                    case ActGameEngine.DR:
                        BitmapData_Base.setPixel(xx, yy, 1);
                        break;
                    }
                }
            }
        }

        //Bitmap_Base => Bitmap_LU,Bitmap_RU,Bitmap_LD,Bitmap_RD
        //Bitmap_Baseを元に、四隅の隣接状況をそれぞれ求める(Uniqueな値になるようにする)
        //Uniqueな値から、対応するIndexへと変換する
        var BitmapData_Quater:Vector.<BitmapData> = new Vector.<BitmapData>(4);
        {
            var rect:Rectangle = BitmapData_Base.rect;

            //
            for(i = 0; i < 4; i++){
                //Init
                var bmd:BitmapData = new BitmapData(NumX, NumY, false, 0x000000);
                bmd.lock();

                bmd.applyFilter(BitmapData_Base, rect, POS_ZERO, m_ConvFilter[i]);

                BitmapData_Quater[i] = bmd;
            }
        }

        //Draw
        //上で求めたIndexに基づき描画
        {
            var DstPoint:Point = new Point(0,0);
            var SrcRect:Rectangle = new Rectangle(0,0,TILE_W,TILE_W);
            for(yy = 0; yy < NumY; yy++){
                for(xx = 0; xx < NumX; xx++){
                    for(i = 0; i < 4; i++){
                        DstPoint.x = xx * PANEL_W + ((i&1)>>0) * TILE_W;
                        DstPoint.y = yy * PANEL_W + ((i&2)>>1) * TILE_W;

                        SrcRect = m_Rect_Ground[BitmapData_Quater[i].getPixel(xx, yy)][i];

                        io_BMD.copyPixels(m_BitmapData_Ori, SrcRect, DstPoint, null, null, true);
                    }
                }
            }
        }
    }


    //==Block==
    static public function CreateBlockGraphic(in_Map:Array):Bitmap
    {
        //Alias
        var NumX:int = in_Map[0].length;
        var NumY:int = in_Map.length;

        //最終的な画像
        var bmd:BitmapData = new BitmapData(NumX * PANEL_W, NumY * PANEL_W, true, 0x00000000);

        bmd.lock();

        //ブロック描画
        DrawBlock(bmd, in_Map);

        bmd.unlock();

        return new Bitmap(bmd);

    }
    //ブロック描画
    static public function DrawBlock(io_BMD:BitmapData, in_Map:Array):void
    {
        //Alias
        var NumX:int = in_Map[0].length;
        var NumY:int = in_Map.length;

        var xx:int, yy:int, i:int;

        //Map => Bitmap_Base
        //Mapの要素を元に、「0:空白」「1:地形」というBitmapを生成
        var BitmapData_Base:BitmapData;
        {
            BitmapData_Base = new BitmapData(NumX, NumY, false, 0x0);
            BitmapData_Base.lock();
            for(yy = 0; yy < NumY; yy++){
                for(xx = 0; xx < NumX; xx++){
                    switch(in_Map[yy][xx]){
                    case ActGameEngine.L:
                        BitmapData_Base.setPixel(xx, yy, 1);
                        break;
                    }
                }
            }
        }

        //Bitmap_Base => Bitmap_LU,Bitmap_RU,Bitmap_LD,Bitmap_RD
        //Bitmap_Baseを元に、四隅の隣接状況をそれぞれ求める(Uniqueな値になるようにする)
        //Uniqueな値から、対応するIndexへと変換する
        var BitmapData_Quater:Vector.<BitmapData> = new Vector.<BitmapData>(4);
        {
            var rect:Rectangle = BitmapData_Base.rect;

            //
            for(i = 0; i < 4; i++){
                //Init
                var bmd:BitmapData = new BitmapData(NumX, NumY, false, 0x000000);
                bmd.lock();

                bmd.applyFilter(BitmapData_Base, rect, POS_ZERO, m_ConvFilter[i]);

                BitmapData_Quater[i] = bmd;
            }
        }

        //Draw
        //上で求めたIndexに基づき描画
        {
            var DstPoint:Point = new Point(0,0);
            var SrcRect:Rectangle = new Rectangle(0,0,TILE_W,TILE_W);
            for(yy = 0; yy < NumY; yy++){
                for(xx = 0; xx < NumX; xx++){
                    for(i = 0; i < 4; i++){
                        DstPoint.x = xx * PANEL_W + ((i&1)>>0) * TILE_W;
                        DstPoint.y = yy * PANEL_W + ((i&2)>>1) * TILE_W;

                        SrcRect = m_Rect_Block[BitmapData_Quater[i].getPixel(xx, yy)][i];

                        io_BMD.copyPixels(m_BitmapData_Ori, SrcRect, DstPoint, null, null, true);
                    }
                }
            }
        }
    }


    //==Player==

    static public function GetPlayerGraphic():BitmapData{
        return m_BitmapData_Player;
    }


    //==Goal==

    static public function CreateGoalGraphic():Bitmap{
        return new Bitmap(m_BitmapData_Goal);
    }


    //==Dash Panel==

    static public function GetDashPanelGraphic(in_MapVal:int):BitmapData{
        switch(in_MapVal){
        case ActGameEngine.DU:
            return m_BitmapData_DashPanel[0];
        case ActGameEngine.DD:
            return m_BitmapData_DashPanel[1];
        case ActGameEngine.DL:
            return m_BitmapData_DashPanel[2];
        case ActGameEngine.DR:
            return m_BitmapData_DashPanel[3];
        }

        return null;
    }

    //==Breakable Box==

    static public function GetBreakableBoxGraphic():BitmapData{
        return m_BitmapData_BreakableBox;
    }
}