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

断斬 ~Touch&Kill~

クリック(Click)
- 移動(Move)&攻撃(Attack)

スコア
- 敵をまとめて倒すと得点が上がります
- 斬った後、そのまま移動してまた倒すと少し得点が上がります
- おじいちゃんを斬ると減点です
- ラストの火の玉のみ、ぶつかると減点です
-- 他のエネミーにはぶつかっても減点されません
Get Adobe Flash player
by o_healer 07 Sep 2011
/**
 * 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/1ubK
 */

/*
 「断斬~Touch&Kill~」
 ・クリックでキャラを移動させ、エネミーを倒すゲーム

 操作方法
 ・クリック
  ・クリック位置にキャラクターが移動
  ・移動中に接触するとエネミーを倒せる
*/

/*
ToDo

処理
・ボス
 ・ボスを倒したらスコアへ
・エネミー:ゴースト
 ・当たり判定の定期オンオフ
 ・今回は不要っぽいので作成保留

*/


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

        //画像のリソース位置
//*
        //wonderfl用ロード型
        static public const URL_GRAPHICS:String = "http://assets.wonderfl.net/images/related_images/0/06/06f2/06f2388a4ff3e3640a4afd47d26dc33881112f6b";
//*/
/*
        //確認用ローカルロード型
        static public const URL_GRAPHICS:String = "TouchKill.png";
//*/
/*
        //ブログ用埋め込み型
        [Embed(source='TouchKill.png')]
         private static var Bitmap_Graphics: Class;
//*/

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

        //エネミーの当たり判定(直径)
        static public const HIT_RANGE:int = 32;

        //画像サイズ
        static public const PANEL_W:int = 24;
        static public const PANEL_H:int = 32;
        static public const BMP_W:int = 24;
        static public const BMP_H:int = 40;//陰用に元画像より少し下に長くする
        static public const PANEL_NUM_X:int = 3;
        static public const PANEL_NUM_Y:int = 4;


        //エネミーの出現パターン
        static public var EnemyIter:int = 0;
        static public const GB:int = EnemyIter++;//TYPE_GOBLIN
        static public const SN:int = EnemyIter++;//TYPE_SNAKE
        static public const OG:int = EnemyIter++;//TYPE_OGRE
        static public const GH:int = EnemyIter++;//TYPE_GOHST
        static public const HU:int = EnemyIter++;//TYPE_HUMAN
        static public const BS:int = EnemyIter++;//TYPE_BOSS
        static public const FR:int = EnemyIter++;//TYPE_FIRE
        static public const XX:int = EnemyIter++;//EMPTY
        //ステージ構成
        //- 下から順に出てくるので注意
        static public const ENEMY_SEQ:Array = [
            //#ボス戦
            [XX, BS, XX],
//*
            [XX, XX, XX],
            [XX, XX, XX],
            [XX, XX, XX],
            [XX, XX, XX],

            //#人質に紛れて突入
            [XX, XX, XX],
            [XX, XX, XX],
            [HU, GB, HU],
            [HU, GB, HU],
            [HU, GB, HU],
            [XX, XX, XX],
            [XX, XX, XX],
            [HU, HU, HU],
            [XX, GB, XX],
            [HU, HU, HU],
            [XX, XX, XX],
            [XX, OG, XX],

            //#人質の帰還
            [XX, XX, XX],
            [XX, XX, XX],
            [XX, XX, HU],
            [HU, XX, XX],
            [XX, HU, XX],

            //#オーグ登場
            [XX, XX, XX],
            [XX, XX, XX],
            [OG, XX, OG],
            [XX, XX, XX],
            [XX, OG, XX],

            //#ゴブリンとスネークの混合
            [XX, XX, XX],
            [XX, XX, XX],
            [XX, SN, XX],
            [XX, XX, XX],
            [GB, SN, GB],
            [XX, XX, XX],
            [GB, XX, GB],

            //#スネークで奇襲
            [XX, XX, XX],
            [XX, XX, XX],
            [SN, XX, SN],
            [XX, XX, XX],
            [XX, SN, XX],

            //#斜め
            [XX, XX, XX],
            [XX, XX, XX],
            [XX, XX, GB],
            [XX, GB, XX],
            [GB, XX, XX],
            [XX, XX, XX],
            [GB, XX, XX],
            [XX, GB, XX],
            [XX, XX, GB],

            //#ゴブリンで小手調べ
            [XX, XX, XX],
            [XX, XX, XX],
            [GB, GB, GB],
            [XX, XX, XX],
            [GB, GB, GB],
            [XX, XX, XX],
            [GB, GB, GB],
//*/
        ];

        //==Var==

        //Pseudo Singleton
        static public var Instance:GameMain;

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

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

        //エネミー
        public var m_EnemyTimer:Number = 0;//生成管理用タイマー
        //エネミーの出現管理用のイテレータ
        public var m_EnemySeqIter:int = ENEMY_SEQ.length-1;

        //背景
        public var m_BitmapData_BG:BitmapData = new BitmapData(VIEW_W, VIEW_H, false, 0x000000);

        //ガイドライン
        public var m_GuideLine:Graphics;

        //スコア
        public var m_Score:int = 0;
        public var m_GlobalCombo:int = 0;
        public var m_ScoreDataBegin:ScoreData;

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

        //==Function==

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

            //Pseudo Singleton
            {
                Instance = this;
            }

            //Static Init
            {
                Player.Initialize();
                Enemy.Initialize();
                ScoreWindowLoader.init(this, new WonderflAPI(loaderInfo.parameters));
            }

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

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

                    //キャラクター:エネミー
                    m_Layer_Root.addChild(m_Layer_Enemy);
                    //キャラクター:プレイヤー
                    m_Layer_Root.addChild(m_Layer_Player);

                    //UI:スコア
                    m_Layer_Root.addChild(m_Layer_Effect);
                }
            }

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

            //ガイドライン
            {
                var s:Sprite = new Sprite();
                m_GuideLine = s.graphics;

                m_Layer_BG.addChild(s);
            }

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

                //左中央に配置
                m_Player.x = VIEW_W/8;
                m_Player.y = VIEW_H/2;

                m_Layer_Player.addChild(m_Player);
            }


            //Text
            {
                m_Text_Score.selectable = false;
                m_Text_Score.autoSize = TextFieldAutoSize.RIGHT;
                m_Text_Score.defaultTextFormat = new TextFormat('Verdana', 16, 0xFFFFFF, true);
                m_Text_Score.text = '0';
                m_Text_Score.filters = [new GlowFilter(0x00FFFF,1.0, 4,4)];

                m_Text_Score.x = VIEW_W - 32;
                m_Text_Score.y = 0;

                addChild(m_Text_Score);
            }
            {
                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);
            }

            //Click
            {
                stage.addEventListener(
                    MouseEvent.CLICK,
                    onClick
                );
                stage.addEventListener(
                    MouseEvent.MOUSE_MOVE,
                    onMove
                );
            }

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

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

        //ロード終了時の処理
        public function OnLoadEnd(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, BMP_W,BMP_H);
            var clip_rect:Rectangle = new Rectangle(0,0, PANEL_W,PANEL_H);
            const pos_zero:Point = new Point(0,0);

            //足元の影画像
            var bmd_shadow:BitmapData = new BitmapData(BMP_W, BMP_H, true, 0x00000000);
            {
                var shadow_sp:Sprite = new Sprite();
                var g:Graphics = shadow_sp.graphics;
                g.lineStyle(0,0,0);
                g.beginFill(0x000000, 0.6);
                g.drawEllipse(0, BMP_H-BMP_W/2, BMP_W, BMP_W/2);
                g.endFill();
                bmd_shadow.draw(shadow_sp);
            }

            //プレイヤー画像
            {
                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.copyPixels(bmd_shadow, rect, pos_zero);
                        //Draw
                        mtx.tx = -index_x*PANEL_W;
                        mtx.ty = -index_y*PANEL_H;
                        bmd.draw(in_Graphic, mtx, null, null, clip_rect);
                    }
                }
            }

            //エネミー画像
            {
                var index_type:int;
                var offset_x:int = 0;
                var offset_y:int = 0;
                index_y = 0;
                for(index_type = 0; index_type < Enemy.TYPE_NUM; index_type++){
                    switch(index_type){
                    case Enemy.TYPE_GOBLIN:
                        offset_x = PANEL_W*PANEL_NUM_X * 1; offset_y = PANEL_H * 0; break;
                    case Enemy.TYPE_SNAKE:
                        offset_x = PANEL_W*PANEL_NUM_X * 1; offset_y = PANEL_H * 1; break;
                    case Enemy.TYPE_OGRE:
                        offset_x = PANEL_W*PANEL_NUM_X * 1; offset_y = PANEL_H * 2; break;
                    case Enemy.TYPE_GOHST:
                        offset_x = PANEL_W*PANEL_NUM_X * 1; offset_y = PANEL_H * 0; break;
                    case Enemy.TYPE_HUMAN:
                        offset_x = PANEL_W*PANEL_NUM_X * 1; offset_y = PANEL_H * 3; break;
                    case Enemy.TYPE_BOSS:
                        offset_x = PANEL_W*PANEL_NUM_X * 2; offset_y = PANEL_H * 3; break;
                    case Enemy.TYPE_FIRE:
                        offset_x = PANEL_W*PANEL_NUM_X * 2; offset_y = PANEL_H * 2; break;
                    }
                    for(index_x = 0; index_x < PANEL_NUM_X; index_x++){
                        bmd = Enemy.m_BitmapDataList[index_type][index_x];
                        //Clear
                        bmd.copyPixels(bmd_shadow, rect, pos_zero);
                        //Draw
                        mtx.tx = -offset_x - index_x*PANEL_W;
                        mtx.ty = -offset_y - index_y*PANEL_H;
                        bmd.draw(in_Graphic, mtx, null, null, clip_rect);
                    }
                }
            }

            //背景画像
            {
                clip_rect.width  = 16;
                clip_rect.height = 16;

                //まずは個別の画像を一旦保持
                var bmd_bg_g:BitmapData = new BitmapData(16,16,false,0x000000);
                var bmd_bg_s:BitmapData = new BitmapData(16,16,false,0x000000);
                var bmd_bg_l:BitmapData = new BitmapData(16,16,false,0x000000);
                var bmd_bg_r:BitmapData = new BitmapData(16,16,false,0x000000);
                {
                    mtx.tx = -PANEL_W*PANEL_NUM_X * 2 - 16*1;
                    mtx.ty = -PANEL_H*PANEL_NUM_Y * 0;
                    bmd_bg_g.draw(in_Graphic, mtx);

                    mtx.tx = -PANEL_W*PANEL_NUM_X * 2 - 16*1;
                    mtx.ty = -PANEL_H*PANEL_NUM_Y * 0 - 16 * 2;
                    bmd_bg_s.draw(in_Graphic, mtx);

                    mtx.tx = -PANEL_W*PANEL_NUM_X * 2 - 16*0;
                    mtx.ty = -PANEL_H*PANEL_NUM_Y * 0 - 16 * 2;
                    bmd_bg_l.draw(in_Graphic, mtx);

                    mtx.tx = -PANEL_W*PANEL_NUM_X * 2 - 16*2;
                    mtx.ty = -PANEL_H*PANEL_NUM_Y * 0 - 16 * 2;
                    bmd_bg_r.draw(in_Graphic, mtx);
                }

                //上のラインに敷き詰める
                {
                    var offset:int = 8;
                    mtx.ty = 0;

                    var CenterX:int = VIEW_W/2;

                    bmd = bmd_bg_s;
                    for(; offset < VIEW_W*6/20; offset += 16){
                        mtx.tx = CenterX + offset - 8;
                        m_BitmapData_BG.draw(bmd, mtx);

                        mtx.tx = CenterX - offset - 8;
                        m_BitmapData_BG.draw(bmd, mtx);
                    }

                    {
                        mtx.tx = CenterX + offset - 8;
                        m_BitmapData_BG.draw(bmd_bg_r, mtx);

                        mtx.tx = CenterX - offset - 8;
                        m_BitmapData_BG.draw(bmd_bg_l, mtx);

                        offset += 16;
                    }

                    bmd = bmd_bg_g;
                    for(; offset < VIEW_W/2 + 16; offset += 16){
                        mtx.tx = CenterX + offset - 8;
                        m_BitmapData_BG.draw(bmd, mtx);

                        mtx.tx = CenterX - offset - 8;
                        m_BitmapData_BG.draw(bmd, mtx);
                    }
                }

                //それを下にコピー
                {
                    var src_rect:Rectangle = new Rectangle(0,0,VIEW_W,16);
                    var dst_point:Point = new Point(0,0);

                    for(index_y = 1; ; index_y++){
                        dst_point.y = index_y * 16;

                        if(dst_point.y > VIEW_H){break;}

                        m_BitmapData_BG.copyPixels(
                            m_BitmapData_BG,
                            src_rect,
                            dst_point
                        );
                    }
                }
            }
        }

        //Move
        public function onMove(e:MouseEvent):void{
            m_GuideLine.clear();
            m_GuideLine.lineStyle(4, 0xFF0000, 0.5);
            m_GuideLine.moveTo(m_Player.x, m_Player.y);
            m_GuideLine.lineTo(m_Player.parent.mouseX, m_Player.parent.mouseY);
        }
        //Click
        public function onClick(e:MouseEvent):void{
            var i:int;
            var j:int;
            var num:int;
            var enemy:Enemy;

            var SrcX:int = m_Player.x;
            var SrcY:int = m_Player.y;
            var DstX:int = m_Player.parent.mouseX;
            var DstY:int = m_Player.parent.mouseY;

            var GapX:int = DstX - SrcX;
            var GapY:int = DstY - SrcY;
            var MoveDistance:Number = Math.sqrt(GapX*GapX + GapY*GapY);

            m_GuideLine.clear();

            //移動してないなら何もしない
            if(MoveDistance < 1){
                return;
            }

            //攻撃処理
            //この時点ではフラグを立てるだけで、すぐにKillはしない?
            num = m_Layer_Enemy.numChildren;
            for(i = 0; i < num; i++){
                enemy = m_Layer_Enemy.getChildAt(i) as Enemy;

                var EnemyGapX:int = enemy.x - SrcX;
                var EnemyGapY:int = enemy.y - SrcY;

                //進行方向に対する内積
                var DistanceForward:Number = (GapX*EnemyGapX + GapY*EnemyGapY) / MoveDistance;
                if(0 <= DistanceForward && DistanceForward < MoveDistance){
                    //進行横方向に対する内積
                    var DistanceSide:Number = (GapY*EnemyGapX - GapX*EnemyGapY) / MoveDistance;
                    if(-HIT_RANGE <= DistanceSide && DistanceSide <= HIT_RANGE){
                        //ダメージを与える
                        enemy.onDamage(1);

                        //スコア計算用準備
                        //- 人質が途中に入っていたらそこでリセットされるため、あとでまとめてチェックする

                        //距離に基づくソート
                        PushScore(
                            DistanceForward,
                            enemy.x,
                            enemy.y,
                            enemy.m_Type
                        );
                    }
                }
            }

            //スコアを実際に計算
            RefreshScore();

            //Effect
            m_Layer_Effect.addChild(new SlashEffect(SrcX, SrcY, DstX, DstY));

            //プレイヤーを実際に移動
            m_Player.x = DstX;
            m_Player.y = DstY;
        }

        //Score : 追加
        public function PushScore(in_Distance:Number, in_X:Number, in_Y:Number, in_Type:int):void{
            var score_data:ScoreData = new ScoreData(
                in_Distance,
                in_X,
                in_Y,
                in_Type
            );

            //あまりエレガントでない書き方になったがリスト挿入
            if(m_ScoreDataBegin == null){
                //最初にセット
                m_ScoreDataBegin = score_data;
            }else{
                for(var iter:ScoreData = m_ScoreDataBegin; iter != null; iter = iter.next){
                    if(in_Distance < iter.distance){
                        //iterの手前に挿入
                        score_data.prev = iter.prev;
                        score_data.next = iter;

                        if(score_data.prev != null){
                            score_data.prev.next = score_data;
                        }else{
                            m_ScoreDataBegin = score_data;
                        }
                        if(score_data.next != null){
                            score_data.next.prev = score_data;
                        }

                        break;
                    }

                    if(iter.next == null){
                        //末尾に追加
                        score_data.prev = iter;
                        iter.next = score_data;

                        break;
                    }
                }
            }
        }

        //Score : 追加(直接)(コンボなし)
        public function AddScore(in_X:Number, in_Y:Number, in_Val:int):void{
            //スコア加算
            m_Score += in_Val;

            //スコア表示
            m_Layer_Effect.addChild(new ScoreView(in_X, in_Y, in_Val));

            //合計スコアの表示更新
            m_Text_Score.text = m_Score.toString();
        }

        //Score : 反映
        public function RefreshScore():void{
            var local_combo:int = 0;
            var score:int = 0;

            for(var iter:ScoreData = m_ScoreDataBegin; iter != null; iter = iter.next){
                switch(iter.type){
                case Enemy.TYPE_FIRE:
                    //火の玉

                    //コンボ中断
                    //!!
                    local_combo = 0;
                    m_GlobalCombo = 0;

                    //スコア計算
                    score = -1;

                    //スコア減算
                    m_Score += score;

                    //スコア表示
                    m_Layer_Effect.addChild(new ScoreView(iter.x, iter.y, score));

                    break;
                case Enemy.TYPE_HUMAN:
                    //人質

                    //コンボ中断
                    //!!
                    local_combo = 0;
                    m_GlobalCombo = 0;

                    //スコア計算
                    score = -10;

                    //スコア減算
                    m_Score += score;

                    //スコア表示
                    m_Layer_Effect.addChild(new ScoreView(iter.x, iter.y, score));

                    break;
                default:
                    //敵

                    //コンボ数++
                    ++local_combo;
                    ++m_GlobalCombo;

                    //スコア計算
                    if(m_GlobalCombo == local_combo){
                        //前回のコンボからはつながってない場合(通常挙動)
                        score = local_combo;
                    }else{
                        //前回のコンボからつながってる場合
                        score = local_combo+1;
                    }

                    //スコア加算
                    m_Score += score;

                    //スコア表示
                    m_Layer_Effect.addChild(new ScoreView(iter.x, iter.y, score));

                    break;
                }

                //相互リンクを切って解放できるようにしておく
                iter.prev = null;
            }

            //ヒットがなければコンボ中断
            if(local_combo == 0){
                m_GlobalCombo = 0;
            }

            //合計スコアの表示更新
            m_Text_Score.text = m_Score.toString();

            //先頭からのリンクを切って解放する
            m_ScoreDataBegin = null;
        }

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

            //Player
            m_Player.Update(DeltaTime);

            //Enemy
            Update_Enemy(DeltaTime);

            //Effect
            Update_Effect(DeltaTime);
        }

        //Update : Score
        public function Update_Effect(in_DeltaTime:Number):void{
            var i:int;
            var num:int;
            var uo:UpdateObject;

            //個別Update
            num = m_Layer_Effect.numChildren;
            for(i = 0; i < num; i++){
                uo = m_Layer_Effect.getChildAt(i) as UpdateObject;

                //更新
                uo.Update(in_DeltaTime);

                //死亡チェック
                if(uo.parent == null){//登録が解除された
                    num -= 1;//更新
                    i--;//相殺
                    continue;
                }
            }
        }

        //Update : Enemy
        public function Update_Enemy(in_DeltaTime:Number):void{
            var i:int;
            var num:int;
            var enemy:Enemy;

            //生成
/*
            //!!仮
            const Interval:Number = 2.0;
            m_EnemyTimer += in_DeltaTime;
            if(Interval < m_EnemyTimer){
                m_EnemyTimer -= Interval;

                for(i = 0; i < 3; i++){
                    enemy = new Enemy(Enemy.TYPE_GOBLIN);

                    enemy.x = VIEW_W * (i+1)/4;
                    enemy.y = -32;

                    m_Layer_Enemy.addChild(enemy);
                }
            }
/*/
            var type:int;

            const Interval:Number = 2.0;
            m_EnemyTimer += in_DeltaTime;
            if(Interval < m_EnemyTimer){
                m_EnemyTimer -= Interval;

                if(0 <= m_EnemySeqIter){
                    for(i = 0; i < 3; i++){
                        type = ENEMY_SEQ[m_EnemySeqIter][i];

                        if(type != XX){
                            enemy = new Enemy(type);

                            enemy.x = VIEW_W * (i+1)/4;
                            enemy.y = -32;

                            m_Layer_Enemy.addChild(enemy);
                        }
                    }

                    //
                    --m_EnemySeqIter;
                }else{
                }
            }
//*/

            //個別Update
            num = m_Layer_Enemy.numChildren;
            for(i = 0; i < num; i++){
                enemy = m_Layer_Enemy.getChildAt(i) as Enemy;

                //更新
                enemy.Update(in_DeltaTime);

                //死亡チェック
                if(enemy.parent == null){//登録が解除された
                    num -= 1;//更新
                    i--;//相殺
                    continue;
                }

                //さらにプレイヤーとぶつかっていたらプレイヤーを横にどける
                var GapX:Number = m_Player.x - enemy.x;
                var GapY:Number = m_Player.y - enemy.y;
//                var Distance:Number = Math.sqrt(GapX*GapX + 4*GapY*GapY);
                var Distance:Number = Math.sqrt(GapX*GapX + 2*GapY*GapY);
                var Range:Number = 16 * enemy.scaleX;
                if(Distance < Range){
                    if(enemy.m_Type != Enemy.TYPE_FIRE){
                        if(0 < GapX){
                            m_Player.x = enemy.x + Math.sqrt(Range*Range - GapY*GapY);
                        }else{
                            m_Player.x = enemy.x - Math.sqrt(Range*Range - GapY*GapY);
                        }
                    }else{
                        //炎に触れるとダメージ、の代わりにスコア減点
                        if(1 <= enemy.alpha){
                            AddScore(
                                m_Player.x,
                                m_Player.y,
                                -1
                            );

                            enemy.alpha = 0.5;
                        }
                    }
                }
            }
        }

    }
}


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


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

class UpdateObject extends Sprite{
    public function Update(in_DeltaTime:Number):void{
    }
}


//#Score
class ScoreData{
    public var distance:Number;
    public var x:Number;
    public var y:Number;
    public var type:int;
    public var next:ScoreData;
    public var prev:ScoreData;

    //Init
    public function ScoreData(in_Distance:Number, in_X:Number, in_Y:Number, in_Type:int){
        distance = in_Distance;
        x = in_X;
        y = in_Y;
        type = in_Type;
    }
}

class ScoreView extends UpdateObject{
    public var m_Text_Score:TextField = new TextField();

    //Init
    public function ScoreView(in_X:int, in_Y:int, in_Score:int){
        //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 = ((in_Score < 0)? "": "+") + in_Score.toString();
            m_Text_Score.filters = [new GlowFilter((in_Score < 0)? 0xFF0000: 0x00FFFF,1.0, 4,4)];

            m_Text_Score.x = -m_Text_Score.width/2;
            m_Text_Score.y = -m_Text_Score.height/2;

            addChild(m_Text_Score);
        }

        //Pos
        {
            this.x = in_X;
            this.y = in_Y - 32;
        }
    }

    //Update
    override public function Update(in_DeltaTime:Number):void{
/*
        const ScaleVel:Number = 1.0;
        const ScaleThr:Number = 1.5;

        var scl:Number = this.scaleX + ScaleVel * in_DeltaTime;
        if(ScaleThr < scl){scl = ScaleThr;}

        this.scaleX = this.scaleY = scl;
        this.alpha = (ScaleThr - scl) / (ScaleThr - 1);
/*/
        const AlphaVel:Number = 0.5;

        this.alpha -= AlphaVel * in_DeltaTime;
//*/

        if(this.alpha <= 0){
            //Kill
            parent.removeChild(this);//描画登録の解除で実現
        }
    }
}


class SlashEffect extends UpdateObject{
    //
    static public const W:int = 8;

    //
    public var m_CT:ColorTransform = new ColorTransform();

    //Init
    public function SlashEffect(in_SrcX:int, in_SrcY:int, in_DstX:int, in_DstY:int){
        //
        {
            var GapX:int = in_DstX - in_SrcX;
            var GapY:int = in_DstY - in_SrcY;

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

            var g:Graphics = this.graphics;
            g.lineStyle(0,0,0);
            g.beginFill(0xFF0000, 1.0);
            g.drawEllipse(-Len/2, -W/2, Len, W);
            g.endFill();
            Len *= 0.9;
            g.beginFill(0xFFFF00, 1.0);
            g.drawEllipse(-Len/2, -W/2, Len, W);
            g.endFill();
            Len *= 0.9;
            g.beginFill(0xFFFFFF, 1.0);
            g.drawEllipse(-Len/2, -W/2, Len, W);
            g.endFill();

            this.rotation = Math.atan2(GapY, GapX) * 180/Math.PI;

            this.x = (in_SrcX + in_DstX)/2;
            this.y = (in_SrcY + in_DstY)/2;

            this.blendMode = BlendMode.ADD;
        }
    }

    //Update
    override public function Update(in_DeltaTime:Number):void{
        const AlphaVel:Number = 3.0;

        this.alpha -= AlphaVel * in_DeltaTime;

        //αを減らしつつ加算合成で表示するのは上手くいかない(RGBを減らさなければいけない)ので以下のようにやる
        m_CT.redMultiplier = this.alpha;
        m_CT.greenMultiplier = this.alpha;
        m_CT.blueMultiplier = this.alpha;
        m_CT.alphaMultiplier = this.alpha;
        this.transform.colorTransform = m_CT;

        if(this.alpha <= 0){
            //Kill
            parent.removeChild(this);//描画登録の解除で実現
        }
    }
}


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

    //アニメーション用定数
    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:Vector.<Vector.<BitmapData> >;

    //Init
    static public function Initialize():void{
        //m_BitmapDataList
        {
            m_BitmapDataList = new Vector.<Vector.<BitmapData> >(GameMain.PANEL_NUM_Y);
            for(var y:int = 0; y < GameMain.PANEL_NUM_Y; y++){
                m_BitmapDataList[y] = new Vector.<BitmapData>(GameMain.PANEL_NUM_X);
                for(var x:int = 0; x < GameMain.PANEL_NUM_X; x++){
                    m_BitmapDataList[y][x] = new BitmapData(GameMain.BMP_W, GameMain.BMP_H, true, 0xFF0000FF);
                }
            }
        }
    }


    //==Var==

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


    //==Function==

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

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

        //移動
//        Update_Move(in_DeltaTime);

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

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

    //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];
    }
/*
    //Check : Dead
    public function Check_Dead():void{
        //Check
        {
            if(m_IsDead){
                return;
            }
        }
    }

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


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

    static public var TypeIter:int = 0;
    static public const TYPE_GOBLIN:int    = TypeIter++;
    static public const TYPE_SNAKE:int    = TypeIter++;
    static public const TYPE_OGRE:int    = TypeIter++;
    static public const TYPE_GOHST:int    = TypeIter++;
    static public const TYPE_HUMAN:int    = TypeIter++;
    static public const TYPE_BOSS:int    = TypeIter++;
    static public const TYPE_FIRE:int    = TypeIter++;
    static public const TYPE_NUM:int    = TypeIter;

    //画像
    static public var m_BitmapDataList:Vector.<Vector.<BitmapData> >;

    //アニメーション用パラメータ
    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;


    //==Var==

    //Type
    public var m_Type:int = 0;

    //Graphic
    public var m_Bitmap:Bitmap = new Bitmap();
    //アニメーション用タイマー
    public var m_AnimTimer:Number = 0.0;

    //HP
    public var m_HP:int = 1;

    //汎用タイマー
    public var m_Timer:Number = 0;
    //ボス用リスト
    public var m_List:Vector.<Enemy> = new Vector.<Enemy>();


    //==Function==

    //Static Init
    static public function Initialize():void{
        m_BitmapDataList = new Vector.<Vector.<BitmapData> >(TYPE_NUM);

        for(var i:int = 0; i < TYPE_NUM; i++){
            m_BitmapDataList[i] = new Vector.<BitmapData>(GameMain.PANEL_NUM_X);
            for(var j:int = 0; j < GameMain.PANEL_NUM_X; j++){
                m_BitmapDataList[i][j] = new BitmapData(GameMain.BMP_W, GameMain.BMP_H, true, 0x22000000);
            }
        }
    }

    //Init
    public function Enemy(in_Type:int){
        //Param
        {
            m_Type = in_Type;

            if(in_Type == TYPE_OGRE){
                m_HP = 2;
                this.scaleX = this.scaleY = m_HP;
            }

            if(in_Type == TYPE_BOSS){
                m_HP = 10;
                this.scaleX = this.scaleY = Math.sqrt(m_HP);

                var fire:Enemy = new Enemy(TYPE_FIRE);
                fire.m_Timer = -1;// ボス側で操作するため
                m_List.push(fire);
                GameMain.Instance.m_Layer_Enemy.addChild(fire);
            }

            if(in_Type == TYPE_FIRE){
                m_HP = -1;
            }
        }

        //Graphic
        {
/*
            //!!仮画像
            var g:Graphics = this.graphics;
            g.lineStyle(0,0,0);
            g.beginFill(0xFF0000, 1.0);
            g.drawCircle(0,0, 16);
            g.endFill();
/*/
            m_Bitmap.x = -GameMain.PANEL_W/2;
            m_Bitmap.y = -GameMain.PANEL_H;
            addChild(m_Bitmap);
//*/
        }
    }

    //Update
    public function Update(in_DeltaTime:Number):void{
        const BOSS_CYCLE:Number = 2.0;

        var en:Enemy;

        //Check HP
        if(m_HP == 0){
            //Kill
            this.parent.removeChild(this);
            return;
        }

        //Move
        switch(m_Type){
        case TYPE_GOBLIN:
            this.y += 40 * in_DeltaTime;
            break;
        case TYPE_SNAKE:
            this.y += 120 * in_DeltaTime;
            break;
        case TYPE_OGRE:
            this.y += 40 * in_DeltaTime;
            break;
        case TYPE_GOHST:
            this.y += 30 * in_DeltaTime;
            break;
        case TYPE_HUMAN:
            this.y += 40 * in_DeltaTime;
            break;
        case TYPE_BOSS:
            this.y += 40 * in_DeltaTime;
            if(GameMain.VIEW_H/4 < this.y){
                this.y = GameMain.VIEW_H/4;
            }
            m_Timer += in_DeltaTime;
            if(2*BOSS_CYCLE < m_Timer){
                m_Timer -= 2*BOSS_CYCLE;

                if(m_HP < 7){
                    en = new Enemy(TYPE_FIRE);

                    //移動角度をm_Timerに詰めてやりくりしてしまう
                    var GapX:Number = GameMain.Instance.m_Player.x - this.x;
                    var GapY:Number = GameMain.Instance.m_Player.y - this.y;
                    en.m_Timer = Math.atan2(GapY, GapX) + 2*Math.PI;

                    en.x = this.x;
                    en.y = this.y;

                    GameMain.Instance.m_Layer_Enemy.addChild(en);
                }
            }
//*
            for(var i:int = 0; i < m_List.length; i++){
                en = m_List[i];

                if(en != null && en.m_Type == TYPE_FIRE){
                    var Rad:int;
                    var theta:Number;
                    if(i < 4){
                        if(i < 2){
                            Rad = 48;
                            theta = 2*Math.PI * (m_Timer/BOSS_CYCLE + i/2.0);
                        }else{
                            Rad = 80;
                            theta = 2*Math.PI * -(m_Timer/BOSS_CYCLE + i/2.0);
                        }

                        //Pos
                        en.x = this.x + Rad * Math.cos(theta);
                        en.y = this.y + Rad * Math.sin(theta);
                    }else{
/*
                        if(0 <= fire.m_Timer){//m_Timerを移動角度代わりに使用
                            const SPEED:Number = 40;
                            fire.x += SPEED * in_DeltaTime * Math.cos(fire.m_Timer);
                            fire.y += SPEED * in_DeltaTime * Math.sin(fire.m_Timer);
                        }
//*/
                    }
                }
            }
//*/
            break;
        case TYPE_FIRE:
            this.alpha += 1 * in_DeltaTime;
            if(1 < this.alpha){this.alpha = 1;}
//*
            if(0 <= m_Timer){//m_Timerを移動角度代わりに使用
                const SPEED:Number = 40;
                this.x += SPEED * in_DeltaTime * Math.cos(m_Timer);
                this.y += SPEED * in_DeltaTime * Math.sin(m_Timer);
            }
//*/
            break;
        }

        //Range
        {
            var IsRangeOut:Boolean = false;
            if(this.x < -32){IsRangeOut = true;}
            if(GameMain.VIEW_W + 32 < this.x){IsRangeOut = true;}
            if(this.y < -32){IsRangeOut = true;}
            if(GameMain.VIEW_H + 32 < this.y){IsRangeOut = true;}

            if(IsRangeOut){
                //Score
                if(m_Type != TYPE_HUMAN){
                    GameMain.Instance.AddScore(
                        this.x,
                        GameMain.VIEW_H,
                        -1
                    );
                }else{
                    GameMain.Instance.AddScore(
                        this.x,
                        GameMain.VIEW_H,
                        10
                    );
                }

                //Kill
                this.parent.removeChild(this);
                return;
            }
        }

        //Anim
        {
            Update_Graphic(in_DeltaTime);
        }
    }

    //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_Type][iter];
    }

    //Damage
    public function onDamage(in_Val:int):void{
        var en:Enemy;

        //すでに死んでたら何もしない
        if(m_HP <= 0){
            return;
        }

        m_HP -= in_Val;
        if(m_HP < 0){m_HP = 0;}

        if(m_Type == TYPE_OGRE){
            this.scaleX = this.scaleY = m_HP;
        }
        if(m_Type == TYPE_BOSS){
            this.scaleX = this.scaleY = Math.sqrt(m_HP);

            if(7 <= m_HP){
                en = new Enemy(TYPE_FIRE);

                en.m_Timer = -1;// ボス側で操作するため

                m_List.push(en);

                GameMain.Instance.m_Layer_Enemy.addChild(en);

                //ボスの方を炎より手前に表示する
                this.parent.swapChildren(this, en);
            }

            if(m_HP == 0){
                //火の玉も消す
                for(var i:int = 0; i < m_List.length; i++){
                    en = m_List[i];
                    en.m_HP = 0;
                }

                //スコア表示に移る
                ScoreWindowLoader.show(GameMain.Instance.m_Score);
            }
        }
    }
}





//bkzenさんのコードを利用
//@see http://wonderfl.net/c/cuY4
//@see http://wonderfl.net/c/kYyY
class ScoreWindowLoader
{
    private static var _top: DisplayObjectContainer;
    private static var _api: WonderflAPI;
    private static var _content: Object;
    //private static const URL: String = "wonderflScore.swf";
    private static const URL: String = "http://swf.wonderfl.net/swf/usercode/5/57/579a/579a46e1306b5770d429a3738349291f05fec4f3.swf";
    private static const TWEET: String = "Playing Touch&Kill [score: %SCORE%] #wonderfl";
    
    public static function init(top: DisplayObjectContainer, api: WonderflAPI): void 
    {
        _top = top, _api = api;
        var loader: Loader = new Loader();
        var comp: Function = function(e: Event): void
        {
            loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, comp);
            _content = loader.content;
//            handler();
        }
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, comp);
        loader.load(new URLRequest(URL), new LoaderContext(true));
    }
    
    /**
     * Wonderfl の Score API 用
     * ランキング表示から Tweet までをひとまとめにしたSWF素材を使う
     * @param    score            : 取得スコア
     * @param    closeHandler    : Window が閉じるイベントハンドら
     */
    public static function show( score: int): void
    {
        var window: DisplayObject = _content.makeScoreWindow(_api, score, "Touch & Kill", 1, TWEET);
//        var close: Function = function(e: Event): void
//        {
//            window.removeEventListener(Event.CLOSE, close);
//            closeHandler();
//        }
//        window.addEventListener(Event.CLOSE, close);
        _top.addChild(window);
    }
    
}