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

ActLaser:タッチ版(検証用)

スマホで動かすためのタッチ対応版
・Air化してAndroidで動かした場合と処理速度などを比較するためのもの

操作方法(How To Play)
・タッチ(Touch)
 ・画面の左上、右上、左下、右下のいずれかをタッチするとそちらの方向に斜め移動する

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

/*
 ActLaser:タッチ版(検証用)
 ・スマホで動かすためのタッチ対応版
  ・Air化してAndroidで動かした場合と処理速度などを比較するためのもの

 操作方法(How To Play)
 ・タッチ(Touch)
  ・画面の左上、右上、左下、右下のいずれかをタッチするとそちらの方向に斜め移動する

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

 変更点
 ・キーではなく画面タッチで動くように設定
 ・フルスクリーン時に画面サイズに合うように設定
 ・描画の高速化
  ・レーザー描画をGraphicsで全て描画していたのを、ぶつかるたびにBitmapDataに結果を描画してキャッシュしていくようにした
*/


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 ActLaser extends Sprite {

        //==Const==

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

        //マップ
        static public var m_MapIter:int = 0;
        static public const O:int = m_MapIter++;//空白
        static public const W:int = m_MapIter++;//壁
        static public const P:int = m_MapIter++;//プレイヤー
        static public const G:int = m_MapIter++;//ゴール

        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,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,W],
[W,O,W,W,O,O,O,W,W,O,W,W,W,O,W,O,W,O,W,O,W,O,W,W,W,O,W,W,W,W,W,W,W,O,W],
[W,O,W,W,O,O,O,W,W,O,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,O,W,O,O,O,O,O,W,O,W],
[W,O,O,O,O,O,O,O,O,O,W,W,W,O,W,O,W,O,W,O,W,O,W,W,W,O,W,O,W,W,W,O,W,O,W],
[W,O,O,O,O,G,O,O,O,O,W,W,W,O,O,O,O,G,O,O,O,O,W,W,W,O,W,O,W,G,W,O,W,O,W],
[W,O,O,O,O,O,O,O,O,O,W,W,W,O,W,O,W,O,W,O,W,O,W,W,W,O,W,O,W,O,W,O,W,O,W],
[W,O,W,W,O,O,O,W,W,O,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,O,W,O,W,O,O,O,W,O,W],
[W,O,W,W,O,O,O,W,W,O,W,W,W,O,W,O,W,O,W,O,W,O,W,W,W,O,W,O,W,W,W,W,W,O,W],
[W,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,O,W,O,O,O,O,O,O,O,W],
[W,W,W,W,W,W,W,W,W,O,W,W,W,W,W,W,W,O,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,O,O,O,O,O,W,W,W,O,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,O,W,W,W,O,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,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,W],
[W,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,O,P,O,O,O,O,W,W,W,O,W,W,W,W,W,W,W,O,W],
[W,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,O,W,O,O,O,O,O,W,O,W],
[W,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,O,W,O,W,W,W,O,W,O,W],
[W,O,O,O,O,G,O,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,W,G,O,O,W,O,W],
[W,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,W,W,W,O,O,O,W,W,W,O,W,O,W,W,W,O,W,O,W],
[W,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,W,W,W,O,O,O,W,W,W,O,W,O,O,O,O,O,W,O,W],
[W,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,O,W,W,W,W,W,W,W,O,W],
[W,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,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,O,W,W,W,O,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,O,O,O,O,O,W,W,W,O,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,O,W,W,W,W,W,W,W,O,W,W,W,W,W,W,W,O,W,W,W,W,W,W,W,W,W],
[W,O,O,O,W,O,O,O,W,O,W,W,W,O,O,O,O,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,O,W],
[W,O,W,O,W,O,W,O,W,O,W,W,W,O,W,W,W,W,W,W,W,O,W,W,W,O,W,O,O,O,O,O,W,O,W],
[W,O,W,O,W,O,W,O,W,O,W,W,W,O,W,O,O,O,O,O,W,O,W,W,W,O,O,W,O,O,O,W,O,O,W],
[W,O,W,O,W,O,W,O,W,O,W,W,W,O,W,O,W,W,W,O,W,O,W,W,W,O,O,O,O,O,O,O,O,O,W],
[W,O,W,O,W,O,W,O,W,O,W,W,W,O,O,O,W,O,O,O,O,O,W,W,W,O,O,O,O,G,O,O,O,O,W],
[W,O,W,O,W,O,W,O,W,O,W,W,W,O,W,O,W,O,W,O,W,O,W,W,W,O,O,O,O,O,O,O,O,O,W],
[W,O,W,O,W,O,W,O,W,O,W,W,W,O,W,O,W,O,W,G,W,O,W,W,W,O,O,W,O,O,O,W,O,O,W],
[W,O,W,O,W,O,W,O,W,O,W,W,W,O,W,W,W,O,W,O,W,O,W,W,W,O,W,O,O,O,O,O,W,O,W],
[W,G,W,O,O,O,W,O,O,O,W,W,W,O,W,O,O,O,O,O,O,O,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,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W],
        ];

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

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

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

        //モード
        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:ActLaser;

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

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

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

        //ゴール
        public var m_Goal:Vector.<Goal> = new Vector.<Goal>();

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

        //スコア
        public var m_Score:int = -1;

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

        //==Function==

        //Init
        public function ActLaser():void {
            if(stage != null){
                Init(null);
            }else{
                addEventListener(
                    Event.ADDED_TO_STAGE,//ステージに追加されたら
                    Init
                );
            }
        }
        public function Init(e:Event):void
        {
            //Pseudo Singleton
            {
                Instance = this;
            }

            //Settings
            {
                //画面幅に合わせ、長い方が画面にフィットするように拡大
                //- 短い方は画面にフィットせず、もともと画面外だったものが内部表示されるかも
                stage.scaleMode = StageScaleMode.SHOW_ALL;
            }

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

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

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

                    //壁(レーザーを隠すため、プレイヤーより手前にする)
                    m_Layer_Root.addChild(m_Layer_Wall);
                }
            }

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

            //壁
            {
                m_Layer_Wall.addChild(new Bitmap(m_BitmapData_Wall));
            }

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

            //レーザー
            {
                m_Layer_Player.addChild(new Bitmap(m_BitmapData_Laser));
            }

//            //Goal
//            {
//                m_Goal = new Goal();
//                m_Layer_BG.addChild(m_Goal);
//            }

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

                        switch(MAP[y][x]){
                        case W:
                            //壁の基本描画
                            m_BitmapData_Wall.fillRect(rect, 0xFF444444);
                            break;
                        case P:
                            //プレイヤーの位置指定
                            m_Player.SetPos(
                                (x+0.5) * PANEL_LEN,
                                (y+0.5) * PANEL_LEN
                            );
                            break;
                        case G:
                            //ゴールの位置指定
                            {
                                var goal:Goal = new Goal();
                                goal.SetPos(
                                    (x+0.5) * PANEL_LEN,
                                    (y+0.5) * PANEL_LEN
                                );
                                //m_Layer_BG.addChild(goal);
                                m_Layer_Wall.addChild(goal);

                                m_Goal.push(goal);
                            }
                            break;
                        }
                    }
                }
            }

            //壁の見た目を調整
            {
                //BMDの一時コピーを生成することになるが気にしない
                m_BitmapData_Wall.applyFilter(
                    m_BitmapData_Wall, m_BitmapData_Wall.rect, new Point(0,0),
                    new GlowFilter(0x383838, 1.0, PANEL_LEN,PANEL_LEN, 2,1, true)
                );
            }

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

                addChild(m_Text);
            }
            {
                m_Text_Score.selectable = false;
                m_Text_Score.autoSize = TextFieldAutoSize.CENTER;
                m_Text_Score.defaultTextFormat = new TextFormat('Verdana', 32, 0xFFFFFF, true);
                m_Text_Score.text = '';
                m_Text_Score.filters = [new GlowFilter(0xFFFF00,1.0, 4,4)];

                m_Text_Score.x = VIEW_W / 2;
                m_Text_Score.y = 16;

                addChild(m_Text_Score);
            }

            //Camera
            {
                Update_Camera(true);
            }

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

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

            //Check
            {
                if(m_Mode == MODE_GOAL)
                {
                    return;
                }
            }

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

            //Goal
            {
                var score:int = 0;
                for(var i:int = 0; i < m_Goal.length; ++i)
                {
                    m_Goal[i].Update();

                    if(m_Goal[i].IsGet()){
                        ++score;
                    }
                }

                if(score == m_Goal.length){
                    OnGoal();
                }

                if(m_Score != score)
                {
                    m_Text_Score.text = "Orb " + score + "/" + m_Goal.length;
                    m_Score = score;
                }
            }

            //Camera
            {
                Update_Camera();
            }
        }

        //Update : Camera
        public function Update_Camera(in_ImmidateFlag:Boolean = false):void{
            var IsLaserMode:Boolean = m_Player.IsLaserMode();

            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;

                if(IsLaserMode){
                    //レーザー移動時
                    //→プレイヤーが画面外に移動するような状況に限りカメラを移動させる

                    //
                    var UnSafeRatio:Number = 0.2;
                    if(RelPlayerX < VIEW_W*UnSafeRatio){CameraMoveX = VIEW_W*UnSafeRatio - RelPlayerX;}
                    if(VIEW_W - VIEW_W*UnSafeRatio < RelPlayerX){CameraMoveX = (VIEW_W - VIEW_W*UnSafeRatio) - RelPlayerX;}
                    if(RelPlayerY < VIEW_H*UnSafeRatio){CameraMoveY = VIEW_H*UnSafeRatio - RelPlayerY;}
                    if(VIEW_H - VIEW_H*UnSafeRatio < RelPlayerY){CameraMoveY = (VIEW_H - VIEW_H*UnSafeRatio) - RelPlayerY;}
                }else{
                    //通常時
                    //→プレイヤーが中央に来るようにする

                    //中央からの差がそのまま移動量
                    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){
                    RootY = -MAP_H + VIEW_H;
                }
                if(RootY > 0){
                    RootY = 0;
                }
            }

            if(in_ImmidateFlag)
            {//初期化用
                m_Layer_Root.x = RootX;
                m_Layer_Root.y = RootY;
            }
            else
            {//レーザーモード解除時にすぐに移動するとわかりにくいので、補間してみる
                var ratio:Number = 0.2;
                m_Layer_Root.x = Lerp(m_Layer_Root.x, RootX, ratio);
                m_Layer_Root.y = Lerp(m_Layer_Root.y, RootY, ratio);
            }
        }

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

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

        //Wall
        public function GetWallVal(in_X:int, in_Y:int):int{
            var IndexX:int = in_X / PANEL_LEN;
            var IndexY:int = in_Y / PANEL_LEN;

            //範囲外は空白とみなす
            {
                if(IndexX < 0){return O;}
                if(MAP_NUM_X <= IndexX){return O;}
                if(IndexY < 0){return O;}
                if(MAP_NUM_Y <= IndexY){return O;}
            }

            //あとはMAPに従う
            var WallVal:int = O;
            {
                switch(MAP[IndexY][IndexX]){
                case W:
//                case Z:
//                case S:
//                case X:
                    //プレイヤー位置とかは空白とみなす
                    WallVal = MAP[IndexY][IndexX];
                    break;
                }
            }

            return WallVal;
        }

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


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


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

    //移動速度
    static public const VEL_X:Number = 100.0;

    //ジャンプ速度
    static public const JUMP_VEL:Number = 290.0;

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

    //最高下降速度(ロックによって無限落下が可能なので、速度制限してみる)
    static public const FALL_VEL_MIN:Number = 1000.0;

    //レーザー移動速度
    static public const LASER_VEL:Number = 500;

    //入力方向
    static public var DirIter:int = 0;
    static public const DIR_NONE:int = -1;
    static public const DIR_DR:int = DirIter++;
    static public const DIR_D :int = DirIter++;
    static public const DIR_DL:int = DirIter++;
    static public const DIR_L :int = DirIter++;
    static public const DIR_UL:int = DirIter++;
    static public const DIR_U :int = DirIter++;
    static public const DIR_UR:int = DirIter++;
    static public const DIR_R :int = DirIter++;
    static public const DIR_NUM :int = DirIter;


    //==Var==

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

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

    //方向指定:グラフィック用
    public var m_AnimIndex:int = DIR_NONE;
    public var m_AnimIndex_Next:int = DIR_NONE;

    //レーザー用ポイント
    public var m_LastPoint:Point = new Point(-999, -999);

    //レーザー移動用
    public var m_RestLen:Number = 1;
    public var m_LaserMoveX:int = 1;
    public var m_LaserMoveY:int = -1;

    //プレイヤー画像
    public var m_Bitmap:Bitmap;
    public var m_Shape:Shape = new Shape();
    public var m_Graphics:Graphics = m_Shape.graphics;

    //矢印画像
    public var m_ArrowGraphic_Normal:Vector.<Sprite>;
    public var m_ArrowGraphic_Push:Vector.<Sprite>;

    //レーザーの描画先
    public var m_BitmapData_Laser:BitmapData = null;

    //接地フラグ
    public var m_GroundFlag:Boolean = false;

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


    //==Function==

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

                    //プレイヤーグラフィック
                    {
                        var g:Graphics = m_Graphics;
                        g.lineStyle(0,0,0);
                        g.beginFill(0xEEFFFF, 1.0);
                        g.drawCircle(ActLaser.PANEL_LEN/2,ActLaser.PANEL_LEN/2, ActLaser.PANEL_LEN/4);
                        g.endFill();

                        var Blur:Number = ActLaser.PANEL_LEN/2;
                        m_Shape.filters = [new GlowFilter(0x00FFFF, 1.0, Blur,Blur)];

                        var bmp_data:BitmapData = new BitmapData(ActLaser.PANEL_LEN, ActLaser.PANEL_LEN, true, 0x00000000);
                        bmp_data.draw(m_Shape);

                        var bmp:Bitmap = new Bitmap(bmp_data);
                        bmp.x = -ActLaser.PANEL_LEN/2;
                        bmp.y = -ActLaser.PANEL_LEN/2;

                        addChild(bmp);

                        g.clear();
                        parent.addChild(m_Shape);

                        m_Bitmap = bmp;
                    }

                    //矢印画像
                    {
                        m_ArrowGraphic_Normal = new Vector.<Sprite>(4);
                        m_ArrowGraphic_Push   = new Vector.<Sprite>(4);
                        for(var i:int = 0; i < 4; ++i)
                        {
                            m_ArrowGraphic_Normal[i] = new Sprite();
                            m_ArrowGraphic_Push[i]   = new Sprite();

                            m_ArrowGraphic_Normal[i].addChild(ImageManager.GetArrowGraphic_Normal());
                            m_ArrowGraphic_Push[i].addChild(ImageManager.GetArrowGraphic_Push());

                            ActLaser.Instance.addChild(m_ArrowGraphic_Normal[i]);
                            ActLaser.Instance.addChild(m_ArrowGraphic_Push[i]);

                            m_ArrowGraphic_Push[i].visible = false;

                            //0:UL, 1:UR, 2:DL,  3:DR
                            if((i & 1) == 0)
                            {//L
                                m_ArrowGraphic_Normal[i].x = 
                                m_ArrowGraphic_Push[i].x =
                                    32;
                            }
                            else
                            {//R
                                m_ArrowGraphic_Normal[i].x = 
                                m_ArrowGraphic_Push[i].x =
                                    stage.stageWidth - 32;

                                m_ArrowGraphic_Normal[i].rotation += 90;
                                m_ArrowGraphic_Push[i].rotation = m_ArrowGraphic_Normal[i].rotation;
                            }

                            if((i & 2) == 0)
                            {//U
                                m_ArrowGraphic_Normal[i].y = 
                                m_ArrowGraphic_Push[i].y =
                                    32;
                            }
                            else
                            {//D
                                m_ArrowGraphic_Normal[i].y = 
                                m_ArrowGraphic_Push[i].y =
                                    stage.stageHeight - 32;

                                m_ArrowGraphic_Normal[i].rotation = 270 - m_ArrowGraphic_Normal[i].rotation;
                                m_ArrowGraphic_Push[i].rotation = m_ArrowGraphic_Normal[i].rotation;
                            }
                        }
                    }
                }
            );
        }
    }

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

    //Get : LaserMode
    public function IsLaserMode():Boolean{
        return (0 <= m_LastPoint.x);
    }

    //Update : Input
    static public const KEY_S:int = 83;
    private function OnKeyDown(event:KeyboardEvent):void{
        if(event.keyCode == Keyboard.LEFT){    m_InputL = true;}
        if(event.keyCode == Keyboard.RIGHT){m_InputR = true;}
        if(event.keyCode == Keyboard.UP){    m_InputU = true;}
        if(event.keyCode == Keyboard.DOWN){    m_InputD = true;}

        if(!m_InputLaser){
            switch(event.keyCode){
            case KEY_S:
            case Keyboard.SPACE:
                //レーザーモード開始

                //Flag
                m_InputLaser = true;

                //PointList : Init
                m_LastPoint.x = this.x;
                m_LastPoint.y = this.y;

                //移動方向リセット
                m_LaserMoveX = 0;
                m_LaserMoveY = 0;
                m_RestLen = 0;
            }
        }

        if(m_LaserMoveX == 0 && m_LaserMoveY == 0){
            //移動方向決定
            if(m_InputL){m_LaserMoveX--;}
            if(m_InputR){m_LaserMoveX++;}
            if(m_InputU){m_LaserMoveY--;}
            if(m_InputD){m_LaserMoveY++;}
        }
    }
    private function OnKeyUp(event:KeyboardEvent):void{
        if(event.keyCode == Keyboard.LEFT){    m_InputL = false;}
        if(event.keyCode == Keyboard.RIGHT){m_InputR = false;}
        if(event.keyCode == Keyboard.UP){    m_InputU = false;}
        if(event.keyCode == Keyboard.DOWN){    m_InputD = false;}

        if(m_InputLaser){
            switch(event.keyCode){
            case KEY_S:
            case Keyboard.SPACE:
                //レーザーモード解除

                //Flag
                m_InputLaser = false;

                //PointList : Clear
                m_LastPoint.x = -999;

                //
                m_BitmapData_Laser.fillRect(m_BitmapData_Laser.rect, 0x00000000);
                m_Graphics.clear();
            }
        }
    }
    private function OnMouseDown(e:MouseEvent):void{
        var ArrowGraphicIndex:int = 0;//0:UL, 1:UR, 2:DL,  3:DR
        if(stage.mouseX < stage.stageWidth/2)
        {//L
            m_LaserMoveX = -1;
        }
        else
        {//R
            m_LaserMoveX = +1;
            ArrowGraphicIndex += 1;
        }

        if(stage.mouseY < stage.stageHeight/2)
        {//U
            m_LaserMoveY = -1;
        }
        else
        {//D
            m_LaserMoveY = +1;
            ArrowGraphicIndex += 2;
        }

        //Flag
        m_InputLaser = true;

        //PointList : Init
        m_LastPoint.x = this.x;
        m_LastPoint.y = this.y;

        //矢印画像の更新
        RefreshArrowGraphic(ArrowGraphicIndex);

        //移動まわりリセット
        m_RestLen = 0;
    }
    private function OnMouseUp(e:MouseEvent):void{
        //レーザーモード解除

        //Flag
        m_InputLaser = false;

        //PointList : Clear
        m_LastPoint.x = -999;

        //矢印画像の更新
        RefreshArrowGraphic(-1);

        //
        m_BitmapData_Laser.fillRect(m_BitmapData_Laser.rect, 0x00000000);
        m_Graphics.clear();
    }

    //
    public function RefreshArrowGraphic(in_GraphicIndex:int):void{
        for(var i:int = 0; i < 4; ++i)
        {
            if(i == in_GraphicIndex)
            {//On
                m_ArrowGraphic_Normal[i].visible = false;
                m_ArrowGraphic_Push[i].visible   = true;
            }
            else
            {//Off
                m_ArrowGraphic_Normal[i].visible = true;
                m_ArrowGraphic_Push[i].visible   = false;
            }
        }
    }

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

        //移動
        Update_Move(in_DeltaTime);

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

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

    //Update : Graphic
    public function Update_Graphic(in_DeltaTime:Number):void{
        if(! IsLaserMode()){
            Update_Graphic_Normal(in_DeltaTime);
        }else{
            Update_Graphic_Laser(in_DeltaTime);
        }
    }
    //Update : Graphic : Normal
    public function Update_Graphic_Normal(in_DeltaTime:Number):void{
    }
    //Update : Graphic : Laser
    public function Update_Graphic_Laser(in_DeltaTime:Number):void{
        //レーザー時
/*
        var g:Graphics = m_Graphics;

        var point_num:int = m_PointList.length;

        //Reset
        {
            g.clear();
            g.lineStyle(ActLaser.PANEL_LEN/4, 0xEEFFFF,1.0);
        }

        //Line
        {
            g.moveTo(m_PointList[0].x-this.x, m_PointList[0].y-this.y);
            for(var i:int = 1; i < point_num; i++){
                g.lineTo(m_PointList[i].x-this.x, m_PointList[i].y-this.y);
            }
            g.lineTo(0,0);
        }

        //Circle
        {
            g.lineStyle(0,0,0);
            g.beginFill(0xEEFFFF, 1.0);
            g.drawCircle(0,0, ActLaser.PANEL_LEN/4);
            g.endFill();
        }

        m_AnimIndex = -2;//戻った時に強制Draw
/*/
        var g:Graphics = m_Graphics;

        //Reset
        {
            g.clear();
            g.lineStyle(ActLaser.PANEL_LEN/4, 0xEEFFFF,1.0);
        }

        //Line
        {
            g.moveTo(m_LastPoint.x, m_LastPoint.y);
            g.lineTo(this.x, this.y);
        }

        //Circle
        {
            g.lineStyle(0,0,0);
            g.beginFill(0xEEFFFF, 1.0);
            g.drawCircle(this.x,this.y, ActLaser.PANEL_LEN/4);
            g.endFill();
        }
//*/
    }

    public function TransGraphic(in_EndX:int, in_EndY:int):void
    {
        //Graphics
        {
            var g:Graphics = m_Graphics;

            //Reset
            {
                g.clear();
                g.lineStyle(ActLaser.PANEL_LEN/4, 0xEEFFFF,1.0);
            }

            //Line
            {
                g.moveTo(m_LastPoint.x, m_LastPoint.y);
                g.lineTo(in_EndX, in_EndY);
            }
        }

        //Trans
        {
//            m_BitmapData_Laser.draw(m_Shape, null, null, BlendMode.ADD);
            m_BitmapData_Laser.draw(m_Shape, null, null, BlendMode.LIGHTEN);
        }
    }

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

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

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

    //Update : Move
    public function Update_Move(in_DeltaTime:Number):void{
        if(! IsLaserMode()){
            Update_Move_Normal(in_DeltaTime);
        }else{
            Update_Move_Laser(in_DeltaTime);
        }
    }
    //Update : Move : Normal
    public function Update_Move_Normal(in_DeltaTime:Number):void{
        const REFRECT_RATIO:Number = 0.5;

        //入力
        {
            //X
            {
                var TrgVX:Number = 0.0;
                if(m_InputR){TrgVX =  VEL_X;}
                if(m_InputL){TrgVX = -VEL_X;}

                var ratio:Number = 0.5;
                if(!m_GroundFlag){ratio = 0.1;}//空中では慣性をきかせる
                m_Vel.x = Lerp(m_Vel.x, TrgVX, ratio);
            }

            //Jump
            {
                if(m_InputU && m_GroundFlag){
                    m_Vel.y = -JUMP_VEL;
                }
            }
        }

        //重力
        {
            m_Vel.y += GRAVITY * in_DeltaTime;

            //速度制限
            if(m_Vel.y > FALL_VEL_MIN){
                m_Vel.y = FALL_VEL_MIN;
            }
        }

        //目標位置
        var DstX:Number;
        var DstY:Number;
        {
            DstX = (m_Pos.x) + (m_Vel.x * in_DeltaTime);
            DstY = (m_Pos.y) + (m_Vel.y * in_DeltaTime);
        }

        //移動を試みる
        //・端数制御のためにちょっと特殊なことをしているが、基本的にはただ単にX移動→Y移動してるだけ
        //・壁判定まわりはかなりムダが多い(高速化の余地が多い)が、ひとまずこれで

        //X移動
        {
            var TryX:int = m_Pos.x;
            if(TryX != int(DstX)){
                for(;;){
                    //++
                    if(TryX < DstX){
                        TryX++;
                    }else{
                        TryX--;
                    }

                    //壁があるならその手前で中断
                    if(IsWall(TryX, m_Pos.y)){
                        DstX = m_Pos.x;//壁の手前になるように位置補正(=端数切捨て)
                        m_Vel.x *= -REFRECT_RATIO;
                        break;
                    }

                    //移動できたようなので更新(主に上の位置補正のための記憶用)
                    m_Pos.x = TryX;

                    //Dstまで辿りついたら終了
                    if(TryX == int(DstX)){
                        break;
                    }
                }
            }
            m_Pos.x = DstX;
        }

        //Y移動
        {
            m_GroundFlag = false;//更新のためリセット

            var TryY:int = m_Pos.y;
            if(TryY != int(DstY)){
                for(;;){
                    //++
                    if(TryY < DstY){
                        TryY++;
                    }else{
                        TryY--;
                    }

                    //壁があるならその手前で中断
                    if(IsWall(m_Pos.x, TryY)){
                        if(DstY > m_Pos.y){m_GroundFlag = true;}
                        DstY = m_Pos.y;//壁の手前になるように位置補正(=端数切捨て)
                        m_Vel.y *= -REFRECT_RATIO;
                        break;
                    }

                    //移動できたようなので更新(主に上の位置補正のための記憶用)
                    m_Pos.y = TryY;

                    //Dstまで辿りついたら終了
                    if(TryY == int(DstY)){
                        break;
                    }
                }
            }
            m_Pos.y = DstY;
        }

        //反映
        {
            this.x = m_Pos.x;
            this.y = m_Pos.y;
        }
    }
    //Update : Move : Laser
    public function Update_Move_Laser(in_DeltaTime:Number):void{
//*
        //今回の移動量を計算
        m_RestLen += LASER_VEL * in_DeltaTime;

        //1ドットずつ移動
        for(; m_RestLen >= 1; m_RestLen -= 1){
            var NextX:int = m_Pos.x + m_LaserMoveX;
            var NextY:int = m_Pos.y + m_LaserMoveY;

            var WallVal:int = ActLaser.Instance.GetWallVal(NextX, NextY);

            //三角壁用
            var DeltaWallCheck:Boolean = false;
            var DeltaWallHit:Boolean = false;
            var RelNextX:int = NextX % ActLaser.PANEL_LEN;
            var RelNextY:int = NextY % ActLaser.PANEL_LEN;

            switch(WallVal){
                //=空間=
            case ActLaser.O:
                //そのまま移動
                m_Pos.x = NextX;
                m_Pos.y = NextY;
                break;

                //=壁=
            case ActLaser.W:
                //上下反転も左右反転も両反転もありうる

                //今の位置を屈折点として登録
                {
                    TransGraphic(m_Pos.x, m_Pos.y);
                }

                //周囲(といっても1ドット)のブロックの並びを調べる
                var WallVal_X:int = ActLaser.Instance.GetWallVal(m_Pos.x+m_LaserMoveX, m_Pos.y);
                var WallVal_Y:int = ActLaser.Instance.GetWallVal(m_Pos.x, m_Pos.y+m_LaserMoveY);

                //並び具合を数値化
                var ReflectVal:int = 0;
                if(WallVal_X == ActLaser.W){ReflectVal += 1;}
                if(WallVal_Y == ActLaser.W){ReflectVal += 2;}

                //並び具合に応じて反射
                switch(ReflectVal){
                case 0://隅
                case 3://隅
                    //逆移動
                    m_LaserMoveX = -m_LaserMoveX;
                    m_LaserMoveY = -m_LaserMoveY;
                    break;
                case 1://ブロックが横に並んでいるところへの衝突
                    //上下反転
                    m_LaserMoveY = -m_LaserMoveY;
                    //横だけ採用
                    m_Pos.x = NextX;
                    break;
                case 2://ブロックが縦に並んでいるところへの衝突
                    //左右反転
                    m_LaserMoveX = -m_LaserMoveX;
                    //縦だけ採用
                    m_Pos.y = NextY;
                    break;
                }

                //次の始点を再び屈折点として登録
                {
                    m_LastPoint.x = m_Pos.x;
                    m_LastPoint.y = m_Pos.y;
                }

                break;
/*
                //=三角壁=
                //- まずはそれぞれのパターンで壁に接触したかをチェック
            case ActLaser.Y:
                if(!DeltaWallCheck){
                    DeltaWallHit = (RelNextX <= (ActLaser.PANEL_LEN-1 - RelNextY));
                    DeltaWallCheck = true;
                }
            case ActLaser.U:
                if(!DeltaWallCheck){
                    DeltaWallHit = (RelNextY <= RelNextX);
                    DeltaWallCheck = true;
                }
            case ActLaser.H:
                if(!DeltaWallCheck){
                    DeltaWallHit = (RelNextY >= RelNextX);
                    DeltaWallCheck = true;
                }
            case ActLaser.J:
                if(!DeltaWallCheck){
                    DeltaWallHit = (RelNextX >= (ActLaser.PANEL_LEN-1 - RelNextY));
                    DeltaWallCheck = true;
                }
                //共通
                //斜め移動なら両反射、そうでなければ90度回転
                break;
//*/
            }
        }

        //反映
        {
            this.x = m_Pos.x;
            this.y = m_Pos.y;

            //速度も
            m_Vel.x = LASER_VEL * m_LaserMoveX;
            m_Vel.y = LASER_VEL * m_LaserMoveY;
        }

        //m_LaserMoveXは-1,0,1の値を取ることで横や斜めに1ドットずつ進むもの
//*/
    }

    //壁があるかどうか
    public function IsWall(in_X:int, in_Y:int):Boolean{
        return ActLaser.Instance.GetWallVal(in_X, in_Y) == ActLaser.W;
    }

    //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
{
    //==Constt==

    static public const GOAL_RANGE:int = 16;


    //==Var==

    public var m_GetFlag:Boolean = false;


    //==Function==

    //Init
    public function Goal():void{
        //Graphic
        {
            addChild(ImageManager.GetGoalGraphic());
        }
    }

    //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(ActLaser.Instance.IsEnd()){
                return;
            }
        }

        //そもそもすでに取られていたら何もしない
        {
            if(m_GetFlag && 0 < this.alpha){
                this.alpha *= 0.9;
                this.scaleX *= 1.05;
                this.scaleY *= 1.05;
                if(this.alpha < 0.01){
                    this.alpha = 0;
                }
                return;
            }
        }

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

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

            if(Distance > GOAL_RANGE){
                return;
            }
        }

        //上のチェックに全てクリアしたらゲットしたものとみなす
        {
            m_GetFlag = true;
        }
    }

    //Flag
    public function IsGet():Boolean{
        return m_GetFlag;
    }
}


//#ImageManager
class ImageManager
{
    static public var m_BitmapData_Goal:BitmapData = null;
    static public var m_BitmapData_Arrow_Normal:BitmapData = null;
    static public var m_BitmapData_Arrow_Push:BitmapData = null;

    //Image : Goal
    static private function CreateGoalBitmapData():BitmapData{
        var shape:Shape = new Shape();
        var g:Graphics = shape.graphics;
        g.lineStyle(0,0,0);
        g.beginFill(0xFFFFEE, 1.0);
        g.drawCircle(ActLaser.PANEL_LEN/2,ActLaser.PANEL_LEN/2, ActLaser.PANEL_LEN/4);
        g.endFill();

        var Blur:Number = ActLaser.PANEL_LEN/2;
        shape.filters = [new GlowFilter(0xFFFF00, 1.0, Blur,Blur)];

        var bmp_data:BitmapData = new BitmapData(ActLaser.PANEL_LEN, ActLaser.PANEL_LEN, true, 0x00000000);
        bmp_data.draw(shape);

        return bmp_data;
    }
    static public function GetGoalGraphic():Bitmap{
        if(m_BitmapData_Goal == null)
        {
            m_BitmapData_Goal = CreateGoalBitmapData();
        }

        //
        var bmp:Bitmap;
        {
            bmp= new Bitmap(m_BitmapData_Goal);
            bmp.x = -ActLaser.PANEL_LEN/2;
            bmp.y = -ActLaser.PANEL_LEN/2;
        }

        return bmp;
    }

    //Image : Arrow
    //- Normal
    static private function CreateArrowBitmapData_Normal():BitmapData{
        const W:int = 32;
        const Offset:int = 4;

        var shape:Shape = new Shape();
        var g:Graphics = shape.graphics;
        g.lineStyle(2, 0xFFFFFF, 1.0);
        g.beginFill(0x000000, 1.0);
        g.moveTo(Offset, Offset);
        g.lineTo(Offset, W-Offset);
        g.lineTo(W-Offset, Offset);
        g.endFill();

        var bmp_data:BitmapData = new BitmapData(W, W, true, 0x00000000);
        bmp_data.draw(shape);

        return bmp_data;
    }
    static public function GetArrowGraphic_Normal():Bitmap{
        if(m_BitmapData_Arrow_Normal == null)
        {
            m_BitmapData_Arrow_Normal = CreateArrowBitmapData_Normal();
        }

        //
        var bmp:Bitmap;
        {
            bmp= new Bitmap(m_BitmapData_Arrow_Normal);
            bmp.x = -bmp.width/2;
            bmp.y = -bmp.height/2;
        }

        return bmp;
    }
    //- Push
    static private function CreateArrowBitmapData_Push():BitmapData{
        const W:int = 32;
        const Offset:int = 4;

        var shape:Shape = new Shape();
        var g:Graphics = shape.graphics;
        g.lineStyle(0,0,0);
        g.beginFill(0xFFFFFF, 1.0);
        g.moveTo(Offset, Offset);
        g.lineTo(Offset, W-Offset);
        g.lineTo(W-Offset, Offset);
        g.endFill();

        var Blur:Number = 4;
        shape.filters = [new GlowFilter(0x00FFFF, 1.0, Blur,Blur)];

        var bmp_data:BitmapData = new BitmapData(W, W, true, 0x00000000);
        bmp_data.draw(shape);

        return bmp_data;
    }
    static public function GetArrowGraphic_Push():Bitmap{
        if(m_BitmapData_Arrow_Push == null)
        {
            m_BitmapData_Arrow_Push = CreateArrowBitmapData_Push();
        }

        //
        var bmp:Bitmap;
        {
            bmp= new Bitmap(m_BitmapData_Arrow_Push);
            bmp.x = -bmp.width/2;
            bmp.y = -bmp.height/2;
        }

        return bmp;
    }
}