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

試作:3次元弾幕Act

概要
 ・3次元アクションでボスが弾幕を撃ってくるようなやつ
 ・当たり判定とかは特にないので、プレイヤーを動かしつつ弾幕が確認できるだけ
 ・ジャンプ中はスローモードになるようにしてみた

 操作方法
 ・十字キー
  ・移動
 ・SPACE
  ・ジャンプ
Get Adobe Flash player
by o_healer 16 Sep 2010
/**
 * Copyright o_healer ( http://wonderfl.net/user/o_healer )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/9Mgi
 */

/*
 「3次元弾幕テスト」

 概要
 ・3次元アクションでボスが弾幕を撃ってくるようなやつ
 ・当たり判定とかは特にないので、プレイヤーを動かしつつ弾幕が確認できるだけ
 ・ジャンプ中はスローモードになるようにしてみた

 操作方法
 ・十字キー
  ・移動
 ・SPACE
  ・ジャンプ

 高速化
 ・被写界深度用ブラーの事前計算
  ・ブラーは毎回かけずに、事前に10段階ほど計算しておいて、それを差し替える方式
 ・Z-Sortをシェーカーソートに
  ・ベタなソートだと遅いので、シェルソートなりシェーカーソートなりに変更
 ・弾の表示はBitmapで
  ・Shapeなどをそのまま表示すると遅いので、Bitmapに描きこんでから表示

 高速化案
 ・弾のzを指定しない
  ・zによるスケーリングなどで遅くなっているっぽい
  ・x,yを自前で計算し、スケーリングはブラーとまとめて事前計算しておく(16段階くらいで十分?)
 ・Z-Sortの事前最適化&インクリメンタル実行
  ・弾を発射する際に、カメラ位置より遠いところから登録することで高速化
  ・Z-Sortは1フレームで完結させず、数回入れ替えを行ったら処理をそこで中断することで処理落ちを緩和

 その他
 ・地面を普通に回転させただけだと被写界深度がかからないので、できたらどうにかしたい
*/


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

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

        //地形の半径
        static public const GROUND_RAD:int = 240;

        //入力
        static private var InputIter:int = 0;
        static public const INPUT_U:int        = InputIter++;
        static public const INPUT_D:int        = InputIter++;
        static public const INPUT_L:int        = InputIter++;
        static public const INPUT_R:int        = InputIter++;
        static public const INPUT_JUMP:int    = InputIter++;
        static public const INPUT_NUM:int    = InputIter;

        //Utility
        static public const TWO_PI:Number = 2*Math.PI;
        static public const POS_ZERO:Point = new Point(0,0);


        //==Var==

        //【似非】Singleton【ていうかGlobalアクセス用】
        static public var Instance:GameMain;

        //レイヤー
        public var m_Layer_Ground:Sprite = new Sprite();
        public var m_Layer_Object:Sprite = new Sprite();

        //入力
        public var m_Input:Array = new Array(INPUT_NUM);

        //カメラ
        public var m_CameraRad:Number = GROUND_RAD*3/4;
        public var m_CameraTheta:Number = 0.0;
        public var m_CameraPos:Vector3D = new Vector3D(0,0,0);
        public var m_CameraTrg:Vector3D = new Vector3D(0,-5,0);
        public var m_CameraDirX:Vector3D = new Vector3D(1,0,0);
        public var m_CameraDirY:Vector3D = new Vector3D(0,1,0);
        public var m_CameraDirZ:Vector3D = new Vector3D(0,0,1);

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

        //地面
        public var m_Ground:Sprite;

        //プレイヤーの影
        public var m_PlayerShadow:Sprite;

        //スロー効果
        public var m_UpdateRatio:Number = 1.0;

        //==Function==


        //#Sequence

        //Init
        public function GameMain(){
            //Singleton
            Instance = this;

            //ロード開始
            Load();
        }

        //Load
//*
        static public const GRAPHICS_URL:String = "http://assets.wonderfl.net/images/related_images/a/a6/a6a6/a6a68ccace04fb05559eef79445e901a82d2accd";

        static public var m_Bitmap_Player:Bitmap = new Bitmap();
        static public var m_Bitmap_Ground:Bitmap = new Bitmap();

        public function Load():void{
            //Load:Sky
            {
                //Init
                {
                    m_Bitmap_Player.bitmapData = new BitmapData(32, 32, true, 0x00000000);
                    m_Bitmap_Ground.bitmapData = new BitmapData(32, 32, true, 0x00000000);
                }

                //Load
                {
                    var url:String = GRAPHICS_URL;

                    var ldr:Loader = new Loader();
                    ldr.load(new URLRequest(url), new LoaderContext(true));
                    ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, function local_load(e:Event):void {
                        //画像保存
                        {
                            var mtx:Matrix = new Matrix(1,0,0,1, 0,0);

                            mtx.tx = 0;
                            mtx.ty = 0;
                            m_Bitmap_Player.bitmapData.draw(ldr.content, mtx);

                            mtx.tx = -32;
                            mtx.ty = 0;
                            m_Bitmap_Ground.bitmapData.draw(ldr.content, mtx);
                        }

                        //初期化開始
                        {
                            Reset();
                        }
                    });
                }
            }
        }
/*/
        [Embed(source='Player.png')]
         private static var Bitmap_Player: Class;
        static public var m_Bitmap_Player:Bitmap = new Bitmap_Player();

        [Embed(source='Ground.png')]
         private static var Bitmap_Ground: Class;
        static public var m_Bitmap_Ground:Bitmap = new Bitmap_Ground();
        public function Load():void{

            //初期化開始
            addEventListener(
                Event.ADDED_TO_STAGE,//stageを扱うので、登録されたときに実行する
                Reset
            );
        }
//*/

        //Reset
        public function Reset(e:Event=null):void{
            var i:int;
            var shape:Shape;
            var g:Graphics;

            //高速化
            {
                this.mouseEnabled = false;//マウスは使わないのでチェックを切る
                this.mouseChildren = false;
            }

            //Layer
            {
                addChild(m_Layer_Ground);
                addChild(m_Layer_Object);

                m_Layer_Ground.x = 465/2;
                m_Layer_Ground.y = 465/2;
                m_Layer_Object.x = 465/2;
                m_Layer_Object.y = 465/2;
            }

            //Key
            {
                //m_Input
                for(i = 0; i < INPUT_NUM; i++){
                    m_Input[i] = false;
                }

                //Listener
                {
                    stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
                    stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
                }
            }

            //Ground
            {
                var bmd_ground:BitmapData = new BitmapData(2*GROUND_RAD, 2*GROUND_RAD, true, 0x00000000);

                var bmd_ori:BitmapData = m_Bitmap_Ground.bitmapData;

                var pos:Point = new Point(0,0);
                for(pos.x = 0; pos.x < 2*GROUND_RAD; pos.x += 32){
                    for(pos.y = 0; pos.y < 2*GROUND_RAD; pos.y += 32){
                        bmd_ground.copyPixels(bmd_ori, bmd_ori.rect, pos);
                    }
                }

                //Mask
                {
                    shape = new Shape();
                    g = shape.graphics;
                    g.lineStyle(0x000000, 0.0);
                    g.beginFill(0xFFFFFF, 1.0);
                    g.drawCircle(GROUND_RAD, GROUND_RAD, GROUND_RAD);
                    g.endFill();

                    var bmd_mask:BitmapData = new BitmapData(2*GROUND_RAD, 2*GROUND_RAD, true, 0x00000000);
                    bmd_mask.draw(shape);

                    bmd_ground.copyChannel(bmd_mask, bmd_mask.rect, POS_ZERO, BitmapDataChannel.ALPHA, BitmapDataChannel.ALPHA);
                }

                var bmp_ground:Bitmap = new Bitmap(bmd_ground);
                bmp_ground.x = -GROUND_RAD;
                bmp_ground.y = -GROUND_RAD;

                m_Ground = new Sprite();
                m_Ground.addChild(bmp_ground);
                m_Layer_Ground.addChild(m_Ground);
            }

            //Player
            {
                m_Player = new Player();

                m_Layer_Object.addChild(m_Player);
            }
//*
            //Player Shadow
            {
                m_PlayerShadow = new Sprite();
                {
                    shape = new Shape();
                    g = shape.graphics;
                    g.beginFill(0x000000, 0.4);
                    g.drawCircle(0, 0, 10);
                    g.endFill();
                    m_PlayerShadow.addChild(shape);
                }

                m_Ground.addChild(m_PlayerShadow);
            }
//*/
            //Bullet
            {
                Bullet.Ready();
            }

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

        //Update
        public function Update(e:Event):void{
            var i:int, j:int;

            var DeltaTime:Number = 1/60.0 * m_UpdateRatio;

            //アップで表示するため、全てのOBJにかけるオフセット
            const OFFSET_Z:Number = -100.0;

            var RelPos:Vector3D = new Vector3D(0,0,0);

            //カメラの更新
            {
                //Rot by Input
                var CameraRotTime:Number = TWO_PI * m_CameraRad / Player.MOVE_VEL;//8.0;
                if(m_Input[INPUT_R]){m_CameraTheta -= TWO_PI * DeltaTime / CameraRotTime;}
                if(m_Input[INPUT_L]){m_CameraTheta += TWO_PI * DeltaTime / CameraRotTime;}

                //Zoom(Move) by Input
                var move:int = Player.MOVE_VEL * DeltaTime;
                if(m_Input[INPUT_U]){m_CameraRad = Math.max(m_CameraRad - move, 64);}
                if(m_Input[INPUT_D]){m_CameraRad = Math.min(m_CameraRad + move, GROUND_RAD);}

                //CameraPos
                m_CameraPos.x = m_CameraRad * Math.cos(m_CameraTheta);
                m_CameraPos.y = Lerp(-50, -10, 1 - m_CameraRad/GROUND_RAD);
                m_CameraPos.z = m_CameraRad * Math.sin(m_CameraTheta);

                //DirZ : Pos => Trg
                m_CameraDirZ.x = m_CameraTrg.x - m_CameraPos.x;
                m_CameraDirZ.y = m_CameraTrg.y - m_CameraPos.y;
                m_CameraDirZ.z = m_CameraTrg.z - m_CameraPos.z;
                m_CameraDirZ.normalize();

                //DirX : DirZ x AxisY
                m_CameraDirX.x = -m_CameraDirZ.z;//AxisY = (0,1,0)なので単純化
                m_CameraDirX.y = 0;
                m_CameraDirX.z = m_CameraDirZ.x;

                //DirY : DirX x DirZ
                m_CameraDirY.x = m_CameraDirX.y*m_CameraDirZ.z - m_CameraDirX.z*m_CameraDirZ.y;
                m_CameraDirY.y = m_CameraDirX.z*m_CameraDirZ.x - m_CameraDirX.x*m_CameraDirZ.z;
                m_CameraDirY.z = m_CameraDirX.x*m_CameraDirZ.y - m_CameraDirX.y*m_CameraDirZ.x;
            }

            //プレイヤーの位置更新
            {
                if(m_Input[INPUT_R]){m_Player.scaleX =  1;}
                if(m_Input[INPUT_L]){m_Player.scaleX = -1;}

                if(m_Input[INPUT_JUMP]){m_Player.TryJump();}

                m_Player.m_Distance = m_CameraRad - 10;

                m_Player.m_Pos.x = m_Player.m_Distance * Math.cos(m_CameraTheta);
                //m_Player.m_Pos.y = 0;
                m_Player.m_Pos.z = m_Player.m_Distance * Math.sin(m_CameraTheta);
            }
//*
            {//Shadow
                m_PlayerShadow.x = -m_Player.m_Pos.z;
                m_PlayerShadow.y = m_Player.m_Pos.x;
            }
//*/
            //地形の傾き更新
            {
                var ground_mtx:Matrix3D = m_Ground.transform.matrix3D;
                if(ground_mtx == null){ground_mtx = new Matrix3D();}
                ground_mtx.identity();
                ground_mtx.appendRotation(m_CameraTheta * -360/TWO_PI, Vector3D.Z_AXIS);
                ground_mtx.appendRotation(Math.acos(m_CameraDirZ.y) * -360/TWO_PI, Vector3D.X_AXIS);
                m_Ground.transform.matrix3D = ground_mtx;

                RelPos.x =  - m_CameraPos.x;
                RelPos.y =  - m_CameraPos.y;
                RelPos.z =  - m_CameraPos.z;

                m_Ground.x = m_CameraDirX.dotProduct(RelPos);
                m_Ground.y = m_CameraDirY.dotProduct(RelPos);
                m_Ground.z = m_CameraDirZ.dotProduct(RelPos) + OFFSET_Z;//!!ここ(の設定で引き起こされる処理)が重い
            }

            //弾の生成チェック
            {
                Update_Bullet(DeltaTime);
            }

            //各OBJのUpdate
            var num:int = m_Layer_Object.numChildren;
            for(i = 0; i < num; i++){
                //
                var obj:GameObject = m_Layer_Object.getChildAt(i) as GameObject;

                //更新
                obj.Update(DeltaTime);

                //Kill(removeChild)があった時用の対応
/*
                if(num != m_Layer_Object.numChildren){//登録数が変わった
                    num = m_Layer_Object.numChildren;//更新
                    i--;//相殺
                    continue;
                }
/*/
                if(obj.parent == null){//登録が解除された
                    num -= 1;//更新
                    i--;//相殺
                    continue;
                }
//*/

                //カメラ位置に応じて表示位置を変更
                RelPos.x = obj.m_Pos.x - m_CameraPos.x;
                RelPos.y = obj.m_Pos.y - m_CameraPos.y;
                RelPos.z = obj.m_Pos.z - m_CameraPos.z;

                obj.x = m_CameraDirX.dotProduct(RelPos);
                obj.y = m_CameraDirY.dotProduct(RelPos);
                obj.z = m_CameraDirZ.dotProduct(RelPos) + OFFSET_Z;
            }

            //Z-sort
/*
            //ベタ
            for(i = 0; i < num; i++){
                var obj_i:GameObject = m_Layer_Object.getChildAt(i) as GameObject;
                for(j = i+1; j < num; j++){
                    var obj_j:GameObject = m_Layer_Object.getChildAt(j) as GameObject;

                    if(obj_i.z < obj_j.z){
                        m_Layer_Object.swapChildrenAt(i, j);
                    }
                }
            }
//*/
//*
            //シェーカーソート
            var index_top:int = 0;
            var index_bot:int = num-1;
            var index_last_swap:int;
            var obj_i:GameObject;
            var obj_j:GameObject;
            for(;;){
                //top => bottom
                {
                    index_last_swap = index_top;//交換が発生しなかったら、後方からの探索をTopから始める

                    for(i = index_top; i < index_bot; i++){
                        obj_i = m_Layer_Object.getChildAt(i) as GameObject;
                        obj_j = m_Layer_Object.getChildAt(i+1) as GameObject;
                        if(obj_i.z < obj_j.z){
                            m_Layer_Object.swapChildrenAt(i, i+1);
                            index_last_swap = i;
                            //i++;//Force Incremental Search
                        }
                    }

                    index_bot = index_last_swap;//後方からの探索開始位置を修正
                }


                //top <= bottom
                {
                    index_last_swap = index_bot;

                    for(i = index_bot; i > index_top; i--){
                        obj_i = m_Layer_Object.getChildAt(i) as GameObject;
                        obj_j = m_Layer_Object.getChildAt(i-1) as GameObject;
                        if(obj_i.z > obj_j.z){
                            m_Layer_Object.swapChildrenAt(i, i-1);
                            index_last_swap = i;
                            //i--;//Force Incremental Search
                        }
                    }

                    index_top = index_last_swap;//後方からの探索開始位置を修正
                }

                //Check
                if(index_top == index_bot){
                    break;
                }
            }
//*/
        }

        //Update : Bullet
        public var m_BulletFuncList:Array = [//弾幕生成関数のリスト
            CreateFunc_CreateBullets_Sin(),
            CreateFunc_CreateBullets_AimDelayCircle(),
            CreateFunc_CreateBullets_Circle(),
            CreateFunc_CreateBullets_AimRing(),
        ];
        public var m_BulletFuncIter:int = 0;//リスト用Iter
        public function Update_Bullet(in_DeltaTime:Number):void{
            if(m_BulletFuncList[m_BulletFuncIter](in_DeltaTime)){//trueを返したら終了とみなして次の弾幕へ
                m_BulletFuncIter++;
                if(m_BulletFuncIter >= m_BulletFuncList.length){m_BulletFuncIter = 0;}
            }
        }

        //Bullet : Circle
        public function CreateFunc_CreateBullets_Circle():Function{
            const BULLET_VEL:Number = 150.0;
            const BULLET_NUM:int = 32;
            const BULLET_PHASE:int = 3;
            const BULLET_INTERVAL:Number = 1.0;
            const BULLET_INTERVAL_END:Number = 2.0;

            //Member
            var Phase:int = 0;
            var RestTimer:Number = 0;
            var RadOffset:Number = 0;

            return function(in_DeltaTime:Number):Boolean{
                //Timer
                {
                    RestTimer -= in_DeltaTime;
                }

                if(RestTimer < 0){
                    //Phase
                    {
                        if(Phase == BULLET_PHASE){
                            Phase = 0;
                            RestTimer = 0;
                            RadOffset = 0;
                            return true;
                        }

                        Phase++;

                        if(Phase != BULLET_PHASE){
                            RestTimer += BULLET_INTERVAL;
                        }else{
                            RestTimer += BULLET_INTERVAL_END;
                        }
                    }

                    for(var i:int = 0; i < BULLET_NUM; i++){
                        var bullet:Bullet = new Bullet();

                        var theta:Number = TWO_PI * i/BULLET_NUM + RadOffset;

                        bullet.m_Pos.y = -Bullet.RAD;

                        bullet.m_Vel.x = BULLET_VEL * Math.cos(theta);
                        bullet.m_Vel.z = BULLET_VEL * Math.sin(theta);

                        m_Layer_Object.addChild(bullet);
                    }

                    RadOffset += TWO_PI * 0.5/BULLET_NUM;
                }

                return false;
            }
        }

        //Bullet : Sin
        public function CreateFunc_CreateBullets_Sin():Function{
            const BULLET_VEL:Number = 150.0;
            const BULLET_HEIGHT:Number = 50;
            const BULLET_CYCLE:int = 8;
            const BULLET_NUM:int = 64;
            const BULLET_PHASE:int = 3;
            const BULLET_INTERVAL:Number = 1.0;
            const BULLET_INTERVAL_END:Number = 2.0;

            //Member
            var Phase:int = 0;
            var RestTimer:Number = 0;
            var RadOffset:Number = 0;

            return function(in_DeltaTime:Number):Boolean{
                //Timer
                {
                    RestTimer -= in_DeltaTime;
                }

                if(RestTimer < 0){
                    //Phase
                    {
                        if(Phase == BULLET_PHASE){
                            Phase = 0;
                            RestTimer = 0;
                            RadOffset = 0;
                            return true;
                        }

                        Phase++;

                        if(Phase != BULLET_PHASE){
                            RestTimer += BULLET_INTERVAL;
                        }else{
                            RestTimer += BULLET_INTERVAL_END;
                        }
                    }

                    for(var i:int = 0; i < BULLET_NUM; i++){
                        var bullet:Bullet = new Bullet();

                        var theta:Number = TWO_PI * i/BULLET_NUM;

                        bullet.m_Pos.y = -BULLET_HEIGHT * (0.5 - 0.5*Math.cos(TWO_PI * i/BULLET_NUM * BULLET_CYCLE + RadOffset)) - Bullet.RAD;

                        bullet.m_Vel.x = BULLET_VEL * Math.cos(theta);
                        bullet.m_Vel.z = BULLET_VEL * Math.sin(theta);

                        m_Layer_Object.addChild(bullet);
                    }

                    RadOffset += Math.PI;
                }

                return false;
            }
        }

        //Bullet : AimRing
        public function CreateFunc_CreateBullets_AimRing():Function{
            const BULLET_VEL:Number = 150.0;
            const BULLET_RAD:Number = 60.0;
            const BULLET_RING_NUM:int = 2;
            const BULLET_RING_OFFSET:Number = 10.0;
            const BULLET_NUM:int = 12;
            const BULLET_PHASE:int = 3;
            const BULLET_INTERVAL:Number = 1.0;
            const BULLET_INTERVAL_END:Number = 2.0;

            //Member
            var Phase:int = 0;
            var RestTimer:Number = 0;
            var RadOffset:Number = 0;
            var ThetaOffset:Number = 0;

            return function(in_DeltaTime:Number):Boolean{
                //Timer
                {
                    RestTimer -= in_DeltaTime;
                }

                if(RestTimer < 0){
                    //Phase
                    {
                        if(Phase == BULLET_PHASE){
                            Phase = 0;
                            RestTimer = 0;
                            RadOffset = 0;
                            ThetaOffset = 0;
                            return true;
                        }

                        Phase++;

                        if(Phase != BULLET_PHASE){
                            RestTimer += BULLET_INTERVAL;
                        }else{
                            RestTimer += BULLET_INTERVAL_END;
                        }
                    }

                    for(var j:int = 0; j < BULLET_RING_NUM; j++){
                        RadOffset = -j * BULLET_RING_OFFSET;
                        ThetaOffset = TWO_PI * 0.5*j/BULLET_NUM;
                        for(var i:int = 0; i < BULLET_NUM; i++){
                            var bullet:Bullet = new Bullet();

                            var theta:Number = TWO_PI * i/BULLET_NUM + ThetaOffset;

                            var rad:Number = BULLET_RAD + RadOffset;

                            bullet.m_Pos.y = -Bullet.RAD - BULLET_RAD + rad * Math.sin(theta);
                            bullet.m_Pos.x = rad * Math.sin(-GameMain.Instance.m_CameraTheta) * Math.cos(theta);
                            bullet.m_Pos.z = rad * Math.cos(-GameMain.Instance.m_CameraTheta) * Math.cos(theta);

                            bullet.m_Vel.x = BULLET_VEL * Math.cos(GameMain.Instance.m_CameraTheta);
                            bullet.m_Vel.z = BULLET_VEL * Math.sin(GameMain.Instance.m_CameraTheta);

                            m_Layer_Object.addChild(bullet);
                        }
                    }
                }

                return false;
            }
        }

        //Bullet : AimDelayCircle
        public function CreateFunc_CreateBullets_AimDelayCircle():Function{
            const BULLET_VEL_MIN:Number = 80.0;
            const BULLET_VEL_MAX:Number = 300.0;
            const BULLET_HEIGHT:Number = 15.0;
            const BULLET_NUM:int = 4;
            const BULLET_PHASE:int = 32;
            const BULLET_INTERVAL:Number = 0.2;
            const BULLET_INTERVAL_END:Number = 2.0;

            //Member
            var Phase:int = 0;
            var RestTimer:Number = 0;
            var PreCameraTheta:Number = 0;

            return function(in_DeltaTime:Number):Boolean{
                //Timer
                {
                    RestTimer -= in_DeltaTime;
                }

                if(RestTimer < 0){
                    //Phase
                    {
                        if(Phase == BULLET_PHASE){
                            Phase = 0;
                            RestTimer = 0;
                            return true;
                        }

                        Phase++;

                        if(Phase != BULLET_PHASE){
                            RestTimer += BULLET_INTERVAL;
                        }else{
                            RestTimer += BULLET_INTERVAL_END;
                        }
                    }

                    var vel:Number;
                    {
                        vel = Lerp(BULLET_VEL_MIN, BULLET_VEL_MAX, (Phase-1.0) / (BULLET_PHASE-1.0)); 
                    }

                    var OffsetTheta:Number;
                    {
                        //プレイヤーの先回り
                        OffsetTheta = (GameMain.Instance.m_CameraTheta - PreCameraTheta) * (Phase-1) * 1.5;
                    }

                    for(var i:int = 0; i < BULLET_NUM; i++){
                        var bullet:Bullet;

                        var theta:Number = TWO_PI * i/BULLET_NUM + OffsetTheta;

                        {
                            bullet = new Bullet();

                            bullet.m_Pos.y = -Bullet.RAD;

                            bullet.m_Vel.x = vel * Math.cos(GameMain.Instance.m_CameraTheta + theta);
                            bullet.m_Vel.z = vel * Math.sin(GameMain.Instance.m_CameraTheta + theta);

                            m_Layer_Object.addChild(bullet);
                        }

                        {
                            bullet = new Bullet();

                            bullet.m_Pos.y = -Bullet.RAD - BULLET_HEIGHT;

                            bullet.m_Vel.x = vel * Math.cos(GameMain.Instance.m_CameraTheta + theta);
                            bullet.m_Vel.z = vel * Math.sin(GameMain.Instance.m_CameraTheta + theta);

                            m_Layer_Object.addChild(bullet);
                        }
                    }
                }

                PreCameraTheta = GameMain.Instance.m_CameraTheta;

                return false;
            }
        }

        //Input
        private function SetInput(in_KeyCode:uint, in_Flag:Boolean):void{
            switch (in_KeyCode){
            case Keyboard.UP:
                m_Input[INPUT_U] = in_Flag;
                break;
            case Keyboard.DOWN:
                m_Input[INPUT_D] = in_Flag;
                break;
            case Keyboard.LEFT:
                m_Input[INPUT_L] = in_Flag;
                break;
            case Keyboard.RIGHT:
                m_Input[INPUT_R] = in_Flag;
                break;
            case Keyboard.SPACE://SPACE
            case 90://Z
                m_Input[INPUT_JUMP] = in_Flag;
                break;
            }
        }
        public function onKeyDown(event:KeyboardEvent):void{
            SetInput(event.keyCode, true);
        }
        public function onKeyUp(event:KeyboardEvent):void{
            SetInput(event.keyCode, false);
        }


        //Utility
        static 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.geom.*;
import flash.filters.*;

class GameObject extends Sprite{
    //==Var==

    //絶対座標
    public var m_Pos:Vector3D = new Vector3D(0,0,0);


    //==Function==

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

class Player extends GameObject{
    //==Const==

    //移動速度
    static public const MOVE_VEL:Number = 120.0;

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

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


    //==Var==

    //中心からの距離
    public var m_Distance:Number = GameMain.GROUND_RAD*3/4;

    //移動速度
    public var m_Vel:Vector3D = new Vector3D(0,0,0);

    //表示画像本体
    public var m_Bitmap:Bitmap;


    //==Function==

    //Init
    public function Player(){
        //Graphic
        {
            m_Bitmap = new Bitmap(GameMain.m_Bitmap_Player.bitmapData);

            m_Bitmap.x = -32/2;
            m_Bitmap.y = -32;

            addChild(m_Bitmap);
        }
    }

    //Update
    override public function Update(in_DeltaTime:Number):void{
        //速度更新
        {
            m_Vel.y += GRAVITY * in_DeltaTime;
        }

        //位置更新
        {
            m_Pos.y += m_Vel.y * in_DeltaTime;
        }

        //接地チェック
        {
            if(m_Pos.y >= 0){
                m_Pos.y = 0;
                m_Vel.y = 0;
                GameMain.Instance.m_UpdateRatio = 1.0;//スローを元に戻す
            }
        }
    }

    //Jump
    public function TryJump():void{
        if(m_Pos.y >= 0){
            m_Vel.y = -JUMP_VEL;
            GameMain.Instance.m_UpdateRatio = 0.5;//ジャンプ中だけスロー
        }
    }
}

class Bullet extends GameObject{
    //==Const==

    //弾の大きさ
    static public const RAD:int = 8;

    //線の太さ
    static public const GLOW_W:int = 8;

    //弾の色:内側
    static public const COLOR_IN:uint = 0xFFFF00;

    //弾の色:外側
    static public const COLOR_OUT:uint = 0xFF4400;

    //被写界深度もどきを何段階用意するか
    static public const BLUR_NUM:int = 10;

    //オリジナル画像(事前計算しておく)
    static public var m_BitmapData_Ori:Array;


    //==Var==

    //移動速度
    public var m_Vel:Vector3D = new Vector3D(0,0,0);

    //表示画像本体
    public var m_Bitmap:Bitmap;

    //表示Index(被写界深度もどき用)
    public var m_BlurIndex:int = 0;


    //==Function==

    //Static Init
    static public function Ready():void{
        if(m_BitmapData_Ori == null){
            m_BitmapData_Ori = new Array(BLUR_NUM);

            //Ori
            {
                //元画像
                var shape:Shape = new Shape();
                {
                    //内側をGraphicsで描く
                    {
                        var g:Graphics = shape.graphics;

                        g.lineStyle(0, 0x000000, 0.0);
                        g.beginFill(COLOR_IN, 1.0);
                        g.drawCircle(1.5*RAD, 1.5*RAD, RAD);
                        g.endFill();
                    }

                    //外側をFilterで描く
                    {
                        const strength:int = 2;
                        shape.filters = [
                            new GlowFilter(COLOR_OUT, 1.0, GLOW_W, GLOW_W, strength, 1, true)
                        ];
                    }
                }

                //保存
                {
                    m_BitmapData_Ori[0] = new BitmapData(3*RAD, 3*RAD, true, 0x00000000);
                    m_BitmapData_Ori[0].draw(shape);
                }
            }

            //Blur
            {
                for(var i:int = 1; i < BLUR_NUM; i++){
                    var blur:int = i;
                    m_BitmapData_Ori[i] = new BitmapData(3*RAD, 3*RAD, true, 0x00000000);
                    m_BitmapData_Ori[i].applyFilter(m_BitmapData_Ori[0], m_BitmapData_Ori[0].rect, GameMain.POS_ZERO, new BlurFilter(blur, blur));
                }
            }
        }
    }

    //Init
    public function Bullet(){
        //Graphic
        {
            m_Bitmap = new Bitmap(m_BitmapData_Ori[m_BlurIndex]);

            m_Bitmap.x = -RAD;
            m_Bitmap.y = -RAD;

            addChild(m_Bitmap);
        }
    }

    //Update
    override public function Update(in_DeltaTime:Number):void{
        //位置更新
        {
            m_Pos.x += m_Vel.x * in_DeltaTime;
            m_Pos.y += m_Vel.y * in_DeltaTime;
            m_Pos.z += m_Vel.z * in_DeltaTime;
        }

        //レンジチェック
        {
            var LenXZ:Number = Math.sqrt(m_Pos.x*m_Pos.x + m_Pos.z*m_Pos.z);

            const FadeOutLen:Number = 30.0;

            if(GameMain.GROUND_RAD - FadeOutLen < LenXZ){
                if(GameMain.GROUND_RAD <= LenXZ){
                    //Kill
                    parent.removeChild(this);
                    return;
                }else{
                    //Alpha
                    this.alpha = (GameMain.GROUND_RAD - LenXZ) / FadeOutLen;
                }
            }
        }
//*
        //被写界深度っぽいもの
        {
            var val:Number = -GameMain.GROUND_RAD * 0.9;

            var blur_index:int = (BLUR_NUM-1) * Math.min(Math.abs(z - val) / (2*GameMain.GROUND_RAD), 1);

            if(m_BlurIndex != blur_index){
                m_BlurIndex = blur_index;
                m_Bitmap.bitmapData = m_BitmapData_Ori[m_BlurIndex];
            }
        }
//*/
    }
}