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

ローリングおじいちゃん(Rollin' Grandpa)

操作方法(How to Play)
- Android:加速度センサー(Accelerometer)
-- ただし実機がないのでまだ確認できてない
- PC:マウス(Mouse)

素材(キャラクター)
- First Seed Material
-- http://www.tekepon.net/fsm/
/**
 * 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/lpJt
 */

/*
 「ローリングおじいちゃん(Rollin' Grandpa)」
 - Android用のBall&Mazeを拡張してみたもの

 操作方法(How to Play)
 - Android:加速度センサー(Accelerometer)
 -- ただし実機がないのでまだ確認できてない
 - PC:マウス(Mouse)

 Box2Dについて補足
 - b2ContactListenerを使ってみた。衝突とかにコールバックを仕込めるので楽。
 - isSensorを使ってみた。「物体」ではなく「領域」としてコリジョンを生成できる。衝突時にはコールバックのみが反応し、排斥処理は行われない。

 素材(キャラクター)
 - First Seed Material
 -- http://www.tekepon.net/fsm/
*/


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

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

    [SWF(width="465", height="465", frameRate="30", backgroundColor="0x004400")]
    public class GameMain extends Sprite {
        //==Const==

        //画像ファイル名
//*
        static public const URL_BLOCKS:String = "http://assets.wonderfl.net/images/related_images/c/cd/cdde/cdde14248108db9327a151f43ac41fa70b897c11";
        static public const URL_PLAYER:String = "http://assets.wonderfl.net/images/related_images/9/99/99a4/99a4cc29134f5e179d52c4b3d446e9cdf592a3a3";
/*/
        static public const URL_BLOCKS:String = "Blocks.png";
        static public const URL_PLAYER:String = "Player.png";
//*/

        //画面サイズ
        static public const VIEW_W:int = 465;
        static public const VIEW_H:int = 465;

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

        //画像サイズ
        static public const PANEL_W:int = 24;
        static public const PANEL_H:int = 32;
        static public const PANEL_NUM_X:int = 3;
        static public const PANEL_NUM_Y:int = 4;

        //マップ要素
        static public var MapIndexIter:int = 0;
        static public const O:int = MapIndexIter++;
        static public const W:int = MapIndexIter++;
        static public const X:int = MapIndexIter++;
        static public const P:int = MapIndexIter++;
        static public const G:int = MapIndexIter++;

        //マップ
        static public const MAP:Array = [//カメラ対応のためWで全体を覆ってるのがややムダくさい
            [W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,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,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,O,O,O,O,O,W,O,O,O,O,O,O,O,X,W,X,O,O,O,O,O,O,O,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,O,O,O,O,O,W,O,W,O,O,O,O,O,X,W,X,O,O,O,O,O,W,O,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,O,O,P,O,O,W,O,W,O,O,O,O,O,X,W,X,O,O,O,O,O,X,O,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,O,O,O,O,O,W,O,W,O,O,O,O,O,W,W,W,O,O,O,O,O,X,O,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,O,O,O,O,O,O,O,W,O,O,O,O,O,O,O,O,O,O,O,O,O,X,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,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,O,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,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,O,O,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,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,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,X,O,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,X,X,X,X,X,X,X,X,X,X,X,W,W,W,W,W,W,W,W,W,W,W,X,O,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,X,O,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,X,O,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,X,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W,O,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,X,O,O,O,X,X,X,X,X,X,X,X,X,X,X,W,O,O,O,O,O,O,W,O,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,X,O,O,O,O,O,O,O,O,O,O,O,O,O,X,W,O,O,O,O,O,O,W,O,X,W,W,W,W,W,W],
            [W,W,W,W,W,W,X,O,O,O,O,O,O,O,O,O,O,O,O,O,X,W,X,X,O,O,X,X,W,O,X,W,W,W,W,W,W],
            [W,W,W,W,W,W,X,X,X,X,X,X,X,X,X,X,X,X,O,O,X,W,O,O,O,O,O,O,W,O,X,W,W,W,W,W,W],
            [W,W,W,W,W,W,X,O,O,O,O,X,O,O,O,O,O,X,O,O,X,W,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,X,O,O,O,O,O,O,O,O,O,O,O,O,O,X,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,X,O,O,O,O,O,O,O,X,O,O,O,O,O,X,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,X,X,O,O,O,X,X,X,X,X,X,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,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,W,W,W,W,W,W,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,W,W,W,W,W,W,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,W,W,W,W,W,W,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,W,W,W,W,W,W,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,W,W,W,W,W,W,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,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,O,G,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,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,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,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
            [W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
        ];

        //マップのパネル数
        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 = MAP_NUM_X * PANEL_LEN;
        static public const MAP_H:int = MAP_NUM_Y * PANEL_LEN;

        //Box2Dと実際の表示の比率(Box2Dに大きすぎる値を入れると上手く動かなかったりする)
        static public const PHYS_SCALE:Number = 10;
        static public function PHYS_to_IMAGE(in_Val:Number):Number{return in_Val * PHYS_SCALE;}
        static public function IMAGE_to_PHYS(in_Val:Number):Number{return in_Val / PHYS_SCALE;}
        //Box2Dの画面外の余白
        static public const BOX2D_RANGE_OFFSET:int = 100;

        //モード
        static public var ModeIter:int = 0;
        static public const MODE_MAIN:int    = ModeIter++;
        static public const MODE_GOAL:int    = ModeIter++;
        static public const MODE_GAME_OVER:int    = ModeIter++;


        //==Var==

        //Pseudo Singleton
        static public var Instance:GameMain;

        //マップ(プレイヤーなどを地面に置き換えたりしたもの)
        public var m_Map:Vector.<Vector.<int> >;

        //プレイヤーの初期位置
        public var m_PlayerX:int = 2.5*PANEL_LEN;//一応それっぽい位置に初期化
        public var m_PlayerY:int = 2.5*PANEL_LEN;

        //ゴールの初期位置
        public var m_GoalX:int = 0.5*PANEL_LEN;//一応それっぽい位置に初期化
        public var m_GoalY:int = 0.5*PANEL_LEN;

        //レイヤー
        public var m_Layer_Root:Sprite = new Sprite();//Root
        public var  m_Layer_Ground:Sprite = new Sprite();//地面用レイヤー
        public var  m_Layer_Obj:Sprite = new Sprite();//通常表示用レイヤー
        public var  m_Layer_Debug:Sprite = new Sprite();//デバッグ描画用
        public var m_Layer_HUD:Sprite = new Sprite();//情報表示用レイヤー

        //地形画像
        public var m_BitmapData_Floor:BitmapData = new BitmapData(MAP_W, MAP_H, true, 0x00000000);

        //トゲ判定のためのダミーSprite
        public var m_NeedleSprite:Sprite = new Sprite();


        //プレイヤー
        public var m_Player:Player;

        //ゴール
        public var m_Goal:Goal;

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

        //モード
        public var m_Mode:int = MODE_MAIN;


        //Box2D
        public var m_Box2D_World:b2World;


        //==Function==

        //Init
        public function GameMain(){
            var x:int;
            var y:int;

            //Pseudo Singleton
            {
                Instance = this;
            }

            //Common
            {
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
            }

            //Static Init
            {
                ImageManager.Init();
                Player.Initialize();
            }

            //MAP => m_Map
            {
                m_Map = new Vector.<Vector.<int> >(MAP_NUM_Y);
                for(y = 0; y < MAP_NUM_Y; y++){
                    m_Map[y] = new Vector.<int>(MAP_NUM_X);
                    var PosY:int = (y+0.5) * PANEL_LEN;
                    for(x = 0; x < MAP_NUM_X; x++){
                        var PosX:int = (x+0.5) * PANEL_LEN;
                        var index:int = MAP[y][x];

                        switch(index){
                        case P:
                            index = O;//プレイヤーの居た位置は地面扱いする
                            m_PlayerX = PosX;
                            m_PlayerY = PosY;
                            break;
                        case G:
                            index = O;//ゴールのある位置は地面扱いする
                            m_GoalX = PosX;
                            m_GoalY = PosY;
                            break;
                        }

                        m_Map[y][x] = index;
                    }
                }
            }

            //Box2D
            {
                //考慮する領域
                var worldAABB:b2AABB = new b2AABB();
                worldAABB.lowerBound.Set(IMAGE_to_PHYS(-BOX2D_RANGE_OFFSET), IMAGE_to_PHYS(-BOX2D_RANGE_OFFSET));
                worldAABB.upperBound.Set(IMAGE_to_PHYS(MAP_W+BOX2D_RANGE_OFFSET), IMAGE_to_PHYS(MAP_H+BOX2D_RANGE_OFFSET));
                //重力ベクトル
                var gravity:b2Vec2 = new b2Vec2(0, 0);
                //Sleep
                var useSleep:Boolean = true;
                //物理world
                m_Box2D_World = new b2World(worldAABB, gravity, useSleep);

                //ContactListener
                m_Box2D_World.SetContactListener(new ContactListener());
            }

            //地形コリジョン
            {
                Init_Terrain_Collision();
            }

            //Layer
            {
                addChild(m_Layer_Root);
                {
                    m_Layer_Root.addChild(m_Layer_Ground);
                    m_Layer_Root.addChild(m_Layer_Obj);
                    m_Layer_Root.addChild(m_Layer_Debug);
                }

                addChild(m_Layer_HUD);
            }

            //地形
            {
                ImageManager.Map_to_Bitmap(
                    m_Map,
                    m_BitmapData_Floor
                );

                var bmp:Bitmap;

                //Floor
                {
                    bmp = new Bitmap(m_BitmapData_Floor);
                    m_Layer_Ground.addChild(bmp);
                }
            }

            //ゴール
            {
                m_Goal = new Goal();

                m_Layer_Obj.addChild(m_Goal);
            }

            //プレイヤー
            {
                m_Player = new Player();

                m_Layer_Obj.addChild(m_Player);
            }

            //Text
            {
                m_Text.selectable = false;
                m_Text.autoSize = TextFieldAutoSize.LEFT;
                m_Text.defaultTextFormat = new TextFormat('Verdana', 60, 0xFFFF00, true);
                m_Text.text = '';
                m_Text.filters = [new GlowFilter(0xFF0000,1.0, 8,8)];

                addChild(m_Text);
            }

            //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);
            }

            //残りはResetと同じ処理
            {
                Reset();
            }

/*
            //Debug
            {
                var debugDraw:b2DebugDraw = new b2DebugDraw();
                debugDraw.m_sprite = m_Layer_Debug;//this;
                debugDraw.m_drawScale = PHYS_SCALE;
                debugDraw.m_fillAlpha = 0.6;
                debugDraw.m_lineThickness = 1;
                debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
                m_Box2D_World.SetDebugDraw(debugDraw);
            }
//*/
        }

        //Reset
        public function Reset():void{
            //プレイヤー
            {
                m_Player.SetPos(m_PlayerX, m_PlayerY);
            }

            //ゴール
            {
                m_Goal.SetPos(m_GoalX, m_GoalY);
            }
        }

        //Init : Terrain Collision
        public function Init_Terrain_Collision():void{
            var x:int;
            var y:int;
            var r:Rectangle;

            //準備:トゲ判定
            const NEEDLE_W:Number = 0.5*PANEL_LEN * 1.1;
            var body_needle:b2Body;
            var shapeDef_needle:b2PolygonDef;
            {
                //まずはトゲ用のBodyを一つだけ作成
                //var body_needle:b2Body;
                {
                    body_needle = m_Box2D_World.CreateBody(new b2BodyDef());
                    body_needle.SetUserData(m_NeedleSprite);
                }

                //作成するShapeのベースを作成
                //var shapeDef_needle:b2PolygonDef;
                {
                    shapeDef_needle = new b2PolygonDef();
                    shapeDef_needle.density = 0;//Fix
                    shapeDef_needle.isSensor = true;
                }
            }

            //コリジョンリスト
            var RectList:Vector.<Rectangle> = new Vector.<Rectangle>();
            {
                //現在の行のコリジョン
                var RectList_Now:Vector.<Rectangle> = new Vector.<Rectangle>(MAP_NUM_X);
                //結合するため、一時的に溜めておく
                var RectList_Pre:Vector.<Rectangle> = new Vector.<Rectangle>(MAP_NUM_X);

                for(y = 0; y < MAP_NUM_Y; y++){
                    var PosY:int = (y+0.5) * PANEL_LEN;
                    r = null;

                    //まずはこの行のまとめられるところをまとめる
                    for(x = 0; x < MAP_NUM_X; x++){
                        var PosX:int = (x+0.5) * PANEL_LEN;
                        var index:int = m_Map[y][x];

                        switch(index){
                        case X:
                            index = W;//壁として一体化する
                            //トゲ判定を追加する
                            shapeDef_needle.SetAsOrientedBox(IMAGE_to_PHYS(NEEDLE_W), IMAGE_to_PHYS(NEEDLE_W), new b2Vec2(IMAGE_to_PHYS(PosX), IMAGE_to_PHYS(PosY)));
                            body_needle.CreateShape(shapeDef_needle);
                            break;
                        }

                        if(index == W){
                            if(r == null){
                                r = new Rectangle(x*PANEL_LEN, y*PANEL_LEN, PANEL_LEN, PANEL_LEN);
                                RectList_Now[x] = r;
                            }else{
                                r.width += PANEL_LEN;
                            }
                        }else{
                            r = null;
                        }
                    }

                    //前回の結果と統合できるなら統合する
                    for(x = 0; x < MAP_NUM_X; x++){
                        if(RectList_Pre[x] != null){//前回の結果と
                            if(RectList_Now[x] != null){//今回の結果で同じ始点のものがあり
                                if(RectList_Pre[x].width == RectList_Now[x].width){//幅が同じなら
                                    //統合する
                                    RectList_Pre[x].height += PANEL_LEN;
                                    RectList_Now[x] = null;
                                    continue;
                                }
                            }

                            //前回の結果が統合できない場合、もう統合することもないのでResultに入れてしまう
                            RectList.push(RectList_Pre[x]);
                        }

                        //今回の結果を前回の結果の方に移す
                        RectList_Pre[x] = RectList_Now[x];
                        RectList_Now[x] = null;
                    }
                }

                //残っているやつをResultに移す
                for(x = 0; x < MAP_NUM_X; x++){
                    if(RectList_Pre[x] != null){
                        RectList.push(RectList_Pre[x]);
                    }
                }
            }

            //実際に作成
            {
                //まずは地形用のBodyを一つだけ作成
                var body:b2Body;
                {
                    body = m_Box2D_World.CreateBody(new b2BodyDef());
                }

                //作成するShapeのベースを作成
                var shapeDef:b2PolygonDef;
                {
                    shapeDef = new b2PolygonDef();
                    shapeDef.density = 0;//Fix
                    shapeDef.friction = 1;
                }

                //あとはリストの形状を追加していく
                var w:Number;
                var h:Number;
                var center:b2Vec2 = new b2Vec2();
                var ColNum:int = RectList.length;
                for(var i:int = 0; i < ColNum; i++){
                    r = RectList[i];

                    w = IMAGE_to_PHYS(r.width/2);
                    h = IMAGE_to_PHYS(r.height/2);
                    center.x = IMAGE_to_PHYS(r.x) + w;
                    center.y = IMAGE_to_PHYS(r.y) + h;

                    shapeDef.SetAsOrientedBox(w, h, center);
                    body.CreateShape(shapeDef);
                }

                //一応、追加したShapeに合わせてMassを計算(Fixなので不要かもしれない)
                body.SetMassFromShapes();
            }

/*
            //Debug
            var sprite:Sprite = new Sprite();
            m_Layer_Debug.addChild(sprite);
            var g:Graphics = sprite.graphics;
            g.lineStyle(3,0x00FFFF,1.0);
            for(i = 0; i < ColNum; i++){
                r = RectList[i];

                g.drawRect(r.x, r.y, r.width, r.height);
            }
//*/
        }

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

            //今の表示のスクリーンショットを撮っておいて、α減衰させつつ画像表示に移行させてみる
            {
                var bmd:BitmapData = new BitmapData(VIEW_W, VIEW_H, false, 0x000000);
                bmd.draw(m_Layer_Root, new Matrix(1,0,0,1, m_Layer_Root.x,m_Layer_Root.y));

                var bmp:Bitmap = new Bitmap(bmd);
                addChild(bmp);

                addEventListener(Event.ENTER_FRAME, function f(e:Event):void{
                    var DeltaAlpha:Number = 5 * 1.0/30.0;
                    bmp.alpha -= DeltaAlpha;
                    if(bmp.alpha <= 0){
                        removeChild(bmp);
                        removeEventListener(Event.ENTER_FRAME, f);
                    }
                });
            }

            //ブロック描画
            {
                ImageManager.Map_to_Bitmap(
                    m_Map,
                    m_BitmapData_Floor
                );
            }
        }

        //OnLoad : Player
        public function OnLoadEnd_Player(in_Graphic:DisplayObject):void{
            var index_x:int;
            var index_y:int;
            var bmd:BitmapData;
            var mtx:Matrix = new Matrix(1,0,0,1, 0,0);
            var rect:Rectangle = new Rectangle(0,0, PANEL_W,PANEL_H);

            //プレイヤー画像
            {
                for(index_x = 0; index_x < PANEL_NUM_X; index_x++){
                    for(index_y = 0; index_y < PANEL_NUM_Y; index_y++){
                        bmd = Player.m_BitmapDataList[index_y][index_x];
                        //Clear
                        //bmd.fillRect(rect, 0x00000000);//円表示のため上書きする
                        //Draw
                        mtx.tx = -index_x*PANEL_W - 4;//微調整
                        mtx.ty = -index_y*PANEL_H - 6;
                        bmd.draw(in_Graphic, mtx);
                    }
                }
            }

            //ゴール画像
            {
                bmd = m_Goal.m_BitmapData;
                mtx.tx = -PANEL_W*0;
                mtx.ty = -PANEL_H*2;
                bmd.fillRect(rect, 0x00000000);
                bmd.draw(in_Graphic, mtx);

                bmd = m_Goal.m_BitmapData_Clear;
                mtx.tx = -PANEL_W*1;
                mtx.ty = -PANEL_H*2;
                bmd.fillRect(rect, 0x00000000);
                bmd.draw(in_Graphic, mtx);
            }
        }


        //Update
        public function Update(e:Event=null):void{
            //Check
            if(IsEnd()){return;}

            //今回進める時間
            var DeltaTime:Number = 1.0/30.0;

            //物理まわりの更新
            Update_Phys(DeltaTime);

            //Player
            m_Player.Update(DeltaTime);

            //Goal
            m_Goal.Update();

            //Camera
            Update_Camera();
        }

        //物理まわりの更新
        public function Update_Phys(in_DeltaTime:Number):void{
            //マウスのところに移動
            //m_MouseJoint.SetTarget(new b2Vec2(IMAGE_to_PHYS(mouseX), IMAGE_to_PHYS(mouseY)));

            //物理エンジンをDeltaTimeだけ進める
            m_Box2D_World.Step(in_DeltaTime, 10);

            //Sync
            for(var b:b2Body = m_Box2D_World.m_bodyList; b; b = b.m_next){
                //画像との同期
                if(b.m_userData != null){
                    var sprite:Sprite = b.m_userData as Sprite;
                    sprite.x = PHYS_to_IMAGE(b.GetPosition().x);
                    sprite.y = PHYS_to_IMAGE(b.GetPosition().y);
                    //b.m_userData.m_VX = PHYS_to_IMAGE(b.m_linearVelocity.x);
                    //b.m_userData.m_VY = PHYS_to_IMAGE(b.m_linearVelocity.y);

                    sprite.rotation = b.GetAngle() * 180/Math.PI;
                }

                //擬似摩擦
                {
                    const Ratio:Number = 0.99;//本当はDeltaTime依存の値にした方が良い
                    b.GetLinearVelocity().x *= Ratio;
                    b.GetLinearVelocity().y *= Ratio;
                    b.SetAngularVelocity(b.GetAngularVelocity() * Ratio);
                }
            }
        }

        //Update : Camera
        public function Update_Camera():void{
            var PlayerX:int = m_Player.x;
            var PlayerY:int = m_Player.y;

            //移動量
            var CameraMoveX:int = 0;
            var CameraMoveY:int = 0;
            {
                //現在のカメラでのプレイヤー相対位置
                var RelPlayerX:Number = PlayerX + m_Layer_Root.x;
                var RelPlayerY:Number = PlayerY + m_Layer_Root.y;

                //中央からの差がそのまま移動量
                CameraMoveX = VIEW_W/2 - RelPlayerX;
                CameraMoveY = VIEW_H/2 - RelPlayerY;
            }

            //目標値
            var RootX:int = m_Layer_Root.x + CameraMoveX;
            var RootY:int = m_Layer_Root.y + CameraMoveY;
            {
                //端制限
                if(RootX < -MAP_W + VIEW_W){
                    RootX = -MAP_W + VIEW_W;
                }
                if(RootX > 0){
                    RootX = 0;
                }
                if(RootY < -MAP_H + VIEW_H + PANEL_LEN){//天井を1パネル上にズラしているので、その分カメラの範囲も狭める
                    RootY = -MAP_H + VIEW_H + PANEL_LEN;
                }
                if(RootY > 0){
                    RootY = 0;
                }
            }

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

        //Goal
        public function OnGoal():void{
            //Mode
            {
                m_Mode = MODE_GOAL;
            }

            //Text
            {
                //Text
                m_Text.text = 'Clear';

                //Centering
                m_Text.x = (stage.stageWidth - m_Text.width) / 2;
                m_Text.y = (stage.stageHeight - m_Text.height) * 4/9;
            }
        }

        //Game Over : Damage
        public function OnDead_Damage():void{
            //Mode
            {
                m_Mode = MODE_GAME_OVER;
            }

            //Text
            {
                //Text
                m_Text.text = 'Game Over';

                //Centering
                m_Text.x = (stage.stageWidth - m_Text.width) / 2;
                m_Text.y = (stage.stageHeight - m_Text.height) / 2;
            }
        }

        //Game Over : Fall
        public function OnDead_Fall():void{
            //Mode
            {
                m_Mode = MODE_GAME_OVER;
            }

            //Text
            {
                //Text
                m_Text.text = 'Game Over';

                //Centering
                m_Text.x = (stage.stageWidth - m_Text.width) / 2;
                m_Text.y = (stage.stageHeight - m_Text.height) / 2;
            }
        }

        //#IsGameOver
        public function IsEnd():Boolean{
            return (m_Mode != MODE_MAIN);
        }
    }
}


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

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

class ContactListener extends b2ContactListener
{
    //衝突が発生した
    override public function Add(in_ContactPoint:b2ContactPoint):void{
        var body1:b2Body = in_ContactPoint.shape1.GetBody();
        var body2:b2Body = in_ContactPoint.shape2.GetBody();

        //ダメージ処理
        {
//*
            var body_needle:b2Body;
            var body_object:b2Body;
            {
                if(body1.GetUserData() == GameMain.Instance.m_NeedleSprite){
                    body_needle = body1;

                    if(body2.IsDynamic()){
                        body_object = body2;
                    }
                }
                if(body2.GetUserData() == GameMain.Instance.m_NeedleSprite){
                    body_needle = body2;

                    if(body1.IsDynamic()){
                        body_object = body1;
                    }
                }
            }

            //if(body_needle && body_object)
            if(body_needle)
            {
                //今は仮ですぐにゲームオーバーにしてしまう
                GameMain.Instance.OnDead_Damage();
            }
//*/
        }
    }
}


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():void{
        var x:int, y:int, i:int;

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

        //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;
            }
        }
    }

    //画像設定
    static public function SetImage(in_Graphic:DisplayObject):void
    {
        m_BitmapData_View.draw(in_Graphic);
    }

    //#Draw : BG
    static public function Map_to_Bitmap(in_Map:Vector.<Vector.<int> >, 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);

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


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

    //重力
    //static public const GRAVITY:Number = 20;
    static public const MOVE_POW:Number = 2000.0;//擬似空気摩擦を考慮して大きめにする

    //アニメーション用定数
    static public const ANIM_DIR_U:int = 0;
    static public const ANIM_DIR_R:int = 1;
    static public const ANIM_DIR_D:int = 2;
    static public const ANIM_DIR_L:int = 3;

    //アニメーション用パラメータ
    static public const ANIM_CYCLE:Number = 1.0;
    static public const ANIM_ITER:Array = [0,1,2,1];
    static public const ANIM_NUM:int = ANIM_ITER.length;


    //==Static==

    //画像
    static public var m_BitmapDataList:Array;

    //Init
    static public function Initialize():void{
        //m_BitmapDataList
        {
            var shape:Shape = new Shape();
            {
                var g:Graphics = shape.graphics;

                g.clear();

                g.lineStyle(2, 0x00FFFF, 0.2);
                g.drawCircle(GameMain.PANEL_W/2, GameMain.PANEL_H/2, GameMain.PANEL_W/2-1);
            }

            m_BitmapDataList = new Array(GameMain.PANEL_NUM_Y);
            for(var y:int = 0; y < GameMain.PANEL_NUM_Y; y++){
                m_BitmapDataList[y] = new Array(GameMain.PANEL_NUM_X);
                for(var x:int = 0; x < GameMain.PANEL_NUM_X; x++){
                    m_BitmapDataList[y][x] = new BitmapData(GameMain.PANEL_W, GameMain.PANEL_H, true, 0x00000000);
                    m_BitmapDataList[y][x].draw(shape);
                }
            }
        }
    }


    //==Var==

    //グラフィック
    public var m_Bitmap:Bitmap = new Bitmap();
    //アニメーションの方向
    public var m_AnimDir:int = ANIM_DIR_R;
    //アニメーション用タイマー
    public var m_AnimTimer:Number = 0.0;

    //死亡フラグ
    public var m_IsDead:Boolean = false;

    //コリジョン
    public var m_Body:b2Body;

    //重力の取り扱い
    public var m_Accel:Accelerometer;
    //重力方向
    public var m_Gravity:Vector3D = new Vector3D(0,0);

    //重力方向の可視化
    public var m_GravityShape:Shape = new Shape();


    //==Function==

    //Init
    public function Player(){
        //プレイヤーグラフィック
        {
            m_Bitmap.x = -GameMain.PANEL_W/2;
            m_Bitmap.y = -GameMain.PANEL_H*9/16;
            addChild(m_Bitmap);
        }

        //コリジョン
        {
            //Shape Def
            var shapeDef:b2CircleDef;
            {
                shapeDef = new b2CircleDef();
                shapeDef.radius = GameMain.IMAGE_to_PHYS(GameMain.PANEL_LEN/2 * 0.9);
                shapeDef.density = 1;//tekitou
                shapeDef.friction = 5;
            }

            //Body Def
            var bodyDef:b2BodyDef;
            {
                bodyDef = new b2BodyDef();
                bodyDef.position.Set(GameMain.IMAGE_to_PHYS(this.x), GameMain.IMAGE_to_PHYS(this.y));
                //bodyDef.fixedRotation = true;
            }

            //Body
            var body:b2Body;
            {
                body = GameMain.Instance.m_Box2D_World.CreateBody(bodyDef);
                body.CreateShape(shapeDef);
                body.SetMassFromShapes();
                body.m_userData = this;
            }

            m_Body = body;
        }

        //加速度センサー
        {
            if(Accelerometer.isSupported){
                m_Accel = new Accelerometer();
                m_Accel.setRequestedUpdateInterval(100);
                m_Accel.addEventListener(AccelerometerEvent.UPDATE, SetGravity_Listener);
            }
        }

        //重力可視化
        {
            GameMain.Instance.m_Layer_HUD.addChild(m_GravityShape);
        }
    }

    //Init : Pos
    public function SetPos(in_X:int, in_Y:int):void{
/*
        this.x = in_X;
        this.y = in_Y;
//*/
        m_Body.SetXForm(new b2Vec2(GameMain.IMAGE_to_PHYS(in_X), GameMain.IMAGE_to_PHYS(in_Y)), 0);
    }

    //Update
    public function Update(in_DeltaTime:Number):void{
        //死亡・ゴール時は何もしない
        if(GameMain.Instance.IsEnd()){
            return;
        }

        //移動
        Update_Move(in_DeltaTime);

        //グラフィック
        Update_Graphic(in_DeltaTime);

        //死亡チェック
        Check_Dead();
    }

    static public const GRAV_LINE_W:int = 4;
    static public const GRAV_LINE_COLOR:uint = 0xFF0000;
    static public const GRAV_LINE_ALPHA:Number = 0.1;
    static public const GRAV_FILL_COLOR:uint = 0x220000;
    static public const GRAV_FILL_ALPHA:Number = 0.1;

    //Update : Graphic
    public function Update_Graphic(in_DeltaTime:Number):void{
        //モーション
        {
            //m_AnimTimer
            {
                m_AnimTimer += in_DeltaTime;
                if(m_AnimTimer > ANIM_CYCLE){m_AnimTimer -= ANIM_CYCLE;}
            }

            //m_AnimTimer => iter
            var iter:int;
            {
                iter = ANIM_ITER[int(ANIM_NUM * m_AnimTimer/ANIM_CYCLE)];
            }

            m_Bitmap.bitmapData = m_BitmapDataList[m_AnimDir][iter];
        }

        //重力の可視化
        {
            var g:Graphics = m_GravityShape.graphics;

            g.clear();
            g.lineStyle(GRAV_LINE_W, GRAV_LINE_COLOR, GRAV_LINE_ALPHA);

            g.beginFill(GRAV_FILL_COLOR, GRAV_FILL_ALPHA);

            //矢印の描画
            {
                const ARROW_LEN:Number = GameMain.VIEW_W/2;//直線の長さっぽいもの
                const ARROW_W:Number = ARROW_LEN/4;//直線の幅っぽいもの
                const DELTA_RATIO:Number = 1.7;//三角形の幅は直線の何倍にするか

                //中央
                var CenterX:int = GameMain.VIEW_W/2;
                var CenterY:int = GameMain.VIEW_H/2;

                //矢印の先端
                var DstX:int = CenterX + m_Gravity.x * ARROW_LEN/MOVE_POW;
                var DstY:int = CenterY + m_Gravity.y * ARROW_LEN/MOVE_POW;

                //接続点の位置
                const DeltaRatio:Number = 0.6;
                var DeltaX:int = Lerp(CenterX, DstX, DeltaRatio);
                var DeltaY:int = Lerp(CenterY, DstY, DeltaRatio);

                //幅用のオフセット
                var OffsetX:int = (DstY - CenterY) * ARROW_W/ARROW_LEN;
                var OffsetY:int = (CenterX - DstX) * ARROW_W/ARROW_LEN;

                //先端から開始
                g.moveTo(DstX, DstY);

                //三角形の片方
                g.lineTo(DeltaX + DELTA_RATIO*OffsetX, DeltaY + DELTA_RATIO*OffsetY);

                //三角形と直線の接続点
                g.lineTo(DeltaX + OffsetX, DeltaY + OffsetY);

                //直線の角
                g.lineTo(CenterX + OffsetX, CenterY + OffsetY);

                //直線の角(もう片方)
                g.lineTo(CenterX - OffsetX, CenterY - OffsetY);

                //再び接続点
                g.lineTo(DeltaX - OffsetX, DeltaY - OffsetY);

                //三角形のもう片方
                g.lineTo(DeltaX - DELTA_RATIO*OffsetX, DeltaY - DELTA_RATIO*OffsetY);

                //先端に戻る
                g.lineTo(DstX, DstY);
            }

            g.endFill();
        }
    }

    //Check : Dead
    public function Check_Dead():void{
        //Check
        {
            if(m_IsDead){
                return;
            }
        }

/*
        //マップより下に行っていたら落下死する
        if(this.y > GameMain.MAP_H+GameMain.PANEL_LEN){
            //ゲームオーバー処理
            {
                GameMain.Instance.OnDead_Fall();
            }

            //フラグ
            {
                m_IsDead = true;
            }
        }
//*/
    }

    //Update : Move
    public function Update_Move(in_DeltaTime:Number):void{
        var Gravity:Vector3D = GetGravity();

        var PowX:Number = GameMain.IMAGE_to_PHYS(Gravity.x);
        var PowY:Number = GameMain.IMAGE_to_PHYS(Gravity.y);

        m_Body.WakeUp();
        m_Body.m_force.x += PowX;
        m_Body.m_force.y += PowY;
/*//向き固定
        //ついでに向きもここで更新
        {
            var AbsGapX:Number = Math.abs(Gravity.x);
            var AbsGapY:Number = Math.abs(Gravity.y);

            if(AbsGapY < AbsGapX){
                if(Gravity.x > 0){
                    m_AnimDir = ANIM_DIR_R;
                }else{
                    m_AnimDir = ANIM_DIR_L;
                }
            }else{
                if(Gravity.y > 0){
                    m_AnimDir = ANIM_DIR_D;
                }else{
                    m_AnimDir = ANIM_DIR_U;
                }
            }
        }
//*/
    }

    //
    public function GetGravity():Vector3D{
        if(m_Accel){
            //加速度センサーを使う
            //→ハンドラで更新されてるはず
        }else{
            //マウスを使う

            const GAP_MIN:Number = 0;//GameMain.PANEL_W/2;
            const GAP_MAX:Number = GameMain.VIEW_W/3;//GameMain.PANEL_LEN*1.5;

/*
            //まずはプレイヤーとマウス位置の差を求める
            m_Gravity.x = GameMain.Instance.mouseX - (this.x + GameMain.Instance.m_Layer_Root.x);
            m_Gravity.y = GameMain.Instance.mouseY - (this.y + GameMain.Instance.m_Layer_Root.y);
/*/
            //マウスの画面中央からの差を求める
            m_Gravity.x = GameMain.Instance.mouseX - GameMain.VIEW_W/2;
            m_Gravity.y = GameMain.Instance.mouseY - GameMain.VIEW_H/2;
//*/
            //長さを制御して、0~1に収める
            var GapLen:Number = m_Gravity.length;
            if(GapLen < GAP_MIN){
                m_Gravity.x = m_Gravity.y = 0;
            }else{
                m_Gravity.x /= GapLen;
                m_Gravity.y /= GapLen;

                if(GapLen < GAP_MAX){
                    m_Gravity.x *= (GapLen - GAP_MIN) / (GAP_MAX - GAP_MIN);
                    m_Gravity.y *= (GapLen - GAP_MIN) / (GAP_MAX - GAP_MIN);
                }
            }

            //最大値がMOVE_POWになるようにする
            m_Gravity.x *= MOVE_POW;
            m_Gravity.y *= MOVE_POW;
        }

        return m_Gravity;
    }

    //
    public function SetGravity_Listener(e:AccelerometerEvent):void{
        m_Gravity.x = MOVE_POW * -e.accelerationX;
        m_Gravity.y = MOVE_POW *  e.accelerationY;
    }

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



//#Goal
class Goal extends Sprite
{
    //==Const==

    static public const GOAL_RANGE:int = 16;


    //==Var==


    public var m_BitmapData:BitmapData = new BitmapData(GameMain.PANEL_W, GameMain.PANEL_H, true, 0x80FFFF00);
    public var m_BitmapData_Clear:BitmapData = new BitmapData(GameMain.PANEL_W, GameMain.PANEL_H, true, 0x80FFFFFF);
    public var m_Bitmap:Bitmap = new Bitmap(m_BitmapData);


    //==Function==

    //Init
    public function Goal():void{
        //Graphic
        {
            m_Bitmap.x -= GameMain.PANEL_W/2;
            m_Bitmap.y -= GameMain.PANEL_H/2;
            addChild(m_Bitmap);
        }
    }

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

    //Update
    public function Update():void{
        //プレイヤーが一定範囲に来たらゴールとする

        //そもそもすでにゴールしてたら何も処理しない
        {
            if(GameMain.Instance.IsEnd()){
                return;
            }
        }

        //プレイヤーとの距離が一定以上離れていたら何も処理しない
        {
            var GapX:Number = GameMain.Instance.m_Player.x - this.x;
            var GapY:Number = GameMain.Instance.m_Player.y - this.y;

            var Distance:Number = Math.sqrt(GapX*GapX + GapY*GapY);

            if(Distance > GOAL_RANGE){
                return;
            }
        }

        //画像を差し替えてみる
        {
            m_Bitmap.bitmapData = m_BitmapData_Clear;
        }

        //上のチェックに全てクリアしたらゴールしたものとして処理する
        {
            GameMain.Instance.OnGoal();
        }
    }
}