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

forked from: Wonderfl Tower Defense

TDが好きです。初心者なので牛歩で進みますが、o8queさんのTDコードをありがたくいじらせてもらいますッ

【現状】 敵メイキング 
o8queさんのおかげでいろいろ解決。大変、勉強になりました。んで、敵は一通り作り終えた感じ。後半の敵がほぼ初見殺しな出方をするが、テストなので。

【次回】 ステージセレクト挑戦
スキルとか足そうと思ったら、先に全体に手を加えたほうが良さそうなので、暫定のセレクト画面づくりに挑戦。なかなか難しそうだ。

※「ワード上でコードいじって、ワンダフルで実行してみる」を繰り返してます。チェックしてるときは頻繁に更新されるので、動かなくなったり画面が崩れたりします。ご容赦ください。
Get Adobe Flash player
by beginners_high 23 Oct 2010
  • Forked from o8que's Wonderfl Tower Defense
  • Diff: 1930
  • Related works: 11
  • Talk

    o8que at 10 Oct 2010 03:19
    「猛ダッシュ現象」は BornAbility クラスの EnemyBirth メソッドで、 一つの座標情報(TileBasedPoint)を生み出される敵全てで共有してしまったことが原因です。 そのためSplitの場合、1回の更新で同じ座標情報が4回分(生み出されたSplitChildの数だけ) 更新されてしまうため、4倍速で動いてしまっています。 解決方法は、座標情報のコピーを生成して敵に渡すだけでokです。 EnemyBirthメソッド内の new Enemy(center, ... の部分を、 new Enemy(TileBasedPoint.createFromWorldPos(center.x, center.y), ... に変更すれば、多分うまくいくのではないでしょうか?
    o8que at 10 Oct 2010 03:20
    int,Number,Boolean,String等のプリミティブ型と、それ以外のリファレンス型の違いは、 意識しないと何度もつまづいてしまう大事な所だったりするので覚えておくといいと思いますよ。 http://oshige.com/flash/as3note_cs4/2009/08/post-49.html
    beginners_high at 14 Oct 2010 16:37
    わーー まさかの回答ありがとうございます!!!!  独り言のつもりだったので、予想外のプレゼント。 中身をわざわざ見てくださったということですよね…たぶんコードが汚くて大変だったろうと想像します… 実を言うと、プリミティブという言葉すらまだよくわからないのですが、 勉強しますー

    Tags

    Embed
/**
 * Copyright beginners_high ( http://wonderfl.net/user/beginners_high )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/1sKW
 */

//forked from o8que's Wonderfl Tower Defense
//初ワンダフルで大好きなタワーディフェンスゲーム!をフォーク
//フォーク元とだいぶ内容が違ってきたので、o8que氏の説明書きを変更させてもらいました(2010.10.6)

/* ------------------------------------------------------
 * The Gate TD
 *  ~forked from o8que's [Wonderfl Tower Defense] ~
 * ------------------------------------------------------
 * [タワーの特徴]
 * Gun     : 安価で地対空両用。レベル5で最大級の射程。
 * Gatling : 連射が速く地対空両用。安定したダメージ源になる。
 * Cannon  : 範囲攻撃で高威力。空中に攻撃できない。
 * Venom   : 対地。毒の威力は移動速度に比例。毒状態の敵が死ぬと周囲に感染。
 * Voltex  : 射程内全体へスロウ効果。地対空両用で威力も高めだが高価。
 * AntiFly : 高威力の対空専用。現行は貫通弾。<修正予定>
 * Base    : 土台。タワーを置けない土地にはまず土台を。設置後は売却不能。
 * 
 * [敵の特徴]
 * << Feeble >>
 * Normal  : 特にこれといった特徴はない。
 * Swarm   : 体力はかなり低いザコだが、大量に出現する。
 * Fast    : 移動が速い。油断すると一気に攻め込まれるぞ。
 * Flying  : 飛行型。地形を無視するのでタワー配置に注意。
 * << Tough >>
 * Immune  : ノロマだが体力が高い。スロウと毒を無効化。
 * Zombie  : 常に傷を再生しながら侵攻してくる。火力で対抗せよ。
 * Fupa    : 破壊すると羽化して飛行タイプに変化。
 * Detour  : 飛行型。左右に迂回するので侵攻経路がやっかい。
 * << Scary >>
 * Shell   : 通称3段ロケット。体力が減ると脱皮し、毒やスロウを破棄する。
 * Split   : 破壊すると移動の速いザコ4体に分裂する。
 * Fade    : 透明化してタワーの攻撃から逃れる。透明中も範囲攻撃は当たる。
 * Decoyer : 飛行型。オトリ弾を発射し、攻撃を拡散させてくるぞ。
 * << Insane >>
 * Fury    : 砲撃や毒でダメージを受けるたびに加速。最大速度はヤバイ。
 * Wall    : 体力が特大。毒とスロウ無効、わずかに再生能力もある。
 * Ghost   : 透明化する飛行型。移動は遅めだが危険な敵。 
 * Random  : (未作成)
 * 
 *            
 * [スキル](予定)
 * 敵メイキングが落ち着いたら着手。
 * 時間でチャージされ発動可能になるスキルを12種から3つまで装備。
 * チャージをオフにするとほかのスキル回復が早まる。
 * 
 * [ゲート](予定)
 * スキルの仕組みの目処が立ったら着手。ずいぶん先になりそう。
 * ゲートに接触した敵は能力がUP、獲得できる得点とお金もUP。
 * 
 * ------------------------------------------------------
 * [HotKey]
 * 1-7   : select a tower to place
 * 7     : select a base to build
 * 0,ESC : cancel a selection
 * U     : upgrade the selected tower
 * S     : sell the selected tower
 * M     : show menu window
 * N     : send the next wave
 * ------------------------------------------------------
 * [今後の予定]
 * ・アップグレードタイム(1~2秒)の導入
 * ・スキル能力の準備と実装(勉強するがすごく大変そう)
 * ・ゲートシステムの準備と実装(たぶん簡単)
 * ・そのうちステージセレクトで5ステージつくりたい(勉強する)
 * ・最後にゴールを自分で配置する仕組み
 * ・バランス調整
 *
 *
 *
 *
 */

/* ---------------------------------------------------------------------------------------------------------
 * Main
 * ---------------------------------------------------------------------------------------------------------
 */
package {
    import com.bit101.components.PushButton;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.ui.Keyboard;
    import flash.utils.Dictionary;
    
    public class Main extends Sprite {
        // 各状態を表す定数
        public static const STATE_READY:int = 0;
        public static const STATE_PLAYING:int = 1;
        public static const STATE_MENU:int = 2;
        public static const STATE_GAMEOVER:int = 3;
        
        private var _states:Vector.<IState>;    // 状態のコレクション
        private var _currentState:IState;        // 現在の状態の参照
        private var _previousState:IState;        // 一つ前の状態の参照
        
        private var _world:World;                // フィールド・タワー・敵等を表示する画面
        private var _frontend:Frontend;            // ステータス・メニュー等を表示するウインドウ
        private var _waveManager:WaveManager;    // Waveを管理・表示するウインドウ
        private var _nextWaveButtonHandler:Function;
        
        public function get world():World { return _world; }
        public function get waveManager():WaveManager { return _waveManager; }
        
        public function Main() {
            graphics.beginFill(0x000000);
            graphics.drawRect(0, 0, 465, 465);
            graphics.endFill();
            
            // 外部アセットを読み込んだ後に初期化を開始する
            var imagePaths:Dictionary = ImageFactory.getExternalImagePaths();
            var imageHolder:Dictionary = ImageFactory.load();
            var preloader:Preloader = new Preloader(this, imagePaths, imageHolder);
            preloader.addEventListener(Event.COMPLETE, initialize);
        }
        
        // 全体の初期化
        private function initialize(e:Event):void {
            e.target.removeEventListener(Event.COMPLETE, initialize);
            HotKey.setStage(this.stage);
            EnemyType.initialize();
            BornAbility.initialize();
            AccelerateAbility.initialize();
            
            // 各状態の初期化
            _states = new Vector.<IState>();
            _states[Main.STATE_READY] = new ReadyState(this);
            _states[Main.STATE_PLAYING] = new PlayingState(this);
            _states[Main.STATE_MENU] = new MenuState(this);
            _states[Main.STATE_GAMEOVER] = new GameoverState(this);
            
            // 画面の初期化
            addChild(_world = new World( -9, 12));
            addChild(_frontend = new Frontend(0, 0));
            _frontend.addChild(_waveManager = new WaveManager(0, 415, _world));
            
            // 各ボタンの初期化と、対応するホットキーを設定する
            var window:Sprite = _frontend.addChild(ImageFactory.createWindow(365, 415, 100, 50)) as Sprite;
            var menuButton:PushButton = new PushButton(window, 5, 4, "Menu (M)", onClickMenuButton);
            var nextWaveButton:PushButton = new PushButton(window, 5, 26, "Next Wave (N)", onClickNextWaveButton);
            menuButton.width = nextWaveButton.width = 90;
            
            HotKey.bind(Keyboard.M, onClickMenuButton);
            HotKey.bind(Keyboard.N, onClickNextWaveButton);
            
            // 初期状態の設定
            _currentState = _states[Main.STATE_GAMEOVER];
            _currentState.enter();
            
            addEventListener(Event.ENTER_FRAME, mainLoop);
        }
        private function onClickMenuButton(e:MouseEvent = null):void { changeState(Main.STATE_MENU); }
        private function onClickNextWaveButton(e:MouseEvent = null):void { _nextWaveButtonHandler(); }
        private function mainLoop(e:Event):void { _currentState.update(); }
        
        // NextWaveボタンを押した時の処理を設定する
        public function setNextWaveButtonHandler(handler:Function = null):void {
            _nextWaveButtonHandler = (handler != null) ? handler : doNothing;
        }
        private function doNothing():void { }
        
        // ゲームの状態を変更する
        public function changeState(stateType:int):void {
            _previousState = _currentState;
            
            _currentState.exit();
            _currentState = _states[stateType];
            _currentState.enter();
        }
        
        // ゲームの状態を一つ前の状態に戻す
        public function revertToPreviousState():void {
            _currentState.exit();
            _currentState = _previousState;
            _currentState.enter();
        }
    }
}
/* ----------------------------------------------------------------------------------------------------------------------
 * IState
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    //public 
    interface IState {
        function enter():void;
        function update():void;
        function exit():void;
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * GameoverState
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import com.bit101.components.PushButton;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import net.wonderfl.score.basic.BasicScoreForm;
    import net.wonderfl.score.basic.BasicScoreRecordViewer;
    
    //public 
    class GameoverState implements IState {
        private var _main:Main;
        private var _gameoverScreen:Sprite;
        private var _instructionWindow:Sprite;
        private var _isBeginning:Boolean;
        
        private var _scoreForm:BasicScoreForm;
        private var _ranking:BasicScoreRecordViewer;
        
        public function GameoverState(main:Main) {
            _main = main;
            _gameoverScreen = createGameoverScreen();
            _instructionWindow = createInstructionWindow();
            _isBeginning = true;
        }
        
        private function createGameoverScreen():Sprite {
            var screen:Sprite = new Sprite();
            screen.graphics.beginFill(0x000000, 0.5);
            screen.graphics.drawRect(0, 0, 465, 465);
            screen.graphics.endFill();
            new PushButton(screen, 182, 182, "Start Game", onClickStartButton);
            return screen;
        }
        private function onClickStartButton(e:MouseEvent):void { _main.changeState(Main.STATE_READY); }
        
        private function createInstructionWindow():Sprite {
            var container:Sprite = new Sprite();
            
            var window1:Sprite = container.addChild(ImageFactory.createWindow(180, 60, 190, 70)) as Sprite;
            window1.addChild(ImageFactory.createInstructionText(5, 7, 190, 24, "Select a tower to build\nby clicking right button.", 12));
            window1.addChild(ImageFactory.createInstructionText(5, 39, 190, 24, "設置したいタワーを、\n右のボタンから選択できます。", 12));
            
            var window2:Sprite = container.addChild(ImageFactory.createWindow(30, 220, 190, 70)) as Sprite;
            window2.addChild(ImageFactory.createInstructionText(5, 7, 190, 24, "Click on the map\nto build the selected tower.", 12));
            window2.addChild(ImageFactory.createInstructionText(5, 39, 190, 24, "マップをクリックすると、\n選択したタワーを設置できます。", 12));
            
            var window3:Sprite = container.addChild(ImageFactory.createWindow(240, 270, 190, 70)) as Sprite;
            window3.addChild(ImageFactory.createInstructionText(5, 7, 190, 24, "Click on a tower on the map\nto upgrade or sell it.", 12));
            window3.addChild(ImageFactory.createInstructionText(5, 39, 190, 24, "マップ上のタワーをクリックすると、\nレベルアップや売却を行えます。", 12));
            
            var window4:Sprite = container.addChild(ImageFactory.createWindow(170, 380, 190, 70)) as Sprite;
            window4.addChild(ImageFactory.createInstructionText(5, 7, 190, 24, "Press \"Next Wave\" button\nto send the next wave.", 12));
            window4.addChild(ImageFactory.createInstructionText(5, 39, 190, 24, "「Next Wave」ボタンを押すと、\nゲームを進めることができます。", 12));
            
            return container;
        }
        
        
        public function enter():void {
            _main.addChild(_gameoverScreen);
            
            if (_isBeginning) {
                _main.addChild(_instructionWindow);
            }else {
                if (_scoreForm != null) { _gameoverScreen.removeChild(_scoreForm); }
                _scoreForm = new BasicScoreForm(_gameoverScreen, 92, 10, GameData.instance.score, "Score", showRanking);
                showRanking(false);
            }
        }
        private function showRanking(b:Boolean):void {
            if (_ranking != null) { _gameoverScreen.removeChild(_ranking); }
            _ranking = new BasicScoreRecordViewer(_gameoverScreen, 122, 215, "Ranking", 99, true, null);
        }
        
        public function update():void { }
        
        public function exit():void {
            if (_isBeginning) {
                _main.removeChild(_instructionWindow);
                _instructionWindow = null;
            }
            _isBeginning = false;
            _main.removeChild(_gameoverScreen);
            
            _main.world.clear();
            _main.waveManager.initialize();
            GameData.instance.initialize();
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * ReadyState
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    //public 
    class ReadyState implements IState {
        private var _main:Main;
        
        public function ReadyState(main:Main) {
            _main = main;
        }
        
        public function enter():void {
            _main.setNextWaveButtonHandler(startPlaying);
            HotKey.enable();
        }
        private function startPlaying():void { _main.changeState(Main.STATE_PLAYING); }
        
        public function update():void {
            _main.world.update();
        }
        
        public function exit():void {
            HotKey.disable();
            _main.setNextWaveButtonHandler(_main.waveManager.sendNextWave);
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * PlayingState
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    //public 
    class PlayingState implements IState {
        private var _main:Main;
        
        public function PlayingState(main:Main) {
            _main = main;
        }
        
        public function enter():void {
            GameData.instance.sellingRatio = 0.8;
            HotKey.enable();
        }
        
        public function update():void {
            _main.world.update();
            _main.waveManager.update();
            
            // ライフが0になるか、全ての敵を倒したら、ゲームオーバー
            if ((GameData.instance.lives <= 0) || (_main.world.numEnemies() == 0 && _main.waveManager.finished())) {
                _main.changeState(Main.STATE_GAMEOVER);
            }
        }
        
        public function exit():void {
            HotKey.disable();
            GameData.instance.sellingRatio = 1;
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * MenuState
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import com.bit101.components.PushButton;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    
    //public 
    class MenuState implements IState {
        private var _main:Main;
        private var _menuScreen:Sprite;
        
        public function MenuState(main:Main) {
            _main = main;
            _menuScreen = createMenuScreen();
        }
        
        private function createMenuScreen():Sprite {
            var screen:Sprite = new Sprite();
            screen.graphics.beginFill(0x000000, 0.5);
            screen.graphics.drawRect(0, 0, 465, 465);
            screen.graphics.endFill();
            
            var window:Sprite = screen.addChild(ImageFactory.createWindow(122, 172, 120, 95)) as Sprite;
            window.addChild(ImageFactory.createWindow(0, 0, 120, 25));
            window.addChild(ImageFactory.createSimpleText(0, 0, 120, 25, "Menu", 12, 0xffffff));
            new PushButton(window, 10, 35, "Resume", onClickResumeButton);
            new PushButton(window, 10, 65, "Give up", onClickGiveUpButton);
            return screen;
        }
        private function onClickResumeButton(e:MouseEvent):void { _main.revertToPreviousState(); }
        private function onClickGiveUpButton(e:MouseEvent):void { _main.changeState(Main.STATE_GAMEOVER); }
        
        public function enter():void { _main.addChild(_menuScreen); }
        
        public function update():void { }
        
        public function exit():void { _main.removeChild(_menuScreen); }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * World
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    
    //public 
    class World extends Sprite {
        private var _nodes:Vector.<Vector.<Node>>;
        private var _starts:Vector.<Start>;
        private var _goals:Vector.<Goal>;
        
        private var _towers:Vector.<Tower>;
        private var _bullets:Vector.<Bullet>;
        private var _groundEnemies:Vector.<Enemy>;
        private var _flyingEnemies:Vector.<Enemy>;
        
        private var _towerLayer:Sprite;
        private var _enemyLayer:Sprite;
        private var _bulletLayer:Sprite;
        private var _effectLayer:Sprite;
        private var _cursor:Cursor;
        
        public function getNode(col:int, row:int):Node { return _nodes[row][col]; }

        public function getStartingPos(startIndex:int):TileBasedPoint {
            return _starts[startIndex].getRandomSpawningPosition();
        }

        public function numEnemies():int { return _groundEnemies.length + _flyingEnemies.length; }

        //----------------------------------------------------------------------        
        //ワールド画面の設置 (画面の開始位置は受け取る) 【F】
        public function World(posx:int, posy:int) {
            x = posx;
            y = posy;
            
            //初期化用パブリックファンクション【F】
            initializeNodes();
            initializeStarts();
            initializeGoals();
            
            _towers = new Vector.<Tower>();
            _bullets = new Vector.<Bullet>();
            _groundEnemies = new Vector.<Enemy>();
            _flyingEnemies = new Vector.<Enemy>();
            
            addChild(new Bitmap(ImageFactory.getImage("World")));
            addChild(_towerLayer = new Sprite());
            addChild(_enemyLayer = new Sprite());
            addChild(_bulletLayer = new Sprite());
            addChild(_effectLayer = new Sprite());
            addChild(_cursor = new Cursor(this));
            _enemyLayer.mouseChildren = _bulletLayer.mouseChildren = false;
            _enemyLayer.mouseEnabled = _bulletLayer.mouseEnabled = false;
            
            //画面上をクリックされたら、基本はタワー配置操作とし、いろいろチェックして対応【F】
            addEventListener(MouseEvent.CLICK, addTower);
        }
        
        private function initializeNodes():void {
            _nodes = new Vector.<Vector.<Node>>();
            for (var row:int = 0; row < Const.NODE_ROWS; row++) {
                _nodes[row] = new Vector.<Node>();
                for (var col:int = 0; col < Const.NODE_COLS; col++) {
                    _nodes[row][col] = new Node(col, row, Config.NODE_TYPE[row][col]);
                }
            }
        }
        
        private function initializeStarts():void {
            _starts = Config.getStarts();
        }
        
        private function initializeGoals():void {
            _goals = Config.getGoals();
            for (var i:int = 0; i < _goals.length; i++) {
                var goal:Goal = _goals[i];
                goal.setNode(_nodes[goal.tileY][goal.tileX]);
                goal.search(this);
            }
        }


    //----------------------------------------------------------------------
    //World.update の設定【F】

        public function update():void {
            var i:int;
            //まず存在している各タワーのupdate (タワークラスのPbFc)【F】
            for (i = 0; i < _towers.length; i++) {
                _towers[i].update();
            }
            //(敵数になるまで)i番目の敵のupdate(エネミークラスのPbFc)【F】
            for (i = 0; i < _groundEnemies.length; i++) {
                var groundEnemy:Enemy = _groundEnemies[i];
                _nodes[groundEnemy.tileY][groundEnemy.tileX].numEnemy--;
                _groundEnemies[i].update(this);
                _nodes[groundEnemy.tileY][groundEnemy.tileX].numEnemy++;
            }
            
            for (i = 0; i < _flyingEnemies.length; i++) {
                _flyingEnemies[i].update(this);
            }
            
            //弾丸の数だけupdate(bulletクラスのPbFc)【F】
            for (i = 0; i < _bullets.length; i++) {
                _bullets[i].update();
            }
            //カーソルもupdate【F】
            _cursor.update(mouseX - Const.CURSOR_OFFSET, mouseY - Const.CURSOR_OFFSET);
        }
        
        
        // すべてのタワー・弾・敵を消去する
        public function clear():void {
            var i:int;
            for (i = _towers.length - 1; i >= 0; i--) { 
                removeTower(_towers[i], true); }
            for (i = 0; i < _goals.length; i++) { _goals[i].search(this); }
            for (i = _groundEnemies.length - 1; i >= 0; i--) { removeEnemy(_groundEnemies[i]); }
            for (i = _flyingEnemies.length - 1; i >= 0; i--) { removeEnemy(_flyingEnemies[i]); }
            for (i = _bullets.length - 1; i >= 0; i--) { removeBullet(_bullets[i]); }
            initializeNodes();
            initializeStarts();
            initializeGoals();
        }
        
        //----------------------------------------------------
        // マウスイベント:タワーを(設置できるなら)設置する【F】
        
        public function addTower(e:MouseEvent):void {
            var position:TileBasedPoint = TileBasedPoint.createFromWorldPos(mouseX - Const.CURSOR_OFFSET, mouseY - Const.CURSOR_OFFSET);
            position.setTilePos(position.tileX, position.tileY);
            //クリックイベントでタイルポジションを取得しておく【F】

                var nearestGoal:Goal;
                var blocking:Boolean = false;
                var tower:Tower = new Tower(position.x, position.y, GameData.instance.selectedTower.type, this);
                var type:TowerType = tower.type;
        
            //お金やタイル状態的にタワー設置可能をを調べる(キャンビルド)をまず実行【F】
            if (canBuildTower(position.tileX, position.tileY)) {
                // 以下キャンビルドOK時の処理【F】
                var i:int, j:int;                 
                // タワーが設置される場所をタワー建設不能にする【F】
                if (!type.towerbase){
                for (var row:int = 0; row < 2; row++) {
                    for (var col:int = 0; col < 2; col++) {
                        var node:Node = _nodes[position.tileY + row][position.tileX + col];
                        node.placeable = false} ;
                    }
                }
                // ベースが設置される場所を通行不能&ベース建設不能&タワー建設可能にする【F】
                // 以下の経路探査操作はベース設置時のみ【F】
                if (type.towerbase){
                for(row = 0; row < 2; row++) {
                   for (col = 0; col < 2; col++) {
                        node = _nodes[position.tileY + row][position.tileX + col];
                        node.passable = node.buildable = false;
                        node.placeable =true } ;
                }                      
                // 全ての経路の最探索
                for (i = 0; i < _goals.length; i++) {
                    _goals[i].search(this);
                }                
                // 全てのスタート、全ての敵(地上)、のゴールを更新
                // ブロッキングが発生していたら中断
                for (i = 0; !blocking && (i < _starts.length); i++) {
                    var start:Start = _starts[i];
                    if (start.forFlying) { continue; }
                    nearestGoal = getNearestGoalFrom(start.posX, start.posY, false);
                    if (!nearestGoal.hasPath(start.tileX,start.tileY)) { blocking = true; }
                }
                for (i = 0; !blocking && (i < _groundEnemies.length); i++) {
                    var enemy:Enemy = _groundEnemies[i];
                    nearestGoal = getNearestGoalFrom(enemy.posX, enemy.posY, false);
                    enemy.setGoal(nearestGoal);
                    if (!enemy.hasPathToGoal()) { blocking = true; }
                }             
                }   // ベース設置時のみここまで【F】
                
                // ブロッキングが発生していたら、
                // 全ての変更を元に戻してタワー設置失敗で終了
                // そうでなければ、実際にタワーを設置する
                // ベースじゃない通常タワーはblocking=常にfalseで通過【F】
                if (blocking) {
                    _cursor.blockingAlart();                    
                    // 通行不能にした場所を元に戻す
                    for (row = 0; row < 2; row++) {
                        for (col = 0; col < 2; col++) {
                            node = _nodes[position.tileY + row][position.tileX + col];

                            node.passable = node.buildable = true;
                            node.placeable = false;
                        }
                    }
                    // 全ての経路を元に戻す
                    for (i = 0; i < _goals.length; i++) {
                        _goals[i].revertToPrevious();
                    }
                    // 全ての敵(地上)のゴールを更新
                    for (i = 0; i < _groundEnemies.length; i++) {
                        _groundEnemies[i].setGoal(getNearestGoalFrom(_groundEnemies[i].posX, _groundEnemies[i].posY, false));
                    }
                }else {
                    _towers.push(tower);
                    _towerLayer.addChild(tower);
                    //ベースはワールド設置時にクリック透過。選択&売却不能。
                    if (type.towerbase){ tower.mouseEnabled = false }
                    GameData.instance.gold -= tower.type.getStatus(tower.level).cost;
                }
            }
        }
                    
        // そもそも建築できる場所なのかファンクション 【F】
        public function canBuildTower(tilex:int, tiley:int):Boolean {
            var selectedTower:Tower = GameData.instance.selectedTower;
            var _type:TowerType = selectedTower.type;
            
            // タワー選択ボタンを選択中か、十分な所持金があるか調べる
            if (selectedTower == null || selectedTower.active || (GameData.instance.gold < selectedTower.type.getStatus(selectedTower.level).cost)) { return false; } 
            // 引数で指定した場所にタワーが建てられるか調べる
            for (var row:int = 0; row < 2; row++) {
                for (var col:int = 0; col < 2; col++) {
                    var node:Node = _nodes[tiley + row][tilex + col];                       
                    if (_type.towerbase){            
                        if (!node.buildable || (node.numEnemy > 0)) { return false; }
                    }else{
                        if (!node.placeable ) { return false; }                   
                    }
                }
            }            
            return true;
        }


        //----------------------------------------------------
        // タワーのターゲットを探してそれを返す(いなければnullを返す)
        public function findTarget(posx:Number, posy:Number, range:int, ground:Boolean, air:Boolean):Enemy {
            var i:int, enemy:Enemy, diffX:Number, diffY:Number;
            var rangeSq:int = range * range;
            
            // 地上に攻撃できるなら、地上の敵のターゲットを探す
            if (ground) {
                for (i = 0; i < _groundEnemies.length; i++) {
                    enemy = _groundEnemies[i];
                    diffX = posx - enemy.posX;
                    diffY = posy - enemy.posY;
                    if (diffX * diffX + diffY * diffY < rangeSq) {
                        if (enemy.targetable) { return enemy }
                    }
                }
            }
            
            // 空中に攻撃できるなら、飛んでいる敵のターゲットを探す
            if (air) {
                for (i = 0; i < _flyingEnemies.length; i++) {
                    enemy = _flyingEnemies[i];
                    diffX = posx - enemy.posX;
                    diffY = posy - enemy.posY;
                    if (diffX * diffX + diffY * diffY < rangeSq) {
                        if (enemy.targetable) { return enemy }                    }
                }
            }
            
            // ターゲットが見つからなければnull
            return null;
        }
        

        //----------------------------------------------------
        // 引数で指定した位置から最も近いゴールを返す
        private function getNearestGoalFrom(posx:Number, posy:Number, flying:Boolean):Goal {
            var nearest:Goal = _goals[0];
            for (var i:int = 1; i < _goals.length; i++) {
                if (_goals[i].getCost(posx, posy, flying) < nearest.getCost(posx, posy, flying)) {
                    nearest = _goals[i];
                }
            }
            return nearest;
        }
        
        //----------------------------------------------------
        // タワーを消去する 
        //引数補足「clear=true:画面初期化」「clear=false(void):売却」
        public function removeTower(tower:Tower, clear:Boolean = false):void {
            var position:TileBasedPoint = TileBasedPoint.createFromWorldPos(tower.x, tower.y);
            for (var row:int = 0; row < 2; row++) {
                for (var col:int = 0; col < 2; col++) {
                    var node:Node = _nodes[position.tileY + row][position.tileX + col];
                    //元々が通路型の土地だったら …clearなら土台も消え通行可能TTF、売却なら土台が残っていて通行不可能FFT
                    if(Config.NODE_TYPE[position.tileY + row][position.tileX + col] == 0) {
                       node.passable = node.buildable = clear ; node.placeable = (!clear);
                    }
                    //元々が壁型の土地だったら 
                    if(Config.NODE_TYPE[position.tileY + row][position.tileX + col] == 1) {
                       node.passable = false; node.buildable = clear ; node.placeable = true;
                    }
                }
            }
            
            // ブロッキングを考慮せずに
            // 全ての経路の最探索と、全ての敵(地上)のゴールを更新
            // clear()時は最探索する必要
            if (!clear) {
                var i:int;
                for (i = 0; i < _goals.length; i++) {
                    _goals[i].search(this);
                }
                for (i = 0; i < _groundEnemies.length; i++) {
                    _groundEnemies[i].setGoal(getNearestGoalFrom(_groundEnemies[i].posX, _groundEnemies[i].posY, false));
                }
            }
            
            _towerLayer.removeChild(tower);
            _towers.splice(_towers.indexOf(tower), 1);
        }
        
        //----------------------------------------------------
        // 弾を出現させる
        public function addBullet(bullet:Bullet):void {
            _bullets.push(bullet);
            _bulletLayer.addChild(bullet);
        }
        
        // 弾を消去する
        public function removeBullet(bullet:Bullet):void {
            _bulletLayer.removeChild(bullet);
            _bullets.splice(_bullets.indexOf(bullet), 1);
        }
        
        //----------------------------------------------------
        // 敵を出現させる
        public function addEnemy(enemy:Enemy):void {
            enemy.setGoal(getNearestGoalFrom(enemy.posX, enemy.posY, enemy.type.flying));
            
            if (enemy.type.flying) {
                _flyingEnemies.push(enemy);
            }else {
                _groundEnemies.push(enemy);
                _nodes[enemy.tileY][enemy.tileX].numEnemy++;
            }
            _enemyLayer.addChild(enemy);
        }
        
        // 敵を消去する
        public function removeEnemy(enemy:Enemy):void {
            _enemyLayer.removeChild(enemy);
            if (enemy.type.flying) {
                _flyingEnemies.splice(_flyingEnemies.indexOf(enemy), 1);
            }else {
                _nodes[enemy.tileY][enemy.tileX].numEnemy--;
                _groundEnemies.splice(_groundEnemies.indexOf(enemy), 1);
            }
        }
        
        // エフェクトを発生させる
        public function addEffect(effect:Sprite):void {
            _effectLayer.addChild(effect);
        }
        // 範囲攻撃
        public function damageSurroundingEnemies(bullet:Bullet):void {
            var i:int, enemy:Enemy;
            if (bullet.ground) {
                for (i = _groundEnemies.length - 1; i >= 0; i--) {
                    enemy = _groundEnemies[i];
                    if (bullet.isHitTarget(enemy, bullet.splashRadius)) { bullet.damageTarget(enemy); }
                }
            }
            if (bullet.air) {
                for (i = _flyingEnemies.length - 1; i >= 0; i--) {
                    enemy = _flyingEnemies[i];
                    if (bullet.isHitTarget(enemy, bullet.splashRadius)) { bullet.damageTarget(enemy); }
                }
            }
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * Node
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    //public 
    class Node {
        private var _center:TileBasedPoint;    // 中心の座標
        private var _passable:Boolean;        // 敵が通れるかどうか
        private var _buildable:Boolean;        // 足場を建てられるかどうか【F】
        private var _placeable:Boolean;        // タワーを建てられるかどうか【F】
        private var _numEnemy:int;            // このノード上にいる敵の数
        
        public function get tileX():int { return _center.tileX; }
        public function get tileY():int { return _center.tileY; }
        public function get centerX():Number { return _center.x; }
        public function get centerY():Number { return _center.y; }
        public function get passable():Boolean { return _passable; }
        public function get buildable():Boolean { return _buildable; }
        public function get placeable():Boolean { return _placeable; }   //追加【F】
        public function get numEnemy():int { return _numEnemy; }
        
        public function set passable(value:Boolean):void { _passable = value; }
        public function set buildable(value:Boolean):void { _buildable = value; }
        public function set placeable(value:Boolean):void { _placeable = value; }  //追加【F】
        public function set numEnemy(value:int):void { _numEnemy = value; }
        
        public function Node(tilex:int, tiley:int, type:int) {
            _center = TileBasedPoint.createFromTilePos(tilex, tiley);
            _center.x += Const.NODE_SIZE / 2;
            _center.y += Const.NODE_SIZE / 2;
            
            switch(type) {    // 追加【F】
                case 0: { _passable = true; _buildable = true; _placeable =false; break; }  // 通路となる土地。土台を置けるが、タワーを置けない【F】
                case 1: { _passable = false; _buildable = false; _placeable =true; break; }  // 土台と同等の土地。通過できないがタワーを置ける【F】
                case 2: { _passable = true; _buildable = false; _placeable = false; break; }  // 敵の出入り口。通過できるが、何も置けない【F】
                case 3: { _passable = false; _buildable = false; _placeable = false; break; }  //  ゲーム中、何も置けない土地【F】
            }
            _numEnemy = 0;
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * Start
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    //public 
    class Start {
        private var _position:TileBasedPoint;
        private var _width:int;
        private var _forFlying:Boolean;
        
        public function get posX():Number { return _position.x; }
        public function get posY():Number { return _position.y; }
        public function get tileX():int { return _position.tileX; }
        public function get tileY():int { return _position.tileY; }
        public function get forFlying():Boolean { return _forFlying; }
        
        public function Start(tilex:int, tiley:int, width:int, forFlying:Boolean) {
            _position = TileBasedPoint.createFromTilePos(tilex, tiley);
            _width = width * Const.NODE_SIZE;
            _forFlying = forFlying;
        }
        
        // ランダムな出現位置を取得する
        public function getRandomSpawningPosition():TileBasedPoint {
            var posx:int = int(_position.x + ((2 * _width * Math.random()) - _width));
            var posy:int = int(_position.y + Const.NODE_SIZE);
            return TileBasedPoint.createFromWorldPos(posx, posy);
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * Goal
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    //public 
    class Goal {
        private static const DX:Array = [0, -1, 1, 0, -1, 1, -1, 1];
        private static const DY:Array = [ -1, 0, 0, 1, -1, -1, 1, 1];
        private static const DCOST:Array = [1, 1, 1, 1, Math.SQRT2, Math.SQRT2, Math.SQRT2, Math.SQRT2];
        
        private var _center:TileBasedPoint;
        private var _node:Node;
        private var _openNodes:Vector.<Node>;            // 保留ノードリスト
        private var _nodeCost:Vector.<Vector.<Number>>;    // 各ノードの移動コスト
        private var _nodeNext:Vector.<Vector.<Node>>;    // 各ノードの次の経路となるノード
        
        private var _previousNodeCost:Vector.<Vector.<Number>>;    // 以前のnodeCost
        private var _previousNodeNext:Vector.<Vector.<Node>>;    // 以前のnodeNext
        
        public function get tileX():int { return _center.tileX; }
        public function get tileY():int { return _center.tileY; }
        
        public function Goal(tilex:int, tiley:int) {
            _center = TileBasedPoint.createFromTilePos(tilex, tiley);
            _center.setWorldPos(_center.x + Const.NODE_SIZE / 2, _center.y + Const.NODE_SIZE / 2);
            _openNodes = new Vector.<Node>();
            _nodeCost = null; _nodeNext = null;
        }
        public function setNode(node:Node):void { _node = node; }
        
        // 引数で指定した位置から、ゴールまでのコストを返す
        public function getCost(posx:Number, posy:Number, flying:Boolean):Number {
            if (flying) {
                var diffx:Number = _center.x - posx;
                var diffy:Number = _center.y - posy;
                return diffx * diffx + diffy * diffy;
            }
            
            var postion:TileBasedPoint = TileBasedPoint.createFromWorldPos(posx, posy);
            return _nodeCost[postion.tileY][postion.tileX];
        }
        
        // 引数で指定した位置から、ゴールへ向かう経路が存在しているかどうか
        public function hasPath(tilex:int, tiley:int):Boolean {
            return _nodeCost[tiley][tilex] != Number.MAX_VALUE;
        }
        
        // 引数で指定した位置から、ゴールへ向かう為の次のノードを返す
        public function getNext(posx:Number, posy:Number, flying:Boolean):Node {
            if (flying) {
                return _node;
            }
            
            var position:TileBasedPoint = TileBasedPoint.createFromWorldPos(posx, posy);
            return _nodeNext[position.tileY][position.tileX];
        }
        
        // Dijkstra法による経路探索
        public function search(world:World):void {
            setup(world);
            
            while (_openNodes.length > 0) {
                var subject:Node = _openNodes.pop() as Node;
                
                // 周囲8方向のノードを訪問する
                for (var i:int = 0; i < 8; i++) {
                    // 画面外の存在しないノードを指すなら次の周囲ノードへ進む
                    if (!isValid(subject.tileX + Goal.DX[i], subject.tileY + Goal.DY[i])) { continue; }
                    // 通れないノード、計算済み(確定)ノード、直進することができないノードなら次の周囲ノードへ進む
                    var test:Node = world.getNode(subject.tileX + Goal.DX[i], subject.tileY + Goal.DY[i]);
                    if (!test.passable || isCalculatedNode(test) || !canGoStraightTo(subject, test, world)) { continue; }
                    
                    // 移動コストを計算する
                    _nodeCost[test.tileY][test.tileX] = _nodeCost[subject.tileY][subject.tileX] + Goal.DCOST[i];
                    // 次の経路ノードをsubjectノードに設定する
                    _nodeNext[test.tileY][test.tileX] = subject;
                    // 保留ノードリストに追加する
                    insertToOpenNodes(test);
                }
            }
        }
        
        // 探索前の準備
        private function setup(world:World):void {
            _previousNodeCost = _nodeCost;
            _previousNodeNext = _nodeNext;
            
            _nodeCost = new Vector.<Vector.<Number>>();
            _nodeNext = new Vector.<Vector.<Node>>();
            for (var row:int = 0; row < Const.NODE_ROWS; row++) {
                _nodeCost[row] = new Vector.<Number>();
                _nodeNext[row] = new Vector.<Node>();
                for (var col:int = 0; col < Const.NODE_COLS; col++) {
                    _nodeCost[row][col] = Number.MAX_VALUE;
                    _nodeNext[row][col] = world.getNode(col, row);
                }
            }
            
            // Goalのノードを経路探索のスタートノードとする
            _nodeCost[_center.tileY][_center.tileX] = 0;
            _openNodes.push(_node);
        }
        
        // indexの値が有効な値かどうか
        private function isValid(col:int, row:int):Boolean {
            return (col >= 0) && (col < Const.NODE_COLS) && (row >= 0) && (row < Const.NODE_ROWS);
        }
        
        // 既にコストを計算済みのノードかどうか
        private function isCalculatedNode(node:Node):Boolean {
            return _nodeCost[node.tileY][node.tileX] != Number.MAX_VALUE;
        }
        
        // subjectノードからtestノードへ直進できるかどうか
        private function canGoStraightTo(subject:Node, test:Node, world:World):Boolean {
            return world.getNode(subject.tileX, test.tileY).passable && world.getNode(test.tileX, subject.tileY).passable;
        }
        
        // nodeを保留ノードリストの適切な場所に挿入する
        private function insertToOpenNodes(node:Node):void {
            var insertIndex:int;
            var nodeCost:Number = _nodeCost[node.tileY][node.tileX];
            
            for (insertIndex = 0; insertIndex < _openNodes.length; insertIndex++) {
                var openNode:Node = _openNodes[insertIndex];
                if (nodeCost > _nodeCost[openNode.tileY][openNode.tileX]) { break; }
            }
            _openNodes.splice(insertIndex, 0, node);
        }
        
        // 最探索更新前の経路情報に戻す
        public function revertToPrevious():void {
            _nodeCost = _previousNodeCost;
            _nodeNext = _previousNodeNext;
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * Tower
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    
    //public 
    class Tower extends Sprite {
        private var _center:TileBasedPoint;
        private var _type:TowerType;        // 種類
        private var _level:int;                // 現在のレベル
        private var _world:World;
        private var _target:Enemy;            // 現在のターゲット
        private var _reloadCount:Number;    // 100を超えたら弾発射
        
        private var _body:Sprite;
        private var _levelText:TextField;
        
        public function get tileX():int { return _center.tileX; }
        public function get tileY():int { return _center.tileY; }
        public function get type():TowerType { return _type; }
        public function get level():int { return _level; }
        public function get active():Boolean { return _world != null; }
        
        //----------------------------------------------------
        public function Tower(posx:int, posy:int, type:TowerType, world:World = null) {
            x = posx;
            y = posy;
            
            _center = TileBasedPoint.createFromWorldPos(posx + Const.TOWER_SIZE / 2, posy + Const.TOWER_SIZE / 2);
            _type = type;
            _level = 1;
            _world = world;
            _target = null;
            _reloadCount = 0;
            
            draw();
            
            buttonMode = true;
            mouseChildren = false;
            
           addEventListener(MouseEvent.CLICK, clickTower, false, 0, true);         
        }

        //----------------------------------------------------
        // タワーの画像を描画する
        private function draw():void {
            addChild(new Bitmap(ImageFactory.getImage("Circle")));
            _body = addChild(new Sprite()) as Sprite;
            var bitmap:Bitmap = _body.addChild(new Bitmap(ImageFactory.getImage(_type.name), "auto", true)) as Bitmap;
            bitmap.x = bitmap.y = int( -Const.TOWER_SIZE / 2);
            _body.x = _body.y = int(Const.TOWER_SIZE / 2);
            
            if (active) {
                if ( !_type.towerbase ) { _body.rotation = 360 * Math.random() - 180};
                if ( !_type.towerbase ) { addChild(_levelText = ImageFactory.createBorderedText(Const.TOWER_SIZE - 10, Const.TOWER_SIZE - 10, 10, 10, _level.toString(), 10, 0xffffff, 0x000000))};
               }
        }
           
        // タワーをクリックしたとき
        public function clickTower(e:MouseEvent = null):void {
            GameData.instance.selectedTower = this;            
        }
      
        //----------------------------------------------------
        public function update():void {
            var range:int = _type.getStatus(_level).range;
            // ターゲット無しorターゲットがやられていたorターゲットが消えたなら、新しいターゲットを探す
            if (_target == null || _target.isDead() || (!_target.targetable) ) {
                _target = _world.findTarget(_center.x, _center.y, range, _type.ground, _type.air);
            }
            
            // リロードカウントを進める
            if (_reloadCount < 100) { _reloadCount += _type.getStatus(_level).reloadSpeed; }
            
            if (_target != null) {
                var rangeSq:int = range * range;
                var diffX:Number = _target.posX - _center.x;
                var diffY:Number = _target.posY - _center.y;
                if (diffX * diffX + diffY * diffY < rangeSq) {
                    _body.rotation = _type.adjustBodyRotation(diffX, diffY, _body.rotation);
                    // リロードを終えていて、ターゲットがいるなら弾を発射する
                    if (_reloadCount >= 100 && _target != null) {
                        _reloadCount = 0;
                        _world.addBullet(type.createBullet(_center.x, _center.y, _level, _target, _world));
                    }
                }else {
                    // ターゲットが射程外になっていたらターゲットから外す
                    _target = null;
                }
            }
        }
        
        public function upgrade():void {
            // 既に最高レベルになっていたら終了
            if (!_type.hasStatus(_level + 1)) { return; }
            
            // アップグレードするだけの所持金があれば、アップグレード
            var upgradeCost:int = _type.getStatus(_level + 1).cost - _type.getStatus(_level).cost;
            if (upgradeCost <= GameData.instance.gold) {
                _level++;
                _levelText.text = _level.toString();
                GameData.instance.gold -= upgradeCost;
                GameData.instance.selectedTower = this;
            }
        }
        
        public function sell():void {
            _world.removeTower(this);
            GameData.instance.gold += _type.getStatus(_level).cost * GameData.instance.sellingRatio;
            GameData.instance.selectedTower = null;
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * TowerType
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.BitmapData;
    
    //public 
    class TowerType {
        private var _name:String;                    // 種類名
        private var _towerbase:Boolean;              //足場(タワーベース)型か【F】
        private var _ground:Boolean;                // 対地攻撃可能か
        private var _air:Boolean;                    // 対空攻撃可能か
        private var _slow:int;                    // スロー効果量
        private var _venom:int;                    //毒攻撃力
        private var _splash:int;                // 範囲攻撃サイズ
        private var _status:Vector.<TowerStatus>;    // (レベルごとの)各ステータス
        
        public function get name():String { return _name; }
        public function get ground():Boolean { return _ground; }
        public function get towerbase():Boolean { return _towerbase; }
        public function get air():Boolean { return _air; }
        public function get slow():int { return _slow; }
        public function get venom():int { return _venom; }
        public function get splash():int { return _splash; }
        public function getStatus(level:int):TowerStatus { return _status[level - 1]; }
        
        // ※インスタンスは Config.getTowerType() から生成する
        public function TowerType(name:String, towerbase:Boolean ,ground:Boolean, air:Boolean, slowing:int, splash:int, venom:int) {
            _name = name;
            _towerbase=towerbase;
            _ground = ground;
            _air = air;
            _slow = slowing;
            _splash = splash;
            _venom = venom;
            _status = Config.getTowerStatus(_name);
        }
        
        // 指定したレベルのステータスがあるかどうか
        public function hasStatus(level:int):Boolean {
            return level <= _status.length;
        }
        
        // 種類に応じて、砲頭の角度を調整する
        public function adjustBodyRotation(diffx:Number, diffy:Number, currentRotation:Number):Number {
            switch(_name) {
                case "Voltex": { return currentRotation + 10; }
                default: { return Math.atan2(diffy, diffx) * 180 / Math.PI; }
            }
        }
        
        // 種類に応じた弾を生成する
        public function createBullet(posx:int, posy:int, level:int, target:Enemy, world:World):Bullet {
            var image:BitmapData = ImageFactory.getImage("Bullet_" + _name);
            var pos:TileBasedPoint = TileBasedPoint.createFromWorldPos(posx, posy);
            var status:TowerStatus = getStatus(level);

            switch(_name) {
            // Bullet引数内訳(pos:TileBasedPoint, life:int, power:int, radius:int, speed:int, ground:Boolean, air:Boolean, level:int
            //               slow:int,venom:int, homing:Boolean, pierce:Boolean, target:Enemy, image:BitmapData, world:World)
                //case "Arrow":
                //{ return new Bullet(pos, status.range, status.damage, _splash, 8, _ground, _air, level, _slow, _venom, false, false, target, image, world); }
                case "Gun":
                { return new Bullet(pos, status.range, status.damage, _splash, (12+2*level), _ground, _air, level, _slow, _venom, true, false, target, image, world); }
                case "Gatling":
                { return new Bullet(pos, status.range, status.damage, _splash, 24, _ground, _air, level, _slow, _venom, false, false, target, image, world); }
                case "Cannon":
                { return new Bullet(pos, status.range, status.damage, _splash, 8, _ground, _air, level, _slow, _venom, true, false, target, image, world); }
                case "Venom":
                { return new Bullet(pos, status.range, status.damage, _splash, 10, _ground, _air, level, _slow, _venom, true, false, target, image, world); }
                case "Voltex":
                { return new Bullet(pos, 0, status.damage, status.range, 0, _ground, _air, level, _slow, _venom, false, false, target, image, world); }
                case "AntiFly":
                { return new Bullet(pos, 900, status.damage, (Const.ENEMY_SIZE + Const.BULLET_SIZE) / 2, Const.NODE_SIZE, _ground, _air, level, _slow, _venom, false, true, target, image, world); }
            }
            return null; // never called
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * TowerStatus
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    //public 
    class TowerStatus {
        private var _level:int;            // レベル 
        private var _cost:int;            // コスト
        private var _damage:int;        // ダメージ
        private var _range:int;            // 射程
        private var _firerate:Number;    // 射撃間隔(発/秒)
        private var _reloadSpeed:Number;
        
        public function get level():int { return _level; }
        public function get cost():int { return _cost; }
        public function get damage():int { return _damage; }
        public function get range():int { return _range; }
        public function get firerate():Number { return _firerate; }
        public function get reloadSpeed():Number { return _reloadSpeed; }
        
        // ※インスタンスは Config.getTowerStatus() から生成する
        public function TowerStatus(level:int, cost:int, damage:int, range:int, firerate:Number) {
            _level = level;
            _cost = cost;
            _damage = damage;
            _range = range;
            _firerate = firerate;
            _reloadSpeed = _firerate * 100 / Const.FRAME_RATE;
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * Bullet
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.geom.Point;
    
    //public 
    class Bullet extends Sprite {
        private var _life:int;            // 寿命(最大射程)
        private var _power:int;            // 威力
        private var _splashRadius:int;    // 範囲攻撃の半径(範囲攻撃で無いなら0)
        private var _speed:int;            // 速さ
        private var _ground:Boolean;    // 地上の敵に当たるか
        private var _air:Boolean;        // 空中の敵にあたるか
        private var _level:int;        // 発射弾のレベル
        private var _slow:int;        // スロー効果量
        private var _venom:int;        // 毒効果量
        private var _homing:Boolean;    // 追尾能力
        private var _pierce:Boolean;    // 貫通力
        private var _target:Enemy;        // ターゲット
        private var _world:World;
        
        private var _position:TileBasedPoint;    // 位置
        private var _velocity:Point;            // 速度
        
        public function get splashRadius():int { return _splashRadius; }
        public function get ground():Boolean { return _ground; }
        public function get air():Boolean { return _air; }
        
        public function Bullet(
            pos:TileBasedPoint, 
            life:int, power:int, radius:int, speed:int, 
            ground:Boolean, air:Boolean, level:int, slow:int, venom:int,
            homing:Boolean, pierce:Boolean, 
            target:Enemy, image:BitmapData, world:World)
        {
            _life = life;
            _power = power;
            _splashRadius = radius;
            _speed = speed;
            _ground = ground;
            _air = air;
            _level = level;
            _slow = slow;
            _venom = venom;
            _homing = homing;
            _pierce = pierce;
            _target = target;
            _world = world;
            
            _position = pos;
            x = int(_position.x);
            y = int(_position.y);
            _velocity = new Point();

            changeVelocity();
            draw(image);
        }
        
        private function draw(image:BitmapData):void {
            var bitmap:Bitmap = new Bitmap(image);
            bitmap.x = bitmap.y = -int(Const.BULLET_SIZE / 2);
            addChild(bitmap);
        }
        
        // 速度を変更し、向きを変える
        private function changeVelocity():void {
            var diffX:Number = _target.posX - _position.x;
            var diffY:Number = _target.posY - _position.y;
            var radian:Number = Math.atan2(diffY, diffX);
            _velocity.x = _speed * Math.cos(radian);
            _velocity.y = _speed * Math.sin(radian);
            
            var degree:Number = radian * 180 / Math.PI;
            rotation = degree;
        }

        
        public function update():void {
            // 移動する
            _life -= _speed;
            x = int(_position.x += _velocity.x);
            y = int(_position.y += _velocity.y);
            if (_homing) { changeVelocity(); }
            
            // 画面外に出たら、消滅する
            if (_position.x < 0 || _position.x > 465 || _position.y < 0 || _position.y > 465) {
                _world.removeBullet(this);
                return;
            }
            
            // 射程外に出たら、(範囲攻撃の弾なら周辺の敵にダメージを与え)消滅する
            // 範囲攻撃の弾なら範囲アニメを出すspreadEffects(位置x、位置y、スプレッドサイズ、色、時間)
            if (_life <= 0) {
                if (_splashRadius > 0) { 
                    if(_slow > 0){_world.addEffect(new splashEffect(x, y, _splashRadius,0x000000,3))
                    }else if(_venom > 0){_world.addEffect(new splashEffect(x, y, _splashRadius,0x00aa00,1))
                    }else {_world.addEffect(new splashEffect(x, y, _splashRadius,0xff5500,1))};
                    _world.damageSurroundingEnemies(this); 
                }
                _world.removeBullet(this);
                return;
            }
            
            // 貫通力ありなら、(ターゲットを問わず)周辺の敵にダメージを与える
            // ターゲットが死んでいたら、直線軌道に変更
            // ターゲットに当たっていたら、ダメージを与え消滅する
            if (_pierce) {
                _world.damageSurroundingEnemies(this);
            }else if (_target.isDead()) {
                _homing = false;
            }else if (isHitTarget(_target, (Const.BULLET_SIZE + Const.ENEMY_SIZE) / 2)) {
                if (_splashRadius > 0) {
                    if(_slow > 0){_world.addEffect(new splashEffect(x, y, _splashRadius,0x000000,3))
                    }else if(_venom > 0){_world.addEffect(new splashEffect(x, y, _splashRadius,0x00aa00,1))
                    }else {_world.addEffect(new splashEffect(x, y, _splashRadius,0xff5500,1))};
                    _world.damageSurroundingEnemies(this); 
                }else { damageTarget(_target); }
                _world.removeBullet(this);
                return;
            }
        }

        
        public function isHitTarget(target:Enemy, radius:Number):Boolean {
            var diffX:Number = target.posX - _position.x;
            var diffY:Number = target.posY - _position.y;
            return diffX * diffX + diffY * diffY < radius * radius;
        }
        
        public function damageTarget(target:Enemy):void {
            target.damage(_power, _level, _slow,_venom);
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * Enemy
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.filters.GlowFilter;
    import flash.geom.Point;
    
    //public 
    class Enemy extends Sprite {
        private var _world:World;
        private var _center:TileBasedPoint;    // 中心の座標
        private var _velocity:Point;        // 速度ベクトル
        private var _currentSpeed:Number;    //速度の変更時に参照する基本速度の値
        private var _type:EnemyType;        // 種族
        private var _HP:int;                // 現在のHP
        private var _maxHP:int;                // 最大HP
        private var _point:int;                // 倒した時のポイント
        private var _money:int;                // 倒した時のお金
        private var _targetable:Boolean;    // 索敵可能かどうか
        private var _isBaby:Boolean;    //出産能力で生まれた場合TRUE(ゲートやスキルの効果を子どもにも継続させる場合に参照)
        private var _babyNum:int;    //出産能力がある場合の出産合計数
        
        private var _liveCount:int;            //出現時間カウント(ランダムな位相差あり)
        private var _slowingCount:int;        //スロウ効果の時間カウント
        private var _attackedSlow:int;        //スロウ効果によって減少した速度値(一時変化)
        private var _venomingCount:int;     //毒効果の時間カウント
        private var _venomingLevel:int;     //毒効果の最大レベルを継続する
        private var _regeneAmount:Number;     //小数で累積する回復量のカウント
        private var _fadeAlpha:Number;        //フェイド能力のアルファ値
        private var _BA:BornAbility;        //出産能力
        private var _AA:AccelerateAbility;    //加速能力
        
        private var _image:Sprite;
        private var _HPbar:Sprite;
        
        private var _goal:Goal;
        private var _nextNode:Node;
        
        public function get posX():Number { return _center.x; }
        public function get posY():Number { return _center.y; }
        public function get tileX():int { return _center.tileX; }
        public function get tileY():int { return _center.tileY; }
        public function get type():EnemyType { return _type; }
        public function get targetable():Boolean { return _targetable; }
        public function get BA():BornAbility { return _BA; }
        public function get AA():AccelerateAbility { return _AA; }
        public function isDead():Boolean { return _HP <= 0; }
        public function isBaby():Boolean { return _isBaby; }
        public function babyNum():int { return _babyNum; }
        public function setGoal(value:Goal):void {
            _goal = value;
            _nextNode = _goal.getNext(_center.x, _center.y, _type.flying);
        }
        
        public function Enemy(center:TileBasedPoint, type:EnemyType, HP:int, point:int, money:int, world:World ,isBaby:Boolean) {
            _world = world;
            _isBaby = isBaby;
            _center = center;
            x = int(_center.x);
            y = int(_center.y);
            _type = type;
            _velocity = new Point(0,0); //移動の速度ベクトルは出現時ゼロ
            _currentSpeed = type.speed; //ベクトルの長さとなる移動速度はタイプの値
            _HP = _maxHP = HP;
            _point = point;
            _money = money;

            _liveCount = Math.floor( (Math.random()*Const.FRAME_RATE) ); //ランダムな位相差あり
            _slowingCount = 0;
            _attackedSlow = 100;
            _venomingCount = 0;
            _venomingLevel = 1;
            _regeneAmount = 0 ;
            _BA = BAbility(); //出産能力のデータセット
            _babyNum = 0;
            _AA = AAbility(); //加速能力のデータセット
            _targetable = true ;

            draw();
        }
        
        private function BAbility():BornAbility {
            if ( _type.born ) { return BornAbility.getBornData( _type.name );
            }else { return null };
        }
        private function AAbility():AccelerateAbility {
            if ( _type.accelerate ) { return AccelerateAbility.getAccelerateData( _type.name );
            }else { return null };
        }
        
        private function draw():void {
            _image = addChild(new Sprite()) as Sprite;
            var bitmap:Bitmap = _image.addChild(new Bitmap(ImageFactory.getImage(_type.name), "auto", true)) as Bitmap;
            bitmap.x = bitmap.y = int( -Const.ENEMY_SIZE / 2);
            
            var HPbarBackground:Sprite = addChild(new Sprite()) as Sprite;
            HPbarBackground.x = -Const.ENEMY_SIZE / 2;
            HPbarBackground.y = -(Const.ENEMY_SIZE / 2 + 2);
            HPbarBackground.graphics.beginFill(0xff0000);
            HPbarBackground.graphics.drawRect(0, 0, Const.ENEMY_SIZE, 1);
            HPbarBackground.graphics.endFill();
            
            _HPbar = HPbarBackground.addChild(new Sprite()) as Sprite;
            _HPbar.graphics.beginFill(0xffff00);
            _HPbar.graphics.drawRect(0, 0, Const.ENEMY_SIZE, 1);
            _HPbar.graphics.endFill();
        }
        
        
        public function update(world:World):void {
            
            _liveCount ++;
            if (_BA != null && _babyNum >= _BA.limit) { _BA = null };

            // スロー状態を更新
            if (_slowingCount > 0) { _slowingCount--; } 
            else { 
                _image.filters = CONDITION_GOOD; 
                _attackedSlow = 100 ; 
            }
            //毒状態を更新(_venomingLevelは毒被弾時にタワーレベルを継承)
            if (_venomingCount > 0) { 
                _venomingCount--;
                var venomDamage : Number = _currentSpeed * (0.5 + (_venomingLevel * 0.5) + (Math.floor(_venomingLevel / 5) * 3));
                damage(venomDamage,1,0,0); 
            } else { 
                _HPbar.filters = CONDITION_GOOD; 
            }
            //regeneration > 0 のときHP回復 
            if ( _type.regeneration > 0 ) {
                _regeneAmount += ((_maxHP / 1000) * _type.regeneration);
                    if (_regeneAmount >= 1) {
                        _HP += int(_regeneAmount)
                        _regeneAmount -= int(_regeneAmount)}
                    if (_HP >= _maxHP) { _HP = _maxHP } ;
                _HPbar.scaleX = _HP / _maxHP;
                }
            //fade > 0 のときフェイド (_liveCountをフェイド間隔でわった偶奇でチェンジ)
            if ( _type.fade > 0 ) {
                if (Math.floor((_liveCount / _type.fade) % 2) == 0) { ;
                    if ( ((_liveCount % _type.fade) / _type.fade) < 0.2 ) { _fadeAlpha = 1 ;
                    } else { _fadeAlpha = 1 - ((_liveCount % _type.fade) / _type.fade)} ;
                    this.alpha = _fadeAlpha ;
                    _targetable = true ;
                }
                if (Math.floor((_liveCount / _type.fade) % 2) == 1) { ;
                    _fadeAlpha = 0 ;
                    this.alpha = _fadeAlpha ;
                    _targetable = false ;
                }
            }    
            
            // 移動する(スロー効果は0~99%の間)
            if (_attackedSlow <= 1) { _attackedSlow = 1 };
            if (_attackedSlow >= 100) { _attackedSlow = 100 };
            x = int(_center.x += (_velocity.x * (_attackedSlow/100)));
            y = int(_center.y += (_velocity.y * (_attackedSlow/100)));

            // ゴールに到着していたら、ライフを減らして消滅
            if (_center.tileX == _goal.tileX && _center.tileY == _goal.tileY) {
                GameData.instance.lives--;
                _HP = 0;
                _world.removeEnemy(this);
                return;
            }
            // 次に進むべきノードに到着していたら、その次に進むべきノードに更新
            if (_center.tileX == _nextNode.tileX && _center.tileY == _nextNode.tileY) {
                _nextNode = _goal.getNext(_center.x, _center.y, _type.flying);
            }
            
            // 速度と向きの更新
            var radian:Number = Math.atan2(_nextNode.centerY - _center.y, _nextNode.centerX - _center.x);
            // 【向き変化】加速能力:Angle >0 の場合、向きを変える
            if (_AA != null && _AA.Angle > 0 ) { 
                radian += (_AA.Angle * Math.PI / 180);
            }
            // 【向き変化】加速能力:sineSlip >0 の場合、向きをぐねぐねさせる
            if (_AA != null && _AA.sineSlip > 0 ) { 
                radian += Math.sin(_liveCount/AA.sineSlip)* 12 *(Math.PI*2)/180 ; //角度の幅は12度内に固定。これ以上だと暴走しやすい
            }
            // 【速度変化】加速能力:時間条件が満たされたら加速
            if (_AA != null && _AA.intervalRun > 0 && (_liveCount % _AA.intervalRun == 0 )) {
                    _currentSpeed = _AA.SpeedChange(_currentSpeed);
            }            
            // 【速度変化】全キャラ共通:移動速度をわずかにふらつかせる(+-は周期変化)
            _currentSpeed += Math.sin(_liveCount)*(Math.random()*0.1) ;
            
            //【速度と向きの計算】
            if (_currentSpeed <= _type.MinSpeed) { _currentSpeed = _type.MinSpeed };
            if (_currentSpeed >= _type.MaxSpeed) { _currentSpeed = _type.MaxSpeed };
            _velocity.x = (_velocity.x + _currentSpeed * Math.cos(radian)) * 0.5;
            _velocity.y = (_velocity.y + _currentSpeed * Math.sin(radian)) * 0.5;
            var degree:Number = radian * 180 / Math.PI;
            _image.rotation = degree;
            
            // 【向き変化】Decoyのみ向きは動きと無関係に回転
            if (_type.name == "Decoy-1") { _image.rotation = (_liveCount * 90 / Math.PI) };
            if (_type.name == "Decoy-2") { _image.rotation = (_liveCount * 90 / Math.PI) * ( -1) };
            if ((_type.name == "Decoy-1" || _type.name == "Decoy-2") && _liveCount > (5 * Const.FRAME_RATE)) { _world.removeEnemy(this) };
            // 時限性の出産があれば出産
            if (_BA != null && _BA.intervalBorn > 0 && (_liveCount % _BA.intervalBorn == 0 )) {
                _babyNum = _BA.EnemyBirth(_babyNum,"interval", this, _center, _maxHP, _point, _money, _world);
                if (_BA.selfRemove ) {
                    _HP = 0;
                    _BA = null;
                    _world.removeEnemy(this);}
            }
        }

        private static const CONDITION_GOOD:Array = [];
        private static const CONDITION_SLOWED:Array = [new GlowFilter(0x0088ff, 1, 4, 4)];
        private static const CONDITION_VENOMED:Array = [new GlowFilter(0x00ff00, 1, 2, 2,255,1,true)];

        // ダメージを受ける処理
        public function damage(amount:Number, level:int, slow:int, venom:int ):void {
            _HP -= amount;
             if (_HP <= 0) { DoomAction() } ;
            _HPbar.scaleX = _HP / _maxHP;
            
            //以下、生きている場合のみ適用
            if (_HP > 0){
                // 能力を持っている場合に、HP割合条件による能力の作動
                if (_BA != null  && _BA.HPrateBorn > 0 && _HP <= (_BA.HPrateBorn * _maxHP)) {
                    _babyNum = _BA.EnemyBirth(_babyNum,"damaged",this, _center, _maxHP, _point, _money, _world);
                    if (_BA.selfRemove ) {
                        _HP = 0;
                        _world.removeEnemy(this);}
                }
                if (_AA != null  && _AA.HPrateRun > 0 && _HP <= (_AA.HPrateRun * _maxHP)) {
                    _currentSpeed = _AA.SpeedChange(_currentSpeed);
                }           
                // 攻撃にスロー効果が付いていて、それに免疫が無かったら、スロー状態になる
                if (( slow > 0 ) && !_type.immunity) { 
                    _attackedSlow = (100 - slow - level*5) ;
                    _slowingCount = Const.SLOWING_DURATION;
                    _image.filters = CONDITION_SLOWED;
                }
                // 攻撃に毒効果が付いていたら、毒状態になる(高レベルの毒効果優先、途中で低レベルの毒攻撃を受けると持続時間リセット)
                if (( venom > 0 ) && !_type.immunity) { 
                    if ( _venomingLevel < level){
                        _venomingLevel = level } ;
                    _venomingCount = venom * Const.VENOMING_DURATION;
                    _HPbar.filters = CONDITION_VENOMED;    
                }
                // 加速能力を持っていて、ダメージ量の加速条件があるとき、ダメージが条件値以上なら加速
                if (_AA != null && _AA.damageRun > 0 && amount >= _AA.damageRun) {
                    var changedSpeed : Number = _AA.SpeedChange(_currentSpeed);
                    _currentSpeed = changedSpeed;
                }
            }
        }

        //-------------------------------------------------
        // 死亡時アクション
        private function DoomAction():void {
                GameData.instance.score += _point;
                // 毒状態で死んだときインフェクション発生
                if (_venomingCount > 0 ) {
                    var Infection:BitmapData = ImageFactory.getImage("Infection");
                    _world.addBullet( new Bullet(_center, 0, 1, 12, 2, true, false, 1, 0, 5, false, false, this, Infection, _world) );
                }
                // 死亡出産のチェック
                if( _BA != null && _BA.deadBorn ){
                    _babyNum = _BA.EnemyBirth(_babyNum,"dead",this, _center, _maxHP, _point, _money, _world);
                    if (_BA.descent) { _money = 0 };
                }
                _world.removeEnemy(this);
                GameData.instance.gold += _money;
                if(_money > 0){_world.addEffect(new Coin(_center.x, _center.y))};
                //return;
            }
     
        public function hasPathToGoal():Boolean {
            return _goal.hasPath(_center.tileX, _center.tileY);
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * EnemyType
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.utils.Dictionary;
    
    //public 
    class EnemyType {
        private static var _types:Dictionary;
        public static function initialize():void { _types = Config.getEnemyType(); }
        public static function getType(typeName:String):EnemyType { return _types[typeName]; }
        
        private var _name:String;        // 種族名称
        private var _speed:Number;        // 移動の速さ
        private var _MinSpeed:Number;        // 移動の最小速度(スロー効果含めない)
        private var _MaxSpeed:Number;        // 移動の最大速度        
        private var _flying:Boolean;    // 飛んでいるかどうか
        private var _immunity:Boolean;    // 免疫(状態異常スローに対する)があるかどうか
        private var _regeneration:int;    // HPの回復量(MaxHPの千分率/フレーム)
        private var _fade:int;    // フェイド能力量(時間間隔)
        private var _born:Boolean;    // 出産能力があるかどうか
        private var _accelerate:Boolean;    // 加速能力があるかどうか
        
        public function get name():String { return _name; }
        public function get speed():Number { return _speed; }
        public function get MinSpeed():Number { return _MinSpeed; }
        public function get MaxSpeed():Number { return _MaxSpeed; }
        public function get flying():Boolean { return _flying; }
        public function get immunity():Boolean { return _immunity; }
        public function get regeneration():int { return _regeneration; }
        public function get fade():int { return _fade; }
        public function get born():Boolean { return _born; }
        public function get accelerate():Boolean { return _accelerate; }
        
        // ※インスタンスは Config.getEnemyType() から生成する
        public function EnemyType(name:String, speed:Number, MinSpeed:Number,MaxSpeed:Number,flying:Boolean, immunity:Boolean, 
                                regeneration:int, fade:int, born:Boolean, accelerate:Boolean) {
            _name = name;
            _speed = speed;
            _MinSpeed = MinSpeed;
            _MaxSpeed = MaxSpeed;
            _flying = flying;
            _immunity = immunity;
            _regeneration = regeneration;
            _fade = fade;
            _born = born;
            _accelerate = accelerate;            
        }
    }
//}
/*----------------------------------------------------------------------------------------------------------------------
 * BornAbility 出産能力管理【F】
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.utils.Dictionary;
    
    //public 
    class BornAbility {
        private static var _parent:Dictionary;
        public static function initialize():void { _parent = Config.getBornAbility(); }
        public static function getBornData (parentName:String):BornAbility { return _parent[parentName]; }
        
        private var _name:String;        //親の名前 
        private var _childrenName:String;        //生まれる子の名前
        private var _childrenHP:Number;      //生まれる子のHP (親に対する割合)
        private var _childrenPoint:Number;   //生まれる子のPoint (親に対する割合)
        private var _amount:int;    //1回の出産で生まれる数
        private var _limit:int;    //出産数の限界量
        private var _intervalBorn:int;    //時間制で生まれるとき、その時間間隔 
        private var _HPrateBorn:Number;    //HPの残量で生まれるとき、その残りHP割合
        private var _deadBorn:Boolean;    //ダメージ量で生まれるとき、生まれる最低ダメージ
        private var _descent:Boolean;    //相続の有無。TRUEのとき自分はお金を出さず、子がお金を出す
        private var _selfRemove:Boolean;    //自己消去の有無。TRUEのとき出産と同時におやは消える
        private var _childrenFull:Boolean;    //子どもが満員のお知らせ。値は計算ごとに更新される
        
        public function get name():String { return _name; }
        public function get childrenName():String { return _childrenName; }
        public function get childrenHP():Number { return _childrenHP; }
        public function get childrenPoint():Number { return _childrenPoint; }
        public function get amount():int { return _amount; }
        public function get limit():int { return _limit; }
        public function get intervalBorn():int { return _intervalBorn; }
        public function get HPrateBorn():Number { return _HPrateBorn; }
        public function get deadBorn():Boolean { return _deadBorn; }
        public function get descent():Boolean { return _descent; }
        public function get selfRemove ():Boolean { return _selfRemove; }
        public function get childrenFull ():Boolean { return _childrenFull; }
        
        public function EnemyBirth(babyNum:int, chance:String, parent:Enemy, center:TileBasedPoint, MaxHP:int, point:int, money:int, world:World):int{
            var _money:int = money;
            if ( !_descent ) { _money = 0 } ; //「相続」がfalseの場合、子どもが持つ報酬は0に
            for ( var i:int = 1; i <= _amount ; i++){
                if (babyNum < limit) {
                var enemyChildren:Enemy = new Enemy(TileBasedPoint.createFromWorldPos(center.x, center.y), EnemyType.getType(_childrenName), int(Math.ceil(MaxHP*_childrenHP)), int(Math.ceil(point*_childrenPoint)), _money, world, true); 
                world.addEnemy(enemyChildren);
                babyNum ++;
                _childrenFull = false;
                }else if (babyNum >= limit) { _childrenFull = true };             
            }
            return babyNum;
        }

        
        // ※インスタンスは Config.getBornAbility() から生成する
        public function BornAbility(name:String, childrenName:String, childrenHP:Number, childrenPoint:Number, amount:int, limit:int, 
                                intervalBorn:int, HPrateBorn:Number, deadBorn:Boolean, descent:Boolean, selfRemove:Boolean) {
            _name = name;
            _childrenName = childrenName;
            _childrenHP = childrenHP;
            _childrenPoint = childrenPoint;
            _amount = amount;
            _limit = limit;
            _intervalBorn = intervalBorn;
            _HPrateBorn = HPrateBorn;
            _deadBorn = deadBorn;
            _descent = descent;
            _selfRemove = selfRemove;
            _childrenFull = false;
        }
    }
//}
/*
/*----------------------------------------------------------------------------------------------------------------------
 * AccelerateAbility 加速能力管理【F】
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.utils.Dictionary;    
    //public 
    class AccelerateAbility {
        private static var _runner:Dictionary;
        public static function initialize():void { _runner = Config.getAccelerateAbility(); }
        public static function getAccelerateData (runnerName:String):AccelerateAbility { return _runner[runnerName]; }
        
        private var _name:String;        //能力者のタイプ名 
        private var _AddPoint:Number;        //速度加算量(マイナスあり)
        private var _RatePoint:Number;      //速度割合変化量
        private var _Angle:Number;            //飛行角度(度数値)
        private var _sineSlip:int;    //ふらふら移動するときの周期量
        private var _intervalRun:int;    //時間制で変化するとき、その時間間隔 
        private var _HPrateRun:Number;    //HPの残量で加速するとき、その残りHP割合        
        private var _damageRun:Number;    //ダメージ量で加速するときの最低ダメージ(割合)
        
        public function get name():String { return _name; }
        public function get AddPoint():Number { return _AddPoint; }
        public function get RatePoint():Number { return _RatePoint; }
        public function get Angle():int { return _Angle; }
        public function get sineSlip():int { return _sineSlip; }
        public function get intervalRun():int { return _intervalRun; }
        public function get HPrateRun():Number { return _HPrateRun; }
        public function get damageRun():Number { return _damageRun; }
        
        //---------------------------
        public function SpeedChange(speed:Number):Number{
            speed = (_RatePoint * speed) + _AddPoint;
            return speed ;
        }

        // ※インスタンスは Config.getAccelerateAbility() から生成する
        public function AccelerateAbility(name:String, AddPoint:Number, RatePoint:Number, Angle:Number, sineSlip:int, 
                                intervalRun:int, HPrateRun:Number, damageRun:Number ) {
            _name = name;
            _AddPoint = AddPoint;
            _RatePoint = RatePoint;
            _Angle = Angle;
            _sineSlip = sineSlip;
            _intervalRun = intervalRun;
            _HPrateRun = HPrateRun;
            _damageRun = damageRun;

        }
    }
//}
/*
/* ----------------------------------------------------------------------------------------------------------------------
 * Coin
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import org.libspark.betweenas3.BetweenAS3;
    import org.libspark.betweenas3.easing.Back;
    import org.libspark.betweenas3.easing.Expo;
    
    //public 
    class Coin extends Sprite {
        public function Coin(posx:int, posy:int) {
            x = posx;
            y = posy;
            
            draw();
            
            BetweenAS3.serial (
                BetweenAS3.tween(this, { $y: -16 }, null, 0.4, Back.easeOut),
                BetweenAS3.tween(this, { alpha: 0 }, null, 0.4, Expo.easeIn),
                BetweenAS3.removeFromParent(this)
            ).play();
        }
        
        private function draw():void {
            var bitmap:Bitmap = new Bitmap(ImageFactory.getImage("Coin"));
            bitmap.smoothing = true;
            bitmap.x = bitmap.y = -4;
            addChild(bitmap);
        }
    }
//}
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * SplashEffect 【F】
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import org.libspark.betweenas3.BetweenAS3;
    import org.libspark.betweenas3.easing.Expo;
    
    //public 
    class splashEffect extends Sprite { 
        //爆発エフェクト (位置x、位置y、スプレッドサイズ、色、時間)        
        public function splashEffect(posx:int, posy:int, size:int, color:uint ,appearTime:int) {
            x = posx;
            y = posy;
            
            drawSplash(color);

            //サイズ値の半径まで拡大、scaleの拡大は右下に伸びるので、同時に基点座標(左上)を動かし、見た目の場所を固定する
            BetweenAS3.serial (
                BetweenAS3.tween(this, { $scaleX: size ,$scaleY: size, alpha: 0 ,$x: -size ,$y: -size  }, null, appearTime, Expo.easeOut),
                BetweenAS3.removeFromParent(this)
            ).play();
        }
        
        private function drawSplash(color:uint):void {
            var sprite:Sprite = new Sprite ;
            sprite.graphics.beginFill(color,0.8);
            sprite.graphics.drawCircle(1,1,1);
            sprite.x = sprite.y=0 ;
            addChild(sprite);
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * Cursor  タワー選択などの動作時にカーソルが変化
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.events.Event;
    
    //public 
    class Cursor extends Sprite {
        private var _world:World;
        private var _border:Sprite;        // 枠線
        private var _baseborder:Sprite;        //選択中の四角い枠追加【F】
        private var _towerImage:Sprite;    // タワーの画像
        private var _towerBody:Bitmap;    // タワー本体の画像
        private var _blockingText:TextField; //ブロッキングの文字表示
        private var _blockingAlart:int
        
        public function Cursor(world:World) {
            _world = world;
            _border = createBorder(0xffff00);
            _baseborder = createBorder(0xff0000);  //選択中の四角い枠追加【F】
            _towerImage = new Sprite();
            _towerImage.addChild(_towerBody = new Bitmap());
            _towerImage.alpha = 0.5;

            _blockingText = ImageFactory.createBorderedText(0, 0, 60, 15, "Blocking!", 12, 0xff0000, 0xffffff);
            _blockingAlart = 0;
            
            mouseChildren = mouseEnabled = false;
            
            GameData.instance.addEventListener(Const.EVENT_CHANGE_SELECTEDTOWER, onUpdateSelectedTower);
        }
        
        // マップ上でタワー選択時に表示する囲み線を生成【F】
        private function createBorder(borderColor:uint):Sprite {
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(2, borderColor);
            sprite.graphics.drawRect(0, 0, Const.TOWER_SIZE, Const.TOWER_SIZE);
            return sprite;
        }
        
        //ブロッキング警告
        public function blockingAlart():void {
            _blockingAlart = 15;
            _blockingText.x = -10 ;
            _blockingText.y = 2 ;
            _blockingText.alpha = 1;
            addChild(_blockingText);
        }

        
        // 
        public function update(posx:int, posy:int):void {
            var selectedTower:Tower = GameData.instance.selectedTower;
            var position:TileBasedPoint;

            // (selectedTowerがnullでない)かつ(selectedTower.activeがtrue)とき
            if (selectedTower != null && selectedTower.active) {
                position = TileBasedPoint.createFromWorldPos(selectedTower.x, selectedTower.y);
            }else {
                position = TileBasedPoint.createFromWorldPos(posx, posy);
                position.setTilePos(position.tileX, position.tileY);
            }
            
            x = position.x;
            y = position.y;
            
            updateRangeCircle(position.tileX, position.tileY);
 
            updateBlockingAlart();
                
            
        }
        
        private function updateBlockingAlart():void {
            if ( _blockingAlart > 0) {
                _blockingAlart-- ;
                _blockingText.alpha -= 0.04;
                if (_blockingAlart == 0) { removeChild(_blockingText) };
            }
        }
        
        
        // 設置可否で変える色の設定
        private static const POSSIBLE:uint = 0xffffff;
        private static const IMPOSSIBLE:uint = 0xff0000;
        
        private function updateRangeCircle(tilex:int, tiley:int):void {
            graphics.clear();
            
            var selectedTower:Tower = GameData.instance.selectedTower;
            if (selectedTower == null) { return; }
            // 配置できる場所かどうかで、レンジサークルの色を変える【F】
            var color:uint = (selectedTower.active || _world.canBuildTower(tilex, tiley)) ? POSSIBLE : IMPOSSIBLE;
            graphics.lineStyle(0, color, 0.6);
            graphics.beginFill(color, 0.2);
            graphics.drawCircle(int(Const.TOWER_SIZE / 2), int(Const.TOWER_SIZE / 2), selectedTower.type.getStatus(selectedTower.level).range);
            graphics.endFill();
            //配置できない場所ではカーソルが赤い四角になる【F】
            if(_world.canBuildTower(tilex, tiley) || selectedTower.active ) {
                 if (contains(_baseborder)) {removeChild(_baseborder)};
            }else{addChild(_baseborder)}

        }
                
        
        private function onUpdateSelectedTower(e:Event):void {
            var selectedTower:Tower = GameData.instance.selectedTower;

            if (contains(_border)) { removeChild(_border); }
            if (contains(_baseborder)) { removeChild(_baseborder); }
            if (contains(_towerImage)) { removeChild(_towerImage); }
            
            if (selectedTower == null) { return; }
            // タワーが選択中なら囲み線表示
            if (selectedTower.active) {
                addChild(_border);
            }else {
                _towerBody.bitmapData = ImageFactory.getImage(selectedTower.type.name);
                _towerBody.smoothing = true;
                addChild(_towerImage);
            }
            
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * Frontend
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.GlowFilter;
    import flash.geom.ColorTransform;
    import flash.text.TextField;
    import flash.ui.Keyboard;
    
    //public 
    class Frontend extends Sprite {
        private var _wave:TextField;
        private var _score:TextField;
        private var _lives:TextField;
        private var _gold:TextField;

        private var _backSprite:Sprite;        //背景的な使用のスプライト        
        private var _buttons:Sprite;                    // ボタンをまとめる表示オブジェクト
        private var _towerStatus:TowerStatusWindow;        // タワーのステータスを表示するウインドウ

        public function Frontend(posx:int, posy:int) {
            x = posx;
            y = posy;
            
            addChild(createTowerSelectionWindow(365, 0));
            addChild(createGameStatusWindow(0, 0));
                        
            GameData.instance.addEventListener(Const.EVENT_CHANGE_SELECTEDTOWER, onUpdateSelectedTower);
            GameData.instance.addEventListener(Const.EVENT_CHANGE_GAMESTATUS, onUpdateGameStatus);
            
        }
                      
        // タワー選択ボタンを配置するウインドウと、タワーのステータスを表示するウインドウを作成する
        private function createTowerSelectionWindow(posx:int, posy:int):Sprite {
            var towerSelection:Sprite = ImageFactory.createWindow(posx, posy, 100, 417);
            towerSelection.addChild(_backSprite = new Sprite());            
            _backSprite.graphics.beginFill(0x505050);_backSprite.graphics.drawRect(5,30,90,110);
            _backSprite.addChild(ImageFactory.createSimpleText(5,-15, 10, 90, "Tower", 10, 0xffffff));
            _backSprite.graphics.beginFill(0x505050);_backSprite.graphics.drawRect(5,150,90,70);
           
            // タワー選択ボタンを7つ作成して配置する
            towerSelection.addChild(_buttons = new Sprite());            

            var towertypes:Vector.<TowerType> = Config.getTowerType();            
            for (var i:int = 0; i < 7; i++) {
                 //var tower:Tower = _buttons.addChild(new Tower(((i < 4) ? 15 : 53), 32 + 38 * (i % 4), towertypes[i])) as Tower;
                var tower:Tower = _buttons.addChild(new Tower(12 + 26 * (i % 3),5 + Math.ceil((i+1)/ 3)*35, towertypes[i])) as Tower;
                //tower.addChild(ImageFactory.createSimpleText(((i < 4) ? -12 : 32), 0, 12, 32, String(i + 1), 10, 0xffffff));
                tower.scaleX = 0.75; tower.scaleY = 0.75;
                
                HotKey.bind(Keyboard.NUMBER_1 + i, tower.clickTower);
                HotKey.bind(Keyboard.NUMPAD_1 + i, tower.clickTower);
            }
            
            // 選択キャンセルボタンを作成して配置する
            var cancelButton:Sprite = towerSelection.addChild(createCancelButton(12 + 27, 5 + 3*35)) as Sprite;
            //cancelButton.addChild(ImageFactory.createSimpleText(32, 0, 12, 32, "0", 10, 0xffffff));
            cancelButton.scaleX=0.75; cancelButton.scaleY=0.75;
            HotKey.bind(Keyboard.NUMBER_0, isSelectedCancelButton);
            HotKey.bind(Keyboard.NUMPAD_0, isSelectedCancelButton);
            HotKey.bind(Keyboard.ESCAPE, isSelectedCancelButton);
            
            // 選択ウィンドウ内にテータスウィンドウを設置し隠しておく【F】
            towerSelection.addChild(_towerStatus = new TowerStatusWindow(5, 225));
            _towerStatus.visible = false;
            return towerSelection;
        }
         
        // ゲームのステータスを表示するウインドウを作成する
        private function createGameStatusWindow(posx:int, posy:int):Sprite {
            var gameStatus:Sprite = ImageFactory.createWindow(posx, posy, 463, 25);
            gameStatus.addChild(ImageFactory.createBorderedText(14, 0, 40, 25, "Wave :", 12, 0xffffff, 0x808080));
            gameStatus.addChild(_wave = ImageFactory.createScoreText(54, 0, 25, 25, "0", 14, 0xffffff));
            gameStatus.addChild(ImageFactory.createBorderedText(93, 0, 40, 25, "Score :", 12, 0xffffff, 0x808080));
            gameStatus.addChild(_score = ImageFactory.createScoreText(133, 0, 50, 25, "0", 14, 0xffffff));
            gameStatus.addChild(ImageFactory.createBorderedText(197, 0, 40, 25, "Lives :", 12, 0xffffff, 0xf00000));
            gameStatus.addChild(_lives = ImageFactory.createScoreText(237, 0, 20, 25, "0", 14, 0xff0000));
            gameStatus.addChild(ImageFactory.createBorderedText(370, 0, 35, 25, "$ :", 12, 0xffffff, 0xb0b000));
            gameStatus.addChild(_gold = ImageFactory.createScoreText(406, 0, 45, 25, "0", 14, 0xffff00));
            return gameStatus;
        }
        
        // 選択キャンセルボタンを作成する
        private function createCancelButton(posx:int, posy:int):Sprite {
            var cancel:Sprite = new Sprite();
            cancel.x = posx;
            cancel.y = posy;
            cancel.addChild(new Bitmap(ImageFactory.getImage("Cancel")));
            cancel.buttonMode = true;
            cancel.addEventListener(MouseEvent.CLICK, isSelectedCancelButton);
            return cancel;
        }
        private function isSelectedCancelButton(e:MouseEvent = null):void { GameData.instance.selectedTower = null; }
        //カラートランスフォームで「明るい(値のまま)」と「暗くする(値半減)」を定義【F】
        private static const LIGHTEN:ColorTransform = new ColorTransform();
        private static const DARKEN:ColorTransform = new ColorTransform(0.5, 0.5, 0.5);
        
        public function onUpdateGameStatus(e:Event):void {
            var data:GameData = GameData.instance;            
            _wave.text = data.wave.toString();
            _score.text = data.score.toString();
            _lives.text = data.lives.toString();
            _gold.text = data.gold.toString();
            
            // タワーが購入できるかどうかで、タワー選択ボタンに明暗をつける
            for (var i:int = 0; i < _buttons.numChildren; i++) {
                var button:Tower = _buttons.getChildAt(i) as Tower;
                button.transform.colorTransform = ((button.type.getStatus(button.level).cost <= data.gold) ? LIGHTEN: DARKEN);
            }
            
            // アップグレードボタンの有効/無効を反映させる
            if (_towerStatus.visible) { _towerStatus.updateUpgradeButton(); }
        }
        
        private static const NON_GLOW:Array = [];
        private static const GLOW:Array = [new GlowFilter(0xffff00, 1, 8, 8)];
        
        public function onUpdateSelectedTower(e:Event):void {
            var selectedTower:Tower = GameData.instance.selectedTower;
            
            // タワー選択ボタンのハイライトを解除する
            for (var i:int = 0; i < _buttons.numChildren; i++) {
                _buttons.getChildAt(i).filters = NON_GLOW;
            }
            
            if (selectedTower != null) {
                _buttons.removeEventListener(MouseEvent.MOUSE_OVER, onMouseOverButton);
                _buttons.removeEventListener(MouseEvent.MOUSE_OUT, onMouseOutButton);
                
                _towerStatus.update(selectedTower);
                _towerStatus.visible = true;
                // 選択されたボタンにハイライトをつける
                if (!selectedTower.active) { selectedTower.filters = GLOW; }
            }else {
                _buttons.addEventListener(MouseEvent.MOUSE_OVER, onMouseOverButton);
                _buttons.addEventListener(MouseEvent.MOUSE_OUT, onMouseOutButton);
                _towerStatus.visible = false;
            }
        }
        
        // タワー非選択時、選択ボタンにマウスオーバーでステータスを表示するようにする
        private function onMouseOverButton(e:MouseEvent):void {
            _towerStatus.update(Tower(e.target));
            _towerStatus.visible = true;
        }
        private function onMouseOutButton(e:MouseEvent):void {
            _towerStatus.visible = false;
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * TowerStatusWindow タワーステータスウィンドウ
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import com.bit101.components.PushButton;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.ui.Keyboard;
    
    //public 
    class TowerStatusWindow extends Sprite {
        private var _towerName:TextField;
        //シンボルスプライトを追加【F】
        private var _synbolKinds:Array = ["groundSynbol","airSynbol","slowSynbol","venomSynbol"];
        private var _synbolWalking:Sprite;
        private var _synbolFlying:Sprite;
        private var _synbolSlow:Sprite;
        private var _synbolVenom:Sprite;

        private var _synbolMarks:Array = ["gradeSynbol","damageSynbol","rangeSynbol","reloadSynbol"];
        private var _level:TextField;  private var _levelAdd:TextField;
        private var _cost:TextField;  private var _costAdd:int;
        private var _sell:TextField;
        private var _damage:TextField;  private var _damageAdd:TextField;
        private var _range:TextField;  private var _rangeAdd:TextField;
        private var _firerate:TextField;  private var _firerateAdd:TextField;
                
        private var _upgradeButton:PushButton;
        private var _sellButton:PushButton;
        
        
        private static const LIGHTEN:uint = 0xffffff;
        private static const DARKEN:uint = 0x606060;

        
        public function TowerStatusWindow(posx:int, posy:int):void {
            x = posx;
            y = posy;
            addChild(ImageFactory.createWindow(0, 0, 90, 190));
            addChild(ImageFactory.createWindow(0, 0, 90, 20));
            //ImageFactoryで定義したSimpleテキストで文字を作成【F】
            addChild(_towerName = ImageFactory.createSimpleText(0, 0, 90, 20, "Tower", 12, 0xffffff));
            
            
            //タワー属性のシンボルを配置【F】
            //シンボルつくって設置。表示更新時にタワーの引数にあわせて見えるor見えない【F】
            _synbolWalking = addChild(createSynbol(5,25,0)) as Sprite;
            _synbolFlying = addChild(createSynbol(25,25,1)) as Sprite;
            _synbolSlow = addChild(createSynbol(45,25,2)) as Sprite;
            _synbolVenom = addChild(createSynbol(65,25,3)) as Sprite;

            //ステータスのシンボルとステータス文字を配置【F】            
            //左にシンボル、右に数字を配置。Upgrade情報は別のフィールドで色を変えて配置。【F】
            addChild(createStatusSynbol(5,45,0));  //レベル 
            addChild(_level = ImageFactory.createStatusText(3, 45, 60, 15, "E", 12, 0xffffff));
            addChild(_levelAdd = ImageFactory.createStatusText(32, 40, 60, 15, "", 10, 0x22aa22));            
            addChild(createStatusSynbol(5,70,1));  //攻撃力 (上のアイコンとの高さの差25)
            addChild(_damage = ImageFactory.createStatusText(3, 70, 60, 15, "0", 12, 0xffffff));
            addChild(_damageAdd = ImageFactory.createStatusText(32, 65, 60, 15, "", 10, 0x22aa22));
            addChild(createStatusSynbol(5,95,2));  //範囲
            addChild(_range = ImageFactory.createStatusText(3, 95, 60, 15, "0", 12, 0xffffff));
            addChild(_rangeAdd = ImageFactory.createStatusText(32, 90, 60, 15, "", 10, 0x22aa22));
            addChild(createStatusSynbol(5,120,3));  //装填速度 
            addChild(_firerate = ImageFactory.createStatusText(3, 120, 60, 15, "0", 12, 0xffffff));
            addChild(_firerateAdd = ImageFactory.createStatusText(32, 115, 60, 15, "", 10, 0x22aa22));
            //コスト
            _upgradeButton = new PushButton(this, 5, 145, " ", upgradeSelectedTower);
            addChild(_cost = ImageFactory.createStatusText(5, 146, 80, 15, " ", 10, 0x505050));
            _sellButton = new PushButton(this, 5, 166, "", sellSelectedTower);
            addChild(_sell = ImageFactory.createStatusText(5, 167, 80, 15, " ", 10, 0x505050));
            _upgradeButton.width = _sellButton.width = 80;
            
            // 各ボタンに対応するホットキーを設定する
            HotKey.bind(Keyboard.U, upgradeSelectedTower);
            HotKey.bind(Keyboard.S, sellSelectedTower);
        }
        
        //タワー属性のシンボルマークを設置するファンクション【F】       
        private function createSynbol(posx:int,posy:int,arrayNum:int):Sprite{
            var Synbol:Sprite = new Sprite();
            Synbol.x = posx ; Synbol.y = posy ; 
            Synbol.addChild(new Bitmap(ImageFactory.getImage(_synbolKinds[arrayNum])));
            Synbol.visible = true;
            return Synbol;
        }        
        //ステータスのシンボルマークを設置するファンクション【F】
        private function createStatusSynbol(posx:int,posy:int,arrayNum:int):Sprite{
            var Synbol:Sprite = new Sprite();
            Synbol.x = posx ; Synbol.y = posy ; 
            Synbol.addChild(new Bitmap(ImageFactory.getImage(_synbolMarks[arrayNum])));
            return Synbol;
        }

        private function upgradeSelectedTower(e:MouseEvent = null):void {
            var selectedTower:Tower = GameData.instance.selectedTower;
            if (selectedTower != null && selectedTower.active) {
                selectedTower.upgrade();
            }
        }
        
        private function sellSelectedTower(e:MouseEvent = null):void {
            var selectedTower:Tower = GameData.instance.selectedTower;
            if (selectedTower != null && selectedTower.active) {
                selectedTower.sell();
            }
        }
        
       
        // 引数で与えたタワーのステータス表示に更新する
        public function update(tower:Tower):void {
            var type:TowerType = tower.type;
            
            var status:TowerStatus = type.getStatus(tower.level);
            _level.text = tower.level.toString();
            _cost.text = status.cost.toString();
            _damage.text = status.damage.toString();
            _range.text = status.range.toString();
            _firerate.text = status.firerate.toFixed(1);
            _levelAdd.text = _damageAdd.text = _rangeAdd.text = _firerateAdd.text = _cost.text = _sell.text = "" ;            

            //_towerName.text = type.name + " Tower";
            _towerName.text = type.name + "  ($"+ status.cost.toString()+ ")" ;

            //シンボルの表示visible = タイプ関数の真偽【F】
            _synbolWalking.visible = type.ground;
            _synbolFlying.visible = type.air;
            _synbolSlow.visible = (type.slow > 0);
            _synbolVenom.visible = (type.venom > 0);

            // タワーが選択ボタンのものならボタンを隠して、処理を終える
            if (!tower.active) {
                _upgradeButton.visible = _sellButton.visible = false;
                return;
            }            
            // アップグレード可能か、アップグレード時の上昇値はいくつかを表示に反映させる
            _upgradeButton.visible = _sellButton.visible = true;           
            updateUpgradeButton();
            if (type.hasStatus(tower.level + 1)) {
                var nextStatus:TowerStatus = type.getStatus(tower.level + 1);
                _levelAdd.text = (" → " + nextStatus.level.toString());
                _costAdd = nextStatus.cost - status.cost;
            
                //レベルとコスト表示【F】
                _cost.text = ( "Lv" + nextStatus.level.toString() + " [" + _costAdd.toString() + "]"); 
                if (nextStatus.damage - status.damage > 0) { 
                _damageAdd.text = (" → " + nextStatus.damage.toString()); }
                if (nextStatus.range - status.range > 0) { _rangeAdd.text = (" → " + nextStatus.range.toString()); }
                if (nextStatus.firerate - status.firerate > 0) { _firerateAdd.text = (" → " + nextStatus.firerate.toFixed(1)); }
                else if (nextStatus.firerate - status.firerate < 0) { _firerateAdd.text = (" → " + nextStatus.firerate.toFixed(1)); }
            }
            var _sellValue:int = status.cost * GameData.instance.sellingRatio;
            _sell.text = ( "Sell [" + _sellValue.toString() + "]" );
        }
        
        public function updateUpgradeButton():void {
            var selectedTower:Tower = GameData.instance.selectedTower;
            if (selectedTower == null || !selectedTower.active || !selectedTower.type.hasStatus(selectedTower.level + 1)) {
                _upgradeButton.enabled = false;
                return;
            }
            var upgradeCost:int = selectedTower.type.getStatus(selectedTower.level + 1).cost - selectedTower.type.getStatus(selectedTower.level).cost;
            _upgradeButton.enabled = (GameData.instance.gold >= upgradeCost) ? true : false;
            
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * WaveManager
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.geom.Rectangle;
    
    //public 
    class WaveManager extends Sprite {
        private var _currentWave:int;
        private var _waves:Vector.<Wave>;
        private var _onScreen:BitmapData;
        private var _offScreen:Sprite;
        private var _offScreenPosX:int;
        private var _nextWaveCount:int;
        private var _countDownText:TextField;
        private var _countDown:int;
        
        public function finished():Boolean { return _currentWave == _waves.length; }
        
        public function WaveManager(posx:int, posy:int, world:World) {
            x = posx;
            y = posy;
            
            _waves = Config.getWaves();
            _offScreen = new Sprite();
            for (var i:int = 0; i < _waves.length; i++) {
                var wave:Wave = _waves[i];
                wave.x = i * Const.WAVE_WIDTH;
                wave.setWorld(world);
                _offScreen.addChild(wave);
            }
            createWaveManagementWindow();
            initialize();
        }
        
        public function initialize():void {
            _currentWave = 0;
            _offScreenPosX = 301;
            _offScreen.x = _offScreenPosX / 10;
            updateOnScreen();
            _nextWaveCount = 1;
            
            for (var i:int = 0; i < _waves.length; i++) {
                _waves[i].initialize();
            }
        }
        
        private function updateOnScreen():void {
            _onScreen.fillRect(ONSCREEN_RECT, 0x000000);
            _onScreen.draw(_offScreen, _offScreen.transform.matrix);
        }
        
        private function createWaveManagementWindow():void {
            var window:Sprite = addChild(ImageFactory.createWindow(-10, 0, 475, 50)) as Sprite;
            _onScreen = new BitmapData(365, 30, false, 0x000000);
            var bitmap:Bitmap = window.addChild(new Bitmap(_onScreen)) as Bitmap;
            bitmap.x = bitmap.y = 10;
            
            var line:Sprite = window.addChild(new Sprite()) as Sprite;
            line.graphics.lineStyle(1, 0xffff00);
            line.graphics.moveTo(40, 2);
            line.graphics.lineTo(40, 48);

            _countDown = 0 ;
            addChild(ImageFactory.createSimpleText(19,30, 100, 15, "Send Bonus", 10, 0xffffff));
            addChild(_countDownText = ImageFactory.createStatusTextRight(75, 30, 80, 15, _countDown.toString(), 10, 0xffffff));
        }
        
        private static const ONSCREEN_RECT:Rectangle = new Rectangle(0, 0, 365, 30);
        
        public function update():void {
            _offScreenPosX--;
            if (_offScreenPosX % 10 == 0) { _offScreen.x = _offScreenPosX / 10; }
            updateOnScreen();
            
            _nextWaveCount--;
            _countDown = int(_nextWaveCount / Const.WAVE_INTERVAL * 10) ;
            
            if (_currentWave == _waves.length) { 
                _countDownText.text = "0" ;
            } else { _countDownText.text = "$ "  + _countDown.toString() + " × "  + (int(_currentWave / 5) +1) ; }
            if (_nextWaveCount == 0) {
                sendNextWave();
            }

            
            for (var i:int = 0; i < _waves.length; i++) {
                _waves[i].update();
            }
        }
        
        public function sendNextWave():void {
            // 全てのWaveが送出されていたら何もせずに終了する
            if (_currentWave == _waves.length) { return; }
            
            _currentWave++;
            GameData.instance.wave = _currentWave;
            _waves[_currentWave - 1].send();
            
            // 先送りしていたら、その分をスコアに加算する
            GameData.instance.score += int(_nextWaveCount / 10);
            // 先送りしていたら、センドボーナスのお金を追加する
            _countDown = int(_nextWaveCount / Const.WAVE_INTERVAL * 10) ;
            GameData.instance.gold += _countDown * (int((_currentWave - 1)/5) +1);
            if((_countDown * (int((_currentWave - 1)/5) +1)) > 0 ) {addChild(new Coin(36,40))};
            
            _offScreenPosX -= _nextWaveCount;
            _offScreen.x = _offScreenPosX / 10;
            updateOnScreen();
            _nextWaveCount = Const.WAVE_INTERVAL;
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * Wave ウェイブの処理とバーグラフィックなど
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.Sprite;
    import flash.utils.Dictionary;
    import flash.display.GradientType;
    
    //public 
    class Wave extends Sprite {
        private var _world:World;
        private var _number:int;            // Wave数
        
        private var _enemyType:EnemyType;    // 敵のタイプ
        private var _enemyHP:int;            // 敵のHP
        private var _enemyPoint:int;        // 敵を倒した時のポイント
        private var _enemyMoney:int;        // 敵を倒した時の入手金
        private var _enemyNum:Vector.<int>;    // 出現する敵の数
        
        private var _isActivated:Boolean;        // 送出中かどうか
        private var _allEnemiesSent:Boolean;     // 全ての敵が送出されたかどうか
        private var _spawnInterval:int;            // 敵の出現間隔
        private var _spawnCount:int;            // 出現カウント
        private var _waitingNum:Vector.<int>;    // 待機中の敵の数
        
        
        public function setWorld(value:World):void { _world = value; }
        
        public function Wave(number:int, type:EnemyType, HP:int, point:int, money:int, numSpawning:Vector.<int>) {
            _number = number
            _enemyType = type;
            _enemyHP = HP;
            _enemyPoint = point;
            _enemyMoney = money;
            _enemyNum = numSpawning;
            
            initialize();
            var max:int = 0;
            for (var i:int = 0; i < _enemyNum.length; i++) {
                if (_enemyNum[i] > max) { max = _enemyNum[i]; }
            }
            _spawnInterval = int((Const.WAVE_INTERVAL / 4) / max);
            _spawnCount = 0;
            _waitingNum = new Vector.<int>(_enemyNum.length);
            
            draw();
        }
        
        public function initialize():void {
            _isActivated = false;
            _allEnemiesSent = false;
        }
        // ウェイブバーを描く (出現する敵の種類によって色を設定)
        private function draw():void {
            var bodyColor:uint, borderColor:uint;
            switch(_enemyType.name) { //bodyColor 数字以外の部分 borderColorは数字などの部分
                case "Immune": { bodyColor = 0xccaaee; borderColor = 0x664488; break; }
                case "Fast":   { bodyColor = 0x99aaff; borderColor = 0x6688dd; break; }
                case "Flying": { bodyColor = 0xffdd00; borderColor = 0xddaa00; break; }
                case "Swarm": { bodyColor = 0xaaaa88; borderColor = 0x888866; break; }
                case "Zombie": { bodyColor = 0x55ddff; borderColor = 0x00aacc; break; }
                case "Fade": { bodyColor = 0xcccccc; borderColor = 0x999999; break; }
                case "Split": { bodyColor = 0x55cc88; borderColor = 0x053305; break; }
                case "Fury": { bodyColor = 0xff3333; borderColor = 0xdd0000; break; }
                case "Shell": { bodyColor = 0xaaaa44; borderColor = 0x444422; break; }
                case "Fupa": { bodyColor = 0xffccaa; borderColor = 0xccaa77; break; }
                case "Ghost": { bodyColor = 0xffeeaa; borderColor = 0xbbbbbb; break; }
                case "Detour": { bodyColor = 0xffee22; borderColor = 0xccaa00; break; }
                case "Decoyer": { bodyColor = 0xff99bb; borderColor = 0x773399; break; }
                case "Wall": { bodyColor = 0xccbbcc; borderColor = 0x443344; break; }
                default:       { bodyColor = 0x88aa88; borderColor = 0x669966; break; }
            }


            graphics.lineStyle(1, borderColor);
            graphics.beginGradientFill(GradientType.LINEAR, [0x050505 , bodyColor ] , [100, 35] , [20 ,255]);
            graphics.drawRect(0.5, 0, Const.WAVE_WIDTH - 1, 20);
            graphics.endFill();
            
            addChild(ImageFactory.createStatusText(0, 0, Const.WAVE_WIDTH, 20, _number.toString(), 30, borderColor));
            addChild(ImageFactory.createBorderedText(0, 0, Const.WAVE_WIDTH, 20, _enemyType.name, 10, 0xffffff, borderColor));
            cacheAsBitmap = true;
        }
        
        // 敵の送出を開始する
        public function send():void {
            _isActivated = true;
            _spawnCount = 0;
            for (var i:int = 0; i < _enemyNum.length; i++) {
                _waitingNum[i] = _enemyNum[i];
            }
        }
        
        public function update():void {
            if (!_isActivated || _allEnemiesSent) { return; }
            
            // カウントを進める
            _spawnCount--;
            if (_spawnCount > 0) { return; }
            _spawnCount = _spawnInterval;
            
            // カウントが0になったら、敵を出現させる
            _allEnemiesSent = true;
            for (var i:int = 0; i < _waitingNum.length; i++) {
                if (_waitingNum[i] > 0) {
                    _waitingNum[i]--;
                    _allEnemiesSent = false;
                    
                    var enemy:Enemy = new Enemy(_world.getStartingPos(i), _enemyType, _enemyHP, _enemyPoint, _enemyMoney, _world , false);                    
                    _world.addEnemy(enemy);
                }
            }
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * GameData
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.events.Event;
    import flash.events.EventDispatcher;
    
    //public 
    class GameData extends EventDispatcher {
        private var _wave:int;
        private var _score:int;
        private var _lives:int;
        private var _gold:int;
        private var _selectedTower:Tower;
        private var _sellingRatio:Number;
        
        public function get wave():int { return _wave; }
        public function get score():int { return _score; }
        public function get lives():int { return _lives; }
        public function get gold():int { return _gold; }
        public function get selectedTower():Tower { return _selectedTower; }
        public function get sellingRatio():Number { return _sellingRatio; }
        
        public function set wave(value:int):void { _wave = value; dispatchEvent(new Event(Const.EVENT_CHANGE_GAMESTATUS)); }
        public function set score(value:int):void { _score = value; dispatchEvent(new Event(Const.EVENT_CHANGE_GAMESTATUS)); }
        public function set lives(value:int):void { _lives = Math.max(0, value); dispatchEvent(new Event(Const.EVENT_CHANGE_GAMESTATUS)); }
        public function set gold(value:int):void { _gold = value; dispatchEvent(new Event(Const.EVENT_CHANGE_GAMESTATUS)); }
        public function set selectedTower(value:Tower):void { _selectedTower = value; dispatchEvent(new Event(Const.EVENT_CHANGE_SELECTEDTOWER)); }
        public function set sellingRatio(value:Number):void { _sellingRatio = value; }
        
        //----------------------------------------

        private static var _instance:GameData = null;
        public static function get instance():GameData {
            if (GameData._instance == null) { _instance = new GameData(new SingletonEnforcer()); }
            return _instance;
        }
        public function GameData(enforcer:SingletonEnforcer) { initialize(); }
        
        public function initialize():void {
            _wave = 0;
            _score = 0;
            _lives = Config.INITIAL_LIVES;
            _gold = Config.INITIAL_GOLD;
            _selectedTower = null;
            _sellingRatio = 1;
            
            dispatchEvent(new Event(Const.EVENT_CHANGE_GAMESTATUS));
            dispatchEvent(new Event(Const.EVENT_CHANGE_SELECTEDTOWER));
        }
    }
//}
internal class SingletonEnforcer { }
/* ----------------------------------------------------------------------------------------------------------------------
 * Const
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    //public 
    class Const {
        public static const FRAME_RATE:int = 30;    // フレームレート
        public static const NODE_SIZE:int = 16;        // ノードの大きさ
        public static const NODE_COLS:int = 24;        // ノードの列数
        public static const NODE_ROWS:int = 26;        // ノードの行数
        public static const TOWER_SIZE:int = 32;    // タワーの大きさ
        public static const BULLET_SIZE:int = 8;    // 弾の大きさ
        public static const ENEMY_SIZE:int = 16;    // 敵の大きさ
        
        public static const SLOWING_DURATION:int = 5 * Const.FRAME_RATE;
        public static const VENOMING_DURATION:int = 1 * Const.FRAME_RATE;

        public static const WAVE_INTERVAL:int = 20 * Const.FRAME_RATE;
        public static const WAVE_WIDTH:int = int(WAVE_INTERVAL / 10);
        public static const CURSOR_OFFSET:int = Const.NODE_SIZE / 2;
        
        public static const EVENT_CHANGE_GAMESTATUS:String = "change_gamestatus";
        public static const EVENT_CHANGE_SELECTEDTOWER:String = "change_selectedtower";
        
        //availableFonts["Aqua","Azuki","Cinecaption","Mona","Sazanami","YSHandy","VLGothic","IPAGP","IPAM","UmeUgo","UmePms","Bebas"]
        public static const EMBED_FONT:String = "IPAGP";
        public static const USE_FONTLOADER:Boolean = true;
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * HotKey
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.Stage;
    import flash.events.KeyboardEvent;
    
    //public 
    class HotKey {
        private static var _keymap:Vector.<Function> = new Vector.<Function>(256, true);
        private static var _stage:Stage;
        
        public static function setStage(value:Stage):void { HotKey._stage = value; }
        public static function enable():void { HotKey._stage.addEventListener(KeyboardEvent.KEY_DOWN, HotKey.onKeyDown); _stage.focus = null; }
        public static function disable():void { HotKey._stage.removeEventListener(KeyboardEvent.KEY_DOWN, HotKey.onKeyDown); }
        
        // 押したキーに処理が割り当てられていたら、それを実行する
        private static function onKeyDown(e:KeyboardEvent):void {
            var command:Function = HotKey._keymap[e.keyCode];
            if (command != null) { command(); }    // command.execute
            _stage.focus = null;
        }
        
        // keyCodeに対応するキーに、commandで指定した処理を割り当てる
        public static function bind(keyCode:uint, command:Function):void {
            HotKey._keymap[keyCode] = command;
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * Preloader
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import com.bit101.components.ProgressBar;
    import flash.display.DisplayObjectContainer;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.utils.Dictionary;
    import net.wonderfl.utils.FontLoader;
    
    //public 
    class Preloader extends EventDispatcher {
        private var _assetsNum:int;                // 読み込むアセットの数
        private var _loadedNum:int;                // 読み込み完了したアセットの数
        private var _progressBar:ProgressBar;    // プログレスバー
        
        private var _imageLoaders:Dictionary;    // 画像のローダを保持する連想配列
        private var refImageHolder:Dictionary;    // 画像を保持する連想配列の参照
        
        public function Preloader(parentOfProgressBar:DisplayObjectContainer, imagePaths:Dictionary, imageHolder:Dictionary) {
            _assetsNum = _loadedNum = 0;
            _progressBar = new ProgressBar(parentOfProgressBar, 182, 227);
            
            startLoadingImages(imagePaths, imageHolder);
            if (Const.USE_FONTLOADER) { startLoadingFont(); }
            
            _progressBar.maximum = _assetsNum;
        }
        
        // 外部画像の読み込みを開始する
        private function startLoadingImages(imagePaths:Dictionary, imageHolder:Dictionary):void {
            _imageLoaders = new Dictionary();
            refImageHolder = imageHolder;
            
            for (var imageName:String in imagePaths) {
                _assetsNum++;
                var imageLoader:ExternalImageLoader = new ExternalImageLoader();
                _imageLoaders[imageName] = imageLoader;
                imageLoader.addEventListener(Event.COMPLETE, assetLoaded);
                imageLoader.load(imagePaths[imageName]);
            }
        }
        
        // フォントの読み込みを開始する
        private function startLoadingFont():void {
            _assetsNum++;
            
            var fontLoader:FontLoader = new FontLoader();
            fontLoader.addEventListener(Event.COMPLETE, assetLoaded);
            fontLoader.load(Const.EMBED_FONT);
        }
        
        // 一つのアセットの読み込みが完了した際に呼ばれるメソッド
        private function assetLoaded(e:Event):void {
            e.target.removeEventListener(Event.COMPLETE, assetLoaded);
            
            _loadedNum++;
            _progressBar.value = _loadedNum;
            checkLoadComplete();
        }
        
        // 読み込んだアセット数を調べ、全て読み込んでいたら完了イベントを通知する
        private function checkLoadComplete():void {
            if (_loadedNum == _assetsNum) {
                for (var imageName:String in _imageLoaders) {
                    refImageHolder[imageName] = _imageLoaders[imageName].content;
                }
                
                _progressBar.parent.removeChild(_progressBar);
                dispatchEvent(new Event(Event.COMPLETE));
            }
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * ExternalImageLoader
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    
    //public 
    class ExternalImageLoader extends EventDispatcher {
        private var _content:BitmapData;
        private var _tempA:Loader;
        private var _tempB:Loader;
        
        public function get content():BitmapData { return _content; }
        
        public function ExternalImageLoader() {
            _content = null; _tempA = new Loader(); _tempB = new Loader();
        }
        
        public function load(url:String):void {
            _tempA.contentLoaderInfo.addEventListener(Event.INIT, tempALoaded);
            _tempA.load(new URLRequest(url), new LoaderContext(true));
        }
        
        private function tempALoaded(e:Event):void {
            _tempA.contentLoaderInfo.removeEventListener(Event.INIT, tempALoaded);
            _content = new BitmapData(int(_tempA.width), int(_tempA.height), true, 0x00ffffff);
            _tempB.contentLoaderInfo.addEventListener(Event.INIT, tempBLoaded);
            _tempB.loadBytes(_tempA.contentLoaderInfo.bytes);
        }
        
        private function tempBLoaded(e:Event):void {
            _tempB.contentLoaderInfo.removeEventListener(Event.INIT, tempBLoaded);
            _content.draw(_tempB); _tempA.unload(); _tempB.unload();
            dispatchEvent(new Event(Event.COMPLETE));
        }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * TileBasedPoint
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    //public 
    class TileBasedPoint {
        private static const TILE_SIZE:int = Const.NODE_SIZE;
        private static const TILE_COLS:int = Const.NODE_COLS;
        private static const TILE_ROWS:int = Const.NODE_ROWS;
        
        // ワールド座標
        private var _worldX:Number;
        private var _worldY:Number;
        // タイル座標
        private var _tileX:int;
        private var _tileY:int;
        
        private var _isInvalidWorldPos:Boolean;    // ワールド座標値を更新する必要があるかどうか
        private var _isInvalidTilePos:Boolean;    // タイル座標値を更新する必要があるかどうか
        
        // Creation Method でインスタンスを生成する
        public static function createFromWorldPos(x:Number, y:Number):TileBasedPoint { return new TileBasedPoint(true, x, y, 0, 0); }
        public static function createFromTilePos(x:int, y:int):TileBasedPoint { return new TileBasedPoint(false, 0, 0, x, y); }
        public function TileBasedPoint(isWorldPos:Boolean, worldx:Number, worldy:Number, tilex:int, tiley:int) {
            _worldX = worldx;
            _worldY = worldy;
            _tileX = tilex;
            _tileY = tiley;
            _isInvalidWorldPos = !isWorldPos;
            _isInvalidTilePos = isWorldPos;
        }
        
        private function updateWorldPos():void {
            _worldX = Math.max(0, Math.min(_tileX * TILE_SIZE, (TILE_COLS - 1) * TILE_SIZE));
            _worldY = Math.max(0, Math.min(_tileY * TILE_SIZE, (TILE_ROWS - 1) * TILE_SIZE));
        }
        
        private function updateTilePos():void {
            _tileX = Math.max(0, Math.min(int(_worldX / TILE_SIZE), TILE_COLS - 1));
            _tileY = Math.max(0, Math.min(int(_worldY / TILE_SIZE), TILE_ROWS - 1));
        }
        
        // ワールド座標を有効にする
        private function validateWorldPos():void {
            if (_isInvalidWorldPos) {
                updateWorldPos();
                _isInvalidWorldPos = false;
            }
        }
        
        // タイル座標を有効にする
        private function validateTilePos():void {
            if (_isInvalidTilePos) {
                updateTilePos();
                _isInvalidTilePos = false;
            }
        }
        
        public function get x():Number { validateWorldPos(); return _worldX; }
        public function get y():Number { validateWorldPos(); return _worldY; }
        public function get tileX():int { validateTilePos(); return _tileX; }
        public function get tileY():int { validateTilePos(); return _tileY; }
        
        public function set x(value:Number):void { validateWorldPos(); _worldX = value; _isInvalidTilePos = true; }
        public function set y(value:Number):void { validateWorldPos(); _worldY = value; _isInvalidTilePos = true; }
        public function setWorldPos(x:Number, y:Number):void { validateWorldPos(); _worldX = x; _worldY = y; _isInvalidTilePos = true; }
        public function set tileX(value:int):void { validateTilePos(); _tileX = value; _isInvalidWorldPos = true; }
        public function set tileY(value:int):void { validateTilePos(); _tileX = value; _isInvalidWorldPos = true; }
        public function setTilePos(x:int, y:int):void { validateTilePos(); _tileX = x; _tileY = y; _isInvalidWorldPos = true; }
    }
//}
/* ----------------------------------------------------------------------------------------------------------------------
 * ImageFactory
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.BitmapData;
    import flash.display.GradientType;
    import flash.display.Sprite;
    import flash.filters.BevelFilter;
    import flash.filters.GlowFilter;
    import flash.geom.Matrix;
    import flash.text.AntiAliasType;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
    import flash.utils.Dictionary;
    
    import flash.display.Bitmap;
    import flash.filters.ColorMatrixFilter;
    
    //public 
    class ImageFactory {
        private static var _images:Dictionary;    // 画像を保持する連想配列
        
        public static function getImage(imageName:String):BitmapData {
            return ImageFactory._images[imageName];
        }
        
        // 外部画像のパスをまとめた配列を取得する
        public static function getExternalImagePaths():Dictionary {
            var imagePaths:Dictionary = new Dictionary();
            imagePaths["World"] = "http://assets.wonderfl.net/images/related_images/2/2c/2c9f/2c9f8923cc3e44db37520f0cbdcda0965a2e3682";
            //imagePaths["World"] = "http://assets.wonderfl.net/images/related_images/f/f9/f957/f957053513e0cf8aeb4991f6d7c5ca4f708d2230";            
        return imagePaths;
        }


        // (内部で作成できる)画像の読み込みを行う
        public static function load():Dictionary {
            ImageFactory._images = new Dictionary();
            
            //タワーのグラフィック読み込みを追加【F】
            ImageFactory._images["Gun"] = ImageFactory.createGunTower();
            ImageFactory._images["Gatling"] = ImageFactory.createGatlingTower();
            ImageFactory._images["Venom"] = ImageFactory.createVenomTower();
            ImageFactory._images["Cannon"] = ImageFactory.createCannonTower();
            ImageFactory._images["Voltex"] = ImageFactory.createVoltexTower();
            ImageFactory._images["AntiFly"] = ImageFactory.createAntiFlyTower();
            ImageFactory._images["Base"] = ImageFactory.createTowerBase();
            ImageFactory._images["Circle"] = ImageFactory.createBase();
            ImageFactory._images["Cancel"] = ImageFactory.createCancelMark();

            //タワー属性のシンボルイメージ読み込みを追加【F】
            ImageFactory._images["groundSynbol"] = ImageFactory.createWalkingSynbol();
            ImageFactory._images["airSynbol"] = ImageFactory.createFlyingSynbol();
            ImageFactory._images["slowSynbol"] = ImageFactory.createSlowSynbol();
            ImageFactory._images["venomSynbol"] = ImageFactory.createVenomSynbol();
            ImageFactory._images["stealSynbol"] = ImageFactory.createStealSynbol();
            
            //ステータスのシンボルイメージの読み込みを追加【F】
            ImageFactory._images["gradeSynbol"] = ImageFactory.createLevelSynbol();
            ImageFactory._images["damageSynbol"] = ImageFactory.createDamageSynbol();
            ImageFactory._images["rangeSynbol"] = ImageFactory.createRangeSynbol();
            ImageFactory._images["reloadSynbol"] = ImageFactory.createReloadSynbol();


            //敵のイメージの読み込み【F】
            ImageFactory._images["Normal"] = ImageFactory.createNormalEnemy(0x669966, 0x99cc99);
            ImageFactory._images["Fast"] = ImageFactory.createFastEnemy(0x6688dd, 0x99aaff);
            ImageFactory._images["Immune"] = ImageFactory.createImmuneEnemy(0x664488, 0xaa88bb);
            ImageFactory._images["Flying"] = ImageFactory.createFlyingEnemy(0xddaa00, 0xffdd00);
            ImageFactory._images["Swarm"] = ImageFactory.createSwarmEnemy(0x888822, 0xcccc44);
            ImageFactory._images["Zombie"] = ImageFactory.createZombieEnemy(0x00aacc, 0x55ddff);
            ImageFactory._images["Fade"] = ImageFactory.createFadeEnemy(0x999999, 0xeeeeee);
            ImageFactory._images["Split"] = ImageFactory.createSplitEnemy(0x116611, 0x55cc88);
            ImageFactory._images["SplitChild"] = ImageFactory.createSplitChildEnemy(0x116611, 0x55cc88);
            ImageFactory._images["Fury"] = ImageFactory.createFuryEnemy(0xdd0000, 0xff3333);
            ImageFactory._images["Shell"] = ImageFactory.createShellOneEnemy(0x666622, 0x999944);
            ImageFactory._images["Shell-2"] = ImageFactory.createShellTwoEnemy(0x666622, 0x999944);
            ImageFactory._images["Shell-3"] = ImageFactory.createShellThreeEnemy(0x666622, 0x999944);
            ImageFactory._images["Fupa"] = ImageFactory.createFupaEnemy(0xaa9955, 0xffccaa);
            ImageFactory._images["FupaChild"] = ImageFactory.createFlyingEnemy(0xddaa22, 0xffdd22);
            ImageFactory._images["Ghost"] = ImageFactory.createGhostEnemy(0xbbbbbb, 0xffeeaa);
            ImageFactory._images["Detour"] = ImageFactory.createDetourRightEnemy(0xcc8800, 0x444444);
            ImageFactory._images["Detour-L"] = ImageFactory.createDetourLeftEnemy(0xcc8800, 0xffffff);             
            ImageFactory._images["Decoyer"] = ImageFactory.createDecoyerEnemy(0x773399, 0xff99bb);
            ImageFactory._images["Decoy-1"] = ImageFactory.createDecoyEnemy(0x773399, 0xff99bb);
            ImageFactory._images["Decoy-2"] = ImageFactory.createDecoyEnemy(0x773399, 0xff99bb);
            ImageFactory._images["Wall"] = ImageFactory.createWallEnemy(0x443344, 0xccbbcc);
            
            //ImageFactory._images["Bullet_Arrow"] = ImageFactory.createArrowBullet();
            ImageFactory._images["Bullet_Gatling"] = ImageFactory.createNormalBullet(2);
            ImageFactory._images["Bullet_Cannon"] = ImageFactory.createNormalBullet(3);
            //ImageFactory._images["Bullet_Missile"] = ImageFactory.createMissileBullet();
            ImageFactory._images["Bullet_Gun"] = ImageFactory.createNormalBullet(2);
            ImageFactory._images["Bullet_Voltex"] = ImageFactory.createNormalBullet(1);
            ImageFactory._images["Bullet_AntiFly"] = ImageFactory.createArrowBullet();            
            ImageFactory._images["Coin"] = ImageFactory.createCoin();
            
            return ImageFactory._images;
        }
        
        
        
        // タワーを設置する土台の画像を作成する
        private static function createTowerBase():BitmapData {            
            var bitmapData:BitmapData = new BitmapData(32, 32,true,0x00ffffff);
            var _base:Sprite = new Sprite;
            _base.graphics.moveTo(2,1);           
            _base = ImageFactory.drawingArray(_base,0x888888,0,0x888888,[0,0,2,30,32,32,30,2],[3,27,29,29,27,3,1,1]);
            _base.graphics.moveTo(0,27);          
            _base = ImageFactory.drawingArray(_base,0x888888,0,0x101010,[0,2,30,32,32,30,2,0],[29,32,32,29,27,29,29,27]);
            _base.graphics.endFill();
            _base.graphics.lineStyle(1,0xd0d0d0,1);
            bitmapData.draw(_base);
            return bitmapData;
        }
        // タワー描画時の土台
        private static function createBase():BitmapData {            
            var bitmapData:BitmapData = new BitmapData(32, 32,true,0x00ffffff);
            var _base:Sprite = new Sprite;
            _base.graphics.beginFill(0xcccccc);
            _base.graphics.drawCircle(16, 16, 10);
            _base.graphics.endFill();
            bitmapData.draw(_base);
            return bitmapData;
        }

        // 各種タワー描画-------------------------------------------------
        // ベーシックガン Gun
        private static function createGunTower():BitmapData{
            var bitmapData:BitmapData = new BitmapData(32, 32, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            var _towerColor:uint = 0x000000;           
            sprite = towerCircle(_towerColor); 
            sprite.graphics.moveTo(16,14)
            sprite = ImageFactory.drawingArray(sprite,_towerColor,0,_towerColor, [18,18,19,19,22,22,20,10,10,20,22,22,16,16], [14,18,18,14,14,12,10,10,22,22,20,18,18,14]);
            sprite.graphics.beginFill(_towerColor);
            sprite.graphics.drawRect(20,15,10,2);
            bitmapData.draw(sprite);
            return bitmapData;
        }


        // ガトリング Gatling
        private static function createGatlingTower():BitmapData{
            var bitmapData:BitmapData = new BitmapData(32, 32, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            var _towerColor:uint = 0x000000;           
            sprite = towerCircle(_towerColor); 
            sprite.graphics.moveTo(6, 6);
            sprite = ImageFactory.drawingArray (sprite, _towerColor, 0, _towerColor, 
                        [4, 4, 6, 6, 4, 4, 6, 6, 4, 4, 6,14,16,29,29,15,15,17,19,19,17,15,15,29,29,16,14, 6], 
                        [8,11,11,12,14,18,20,21,21,24,26,26,24,24,22,22,21,21,20,12,11,11,10,10, 8, 8, 6, 6]);
            sprite.graphics.beginFill(_towerColor);
            sprite.graphics.drawEllipse(5,8,10,16);
            bitmapData.draw(sprite);
            return bitmapData;
        }

        // ポイズン Venom
        private static function createVenomTower():BitmapData{
            var bitmapData:BitmapData = new BitmapData(32, 32, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            var _towerColor:uint = 0x000000;           
            sprite = towerCircle(_towerColor);
            sprite.graphics.moveTo(15,10)           
            sprite = ImageFactory.drawingArray (sprite,_towerColor,0,_towerColor, [11,13,13,11,15,19,30,30,19,15], [14,14,18,18,22,17,17,15,15,10]);
            sprite.graphics.beginFill(_towerColor);
            sprite.graphics.drawCircle(16,9,4);
            sprite.graphics.drawCircle(16,23,4);
            sprite.graphics.drawCircle(10,13,2);
            sprite.graphics.drawCircle(10,19,2);
            sprite.graphics.drawCircle(21,16,3);
            bitmapData.draw(sprite);
            return bitmapData;
        }

        // キャノン Cannon
        private static function createCannonTower():BitmapData{
            var bitmapData:BitmapData = new BitmapData(32, 32, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            var _towerColor:uint = 0x000000;           
            sprite = towerCircle(_towerColor); 
            sprite.graphics.moveTo(7,6);
            sprite = ImageFactory.drawingArray (sprite, _towerColor, 0, _towerColor, 
                            [6, 6, 8, 6, 6, 8, 6, 6, 7,17,19,19,16,12,30,30,12,12,19,19,17, 7], 
                            [8,10,10,12,20,22,22,24,26,26,24,22,22,20,20,12,12,10,10, 8, 6, 6]);            sprite.graphics.beginFill(_towerColor);
            sprite.graphics.drawCircle(14,16,7);
            bitmapData.draw(sprite);
            return bitmapData;
        }

        // アンチフライ AntiFly
        private static function createAntiFlyTower():BitmapData{
            var bitmapData:BitmapData = new BitmapData(32, 32, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            var _towerColor:uint = 0x000000;           
            sprite = towerCircle(_towerColor); 
            sprite.graphics.moveTo(14,8);           
            sprite = ImageFactory.drawingArray (sprite,_towerColor,0,_towerColor, [10,12,10,14,24,14], [14,16,18,24,16,8]);
            sprite.graphics.lineStyle(1.5,0x000000,1);
            sprite.graphics.endFill();
            sprite.graphics.moveTo(12,8); sprite.graphics.lineTo(9,13);
            sprite.graphics.moveTo(12,24); sprite.graphics.lineTo(9,19);           
            sprite.graphics.moveTo(28,8); 
            sprite.graphics.lineTo(22,2);sprite.graphics.lineTo(14,16);
            sprite.graphics.lineTo(22,30);sprite.graphics.lineTo(28,24);
            bitmapData.draw(sprite);
            return bitmapData;
        }

        // ボルテクス Votex
        private static function createVoltexTower():BitmapData{
            var bitmapData:BitmapData = new BitmapData(32, 32, true, 0x00ffffff);
            var sprite:Sprite = new Sprite(); 
            var _towerColor:uint = 0x000000;           
            sprite = towerCircle(_towerColor);          
            sprite.graphics.lineStyle(1,0x000000, 1, true);
            sprite.graphics.moveTo(12,7); sprite.graphics.lineTo(6,16); sprite.graphics.lineTo(12,25);
            sprite.graphics.lineTo(20,25); sprite.graphics.lineTo(26,16); sprite.graphics.lineTo(20,7);
            sprite.graphics.lineTo(12,7);
            sprite.graphics.lineStyle(0,0x000000, 0, true);
            sprite.graphics.beginFill(0x000000);
            sprite.graphics.drawCircle(16,16,4);
            sprite.graphics.endFill();
            sprite.graphics.beginFill(0x000000);
            sprite.graphics.moveTo(8,8);
            sprite.graphics.lineTo(12,12);sprite.graphics.lineTo(14,10);sprite.graphics.lineTo(11,4);sprite.graphics.lineTo(8,8);                      
            sprite.graphics.moveTo(4,13);
            sprite.graphics.lineTo(4,19);sprite.graphics.lineTo(10,18);sprite.graphics.lineTo(10,14);sprite.graphics.lineTo(4,13);
            sprite.graphics.moveTo(8,24);
            sprite.graphics.lineTo(11,28);sprite.graphics.lineTo(14,22);sprite.graphics.lineTo(12,20);sprite.graphics.lineTo(8,24);
            sprite.graphics.moveTo(21,28);
            sprite.graphics.lineTo(24,24);sprite.graphics.lineTo(20,20);sprite.graphics.lineTo(18,22);sprite.graphics.lineTo(21,28);
            sprite.graphics.moveTo(28,19);
            sprite.graphics.lineTo(28,13);sprite.graphics.lineTo(22,14);sprite.graphics.lineTo(22,18);sprite.graphics.lineTo(28,19);
            sprite.graphics.moveTo(24,8);
            sprite.graphics.lineTo(21,4);sprite.graphics.lineTo(18,10);sprite.graphics.lineTo(20,12);sprite.graphics.lineTo(24,8);
            sprite.graphics.endFill();
            bitmapData.draw(sprite);
            return bitmapData;
        }
        //-----------------------------------------------------
        //-----------------------------------------------------
        
                
        // キャンセルマークの画像を作成する
        private static function createCancelMark():BitmapData {
            var bitmapData:BitmapData = new BitmapData(32, 32, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(4, 0xff0000);
            sprite.graphics.drawCircle(16, 16, 12);
            sprite.graphics.moveTo(16 + (12 * Math.cos(9 * Math.PI / 8)), 16 + (12 * Math.sin(9 * Math.PI / 8)));
            sprite.graphics.lineTo(16 + (12 * Math.cos(Math.PI / 8)), 16 + (12 * Math.sin(Math.PI / 8)));
            bitmapData.draw(sprite);
            return bitmapData;
        }

        // ステータスウィンドウ用の画像を作成する【F】
        // 靴アイコン:地上の敵を攻撃【F】
        private static function createWalkingSynbol():BitmapData{
            var bitmapData:BitmapData = new BitmapData(12, 12, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(0, 0x000000, 0, true);
            sprite.graphics.beginFill(0xb0b0b0)
            sprite.graphics.moveTo(6,2);
            sprite.graphics.lineTo(12,2);
            sprite.graphics.lineTo(12,11);
            sprite.graphics.lineTo(3,11);
            sprite.graphics.curveTo(0,7,6,6);
            sprite.graphics.lineTo(6,2);
            bitmapData.draw(sprite);
            return bitmapData;
        }
       // 羽アイコン:空中の敵を攻撃【F】
        private static function createFlyingSynbol():BitmapData{
            var bitmapData:BitmapData = new BitmapData(12, 12, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(0, 0x000000, 0, true);
            sprite.graphics.beginFill(0xb0b0b0)
            sprite.graphics.moveTo(8,2);
            sprite.graphics.lineTo(11,2);
            sprite.graphics.curveTo(15,2.5,8,5);
            sprite.graphics.curveTo(12,5.5,6,7);
            sprite.graphics.curveTo(10,8,4,9);
            sprite.graphics.curveTo(3,9.8,3,12);
            sprite.graphics.lineTo(2,11);
            sprite.graphics.curveTo(2,2.5,8,2);
            bitmapData.draw(sprite);
            return bitmapData;
        }        
       // スロウアイコン:減速効果【F】
        private static function createSlowSynbol():BitmapData{
            var bitmapData:BitmapData = new BitmapData(12, 12, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(1.4, 0xffffff, 1, true);
            sprite.graphics.endFill();
            sprite.graphics.moveTo(4,1) ; 
            sprite.graphics.lineTo(2,3) ; sprite.graphics.lineTo(4,5) ; sprite.graphics.lineTo(2,7) ; sprite.graphics.lineTo(4,9) ; sprite.graphics.lineTo(2,11) ;
            sprite.graphics.moveTo(7,1) ; 
            sprite.graphics.lineTo(5,3) ; sprite.graphics.lineTo(7,5) ; sprite.graphics.lineTo(5,7) ; sprite.graphics.lineTo(7,9) ; sprite.graphics.lineTo(5,11) ;
            sprite.graphics.moveTo(10,1) ; 
            sprite.graphics.lineTo(8,3) ; sprite.graphics.lineTo(10,5) ; sprite.graphics.lineTo(8,7) ; sprite.graphics.lineTo(10,9) ; sprite.graphics.lineTo(8,11) ;
            bitmapData.draw(sprite);
            return bitmapData;
        }
       // ベノムアイコン:毒液効果【F】
        private static function createVenomSynbol():BitmapData{
            var bitmapData:BitmapData = new BitmapData(12,12, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(0, 0x000000, 0, true);
            sprite.graphics.beginFill(0xb0b0b0);
            sprite.graphics.moveTo(9,9);           
            sprite = drawingArray( sprite, 0xb0b0b0, 0, 0xb0b0b0, [7,7,5,5,3], [6,0,0,6,9]);
            sprite.graphics.curveTo(0,12,5,12); sprite.graphics.lineTo(7,12); sprite.graphics.curveTo(12,12,9,9);
            bitmapData.draw(sprite);
            return bitmapData;
        }
       // スティールアイコン:窃盗効果【F】
        private static function createStealSynbol():BitmapData{
            var bitmapData:BitmapData = new BitmapData(12, 12, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(0, 0x000000, 0, true);
            sprite.graphics.beginFill(0xb0b0b0);
            sprite.graphics.drawEllipse( 3, 1, 6, 10);
            sprite.graphics.endFill();
            sprite.graphics.lineStyle(1, 0x000000, 1, true);
            sprite.graphics.drawEllipse(4.5, 3, 3, 6);
            bitmapData.draw(sprite);
            return bitmapData;
        }


       //レベルアイコン:タワーレベル【F】
        private static function createLevelSynbol():BitmapData{
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(0, 0x000000, 0, true);
            sprite.graphics.beginFill(0xffffff);
            sprite.graphics.moveTo(4, 4); sprite.graphics.lineTo(6, 4); sprite.graphics.lineTo(6, 10); sprite.graphics.lineTo(8, 10);
            sprite.graphics.lineTo(8, 12); sprite.graphics.lineTo(4, 12); sprite.graphics.lineTo(4, 4);
            sprite.graphics.moveTo(8, 6); sprite.graphics.lineTo(9, 6); sprite.graphics.lineTo(10, 10); sprite.graphics.lineTo(11, 6);
            sprite.graphics.lineTo(12, 6); sprite.graphics.lineTo(11, 12); sprite.graphics.lineTo(9, 12); sprite.graphics.lineTo(8, 6);
            bitmapData.draw(sprite);
            return bitmapData;
        }

       //剣アイコン:攻撃力【F】
        private static function createDamageSynbol():BitmapData{
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(0, 0x000000, 0, true);
            sprite.graphics.beginFill(0xffffff);
            sprite.graphics.moveTo(4, 11); sprite.graphics.lineTo(10, 4); sprite.graphics.lineTo(12, 4); sprite.graphics.lineTo(12, 6); sprite.graphics.lineTo(5, 12); 
            sprite.graphics.endFill();sprite.graphics.beginFill(0xffffff);
            sprite.graphics.moveTo(4, 7); sprite.graphics.lineTo(5, 6); sprite.graphics.lineTo(10, 11); sprite.graphics.lineTo(9, 12); sprite.graphics.lineTo(4, 7);
            bitmapData.draw(sprite);
            return bitmapData;
        }
       //波紋アイコン:攻撃範囲【F】
        private static function createRangeSynbol():BitmapData{
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(2,0xffffff);
            sprite.graphics.drawCircle(8,8,4.6);sprite.graphics.drawCircle(8,8,1.8);
            bitmapData.draw(sprite);
            return bitmapData;
        }
       //連射アイコン:装填速度【F】
        private static function createReloadSynbol():BitmapData{
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(2,0xffffff);
            sprite.graphics.moveTo(4,6); sprite.graphics.lineTo(6,8);sprite.graphics.lineTo(4,10);
            sprite.graphics.moveTo(7,5); sprite.graphics.lineTo(9,8); sprite.graphics.lineTo(7,11);
            sprite.graphics.moveTo(10,4); sprite.graphics.lineTo(12,8); sprite.graphics.lineTo(10,12);
            bitmapData.draw(sprite);
            return bitmapData;
        }

       
        //-----------------------------------------------------       
        // 敵の画像作成【F】
        //-----------------------------------------------------
        //Nomal タイプ
        private static function createNormalEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite; 
            sprite.graphics.moveTo(0,8);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_inColor ,1 ,
                            [3.5,7,14] , [8,4,4] , [5.5,9.5,14] , [6,4,8] );
            sprite.graphics.moveTo(0,8); 
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_inColor ,1 ,
                            [3.5,7,14] , [8,4,4] , [5.5,9.5,14] , [6,4,8] );
            sprite.graphics.moveTo(15.5,8);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [15.5,7,3 ,3.5 ,7,14] , [2.5,2.5,8,8,4 ,4 ] , [9.5,5,0 ,5.5,9.5,14] , [2.5 ,5,8,6,4 ,8]);
            sprite.graphics.moveTo(15.5,8);
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [15.5,7,3 ,3.5 ,7,14] , [2.5,2.5,8,8,4 ,4 ] , [9.5,5,0 ,5.5,9.5,14] , [2.5 ,5,8,6,4 ,8]);
            sprite.graphics.drawCircle(10,8,3); 
            bitmapData.draw(sprite);
            return bitmapData;
        }
        // Fastタイプ
        private static function createFastEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.moveTo(5,8);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_inColor ,1 ,
                            [8.5,11] , [6,6] , [9.5,11] , [6,8]);
            sprite.graphics.moveTo(5,8);
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_inColor ,1 ,
                            [8.5,11] , [6,6] , [9.5,11] , [6,8]);
            sprite.graphics.moveTo(12,8);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [12,5.5,  ,8.5,11] , [4.5 ,4.5 ,  ,6 ,6 ] , [8.5 ,0 ,5 ,9.5,11] , [4.5 ,8 ,8 ,6 ,8 ]);
            sprite.graphics.moveTo(12,8);
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [12,5.5,  ,8.5,11] , [4.5 ,4.5 ,  ,6 ,6 ] , [8.5 ,0 ,5 ,9.5,11] , [4.5 ,8 ,8 ,6 ,8 ]);
            sprite.graphics.moveTo(15 ,8 );
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [15,9,13] , [3.5 ,3 ,3.5 ] , [10 ,8 ,13.5 ] , [3 ,3.5 ,8]);
            sprite.graphics.moveTo(15 ,8 );
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [15,9,13] , [3.5 ,3 ,3.5 ] , [10 ,8 ,13.5 ] , [3 ,3.5 ,8]);
            bitmapData.draw(sprite);
            return bitmapData;
        }
        // Immuneタイプの敵の画像を作成する【F】
        private static function createImmuneEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.moveTo(4, 8);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_inColor ,1 ,
                            [4 ,10.5] , [5.5, 4 ] , [5, 12] , [4 ,8 ]);
            sprite.graphics.moveTo(4, 8);
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_inColor ,1 ,
                            [4 ,10.5] , [5.5, 4 ] , [5, 12] , [4 ,8 ]);
            sprite.graphics.moveTo(15,8);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [12 ,1.5 ,  ,4 ,10.5] , [0 ,2 ,  ,5.5 ,4 ] , [4 ,1 ,4 ,5 ,12 ] , [1.5 ,8 ,8 ,4 ,8 ]);
            sprite.graphics.moveTo(15,8);
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [12 ,1.5 ,  ,4 ,10.5] , [0 ,2 ,  ,5.5 ,4 ] , [4 ,1 ,4 ,5 ,12 ] , [1.5 ,8 ,8 ,4 ,8 ]);
            sprite.graphics.moveTo(11,8);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [10 ,5.5 ] , [6 ,7 ] , [6 ,5.5] , [5 ,8 ]);
            sprite.graphics.moveTo(11,8);
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [10 ,5.5 ] , [6 ,7 ] , [6 ,5.5] , [5 ,8 ]);
            bitmapData.draw(sprite);
            return bitmapData;
        }
        // Flying タイプの敵の画像を作成する
        private static function createFlyingEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.moveTo(12 ,6 );
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [11 ,  ,10 ] , [2 ,  ,3 ] , [6 ,6.5 ,12 ] , [0.5 ,4.5 ,6 ]);
            sprite.graphics.moveTo(12,10);
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [11 ,  ,10 ] , [2 ,  ,3 ] , [6 ,6.5 ,12 ] , [0.5 ,11.5,6]);
            sprite.graphics.drawCircle(8.5 ,8 ,3.5)
            sprite.graphics.beginFill(_inColor); sprite.graphics.drawCircle(9 ,8 ,3)
            sprite.graphics.beginFill(_outColor); sprite.graphics.drawCircle(9.5 ,8 ,2)
            bitmapData.draw(sprite);
            return bitmapData;
        }
        // Swarm タイプの敵の画像を作成する
        private static function createSwarmEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.moveTo(0,8);           
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [4 ,7 ,12 ] , [8 ,5 ,5 ] , [6 ,9.5 ,14 ] , [7 ,5 ,8 ]);
            sprite.graphics.moveTo(0,8);
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [4 ,7 ,12 ] , [8 ,5 ,5 ] , [6 ,9.5 ,14 ] , [7 ,5 ,8 ]);                       
            sprite.graphics.beginFill(_inColor); sprite.graphics.drawCircle(11 ,8 ,2 ); sprite.graphics.drawCircle(8 ,8 ,1 );
            bitmapData.draw(sprite);
            return bitmapData;
        }

        // Zombieタイプの敵の画像を作成する            
        private static function createZombieEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.moveTo(5,2);           
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [5,  ,8] , [5,  ,5] , [5,15,2] , [8,8 ,5]); 
            sprite.graphics.moveTo(5,14);
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [5,  ,8] ,[5,  ,5] , [5,15,2] ,[8,8 ,5]); 
            sprite.graphics.moveTo(2,2);           
            sprite = drawingArray(sprite ,0x000000 ,0 ,_outColor ,
                            [8,14,10,14,8 ,2 ,6] , [6,2 , 8,14,10,14,8] );
            sprite.graphics.endFill() ;
            sprite.graphics.beginFill(_outColor);
            sprite.graphics.drawCircle(8,8,3.5);
            sprite.graphics.endFill();
            sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawCircle(8,8,2);
            sprite.graphics.drawCircle(2,2,2);
            sprite.graphics.drawCircle(2,14,2);
            bitmapData.draw(sprite);
            return bitmapData;
        }

        // Fadeタイプの敵の画像を作成する            
        private static function createFadeEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
                        sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawCircle(4,8,2.5);                                      
            sprite.graphics.drawCircle(12,4,2.5);
            sprite.graphics.drawCircle(12,12,2.5);
            sprite.graphics.moveTo(2,8);
            sprite = drawingCurveArray(sprite ,_outColor ,1 ,_outColor ,0 ,
                            [2,7,10 ,15,13] , [5,5,1 ,4 ,7 ] , 
                            [5,9,13,14,13] , [5,3,2 ,6 ,8 ]); 
            sprite.graphics.moveTo(2,8);
            sprite = drawingCurveArrayMILLOR(sprite ,_outColor ,1 ,_outColor ,0 ,
                            [2,7,10,15,13] , [5,5,1 ,4 ,7 ] , 
                            [5,9,13,14,13] , [5,3,2 ,6 ,8 ]); 
            sprite.graphics.endFill();
            sprite.graphics.moveTo(7,5); sprite.graphics.lineTo(13,14);
            sprite.graphics.moveTo(7,11); sprite.graphics.lineTo(13,2);
            bitmapData.draw(sprite);
            return bitmapData;
        }

        // Splitタイプの敵の画像を作成する            
        private static function createSplitEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginFill(_outColor);
            sprite.graphics.drawCircle(9,8,6);sprite.graphics.endFill();
            sprite.graphics.beginFill(_outColor);            
            sprite.graphics.drawCircle(5,4,3.5); sprite.graphics.drawCircle(11,5,3);
            sprite.graphics.drawCircle(5,12,3.5); sprite.graphics.drawCircle(11,11,3);
            sprite.graphics.endFill();
            sprite.graphics.moveTo(6,4);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [4,4] , [7,9] , [0,6] , [8,12] ); 
            sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawCircle(8,8,2);
            sprite.graphics.drawCircle(5,4,2.5); sprite.graphics.drawCircle(11,5,2);
            sprite.graphics.drawCircle(5,12,2.5); sprite.graphics.drawCircle(11,11,2);
            bitmapData.draw(sprite);
            return bitmapData;
        }
        // SplitChildタイプの敵の画像を作成する
        private static function createSplitChildEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginFill(_outColor);
            sprite.graphics.drawCircle(9,8,3.5);sprite.graphics.endFill();
            sprite.graphics.moveTo(8,6);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 , [4,4] , [7,9] , [0,8] , [8,10] ); 
            sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawCircle(9,8,2);
            bitmapData.draw(sprite);
            return bitmapData;
        }
        // Furyタイプの敵の画像を作成する
        private static function createFuryEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.moveTo(14,8);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 , [13,5 ] , [6 ,6 ] , [9 ,0 ] ,  [6 ,8 ] ); 
            sprite.graphics.endFill();            
            sprite.graphics.moveTo(15,7);            
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 , [15,11 ,10 ,14] , [3 ,0.5,2.5,5 ] ,  [13,4  ,12 ,15] , [2 ,2  ,4  ,7 ] ); 
            sprite.graphics.endFill();
            sprite.graphics.moveTo(12,5.5);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 , [10 ,5.5,8  ] ,  [3.5,3  ,4] ,  [8  ,2  ,12 ] ,  [3.5,6  ,5.5 ] ); 
            sprite.graphics.endFill();            
            sprite.graphics.moveTo(14,8);
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_outColor ,1 , [13,5 ] , [6 ,6 ] , [9 ,0 ] ,  [6 ,8 ] ); 
            sprite.graphics.endFill();            
            sprite.graphics.moveTo(15,9);            
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_outColor ,1 , [15,11 ,10 ,14] , [3 ,0.5,2.5,5 ] ,  [13,4  ,12 ,15] , [2 ,2  ,4  ,7 ] ); 
            sprite.graphics.endFill();
            sprite.graphics.moveTo(12,10.5);
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_outColor ,1 , [10 ,5.5,8  ] ,  [3.5,3  ,4] ,  [8  ,2  ,12 ] ,  [3.5,6  ,5.5 ] ); 
            sprite.graphics.endFill();
            sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawEllipse(7,7,5,2);
            bitmapData.draw(sprite);
            return bitmapData;
        }
        
        // Shellタイプの敵01-03の画像を作成する
        private static function createShellOneEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawCircle(8,8,4);
            sprite.graphics.endFill();
            sprite.graphics.moveTo(15,8);
            sprite = drawingArray(sprite ,0x000000 ,0 ,_outColor ,
                            [13,11,10,12,10,11,13,15] , 
                            [4 ,2 ,2 ,8 ,14,14,12,8 ] ); 
            sprite.graphics.moveTo(11,8);
            sprite = drawingArray(sprite ,0x000000 ,0 ,_outColor ,
                            [9 ,7 ,6 ,8 ,6 ,7 ,9 ,11] , 
                            [5 ,3 ,3 ,8 ,13,13,11,8 ] ); 
            sprite.graphics.moveTo(7,8);
            sprite = drawingArray(sprite ,0x000000 ,0 ,_outColor ,
                            [5 ,3 ,2 ,4 ,2 ,3 ,5 ,7 ] , 
                            [6 ,4 ,4 ,8 ,12,12,10,8 ] ); 
            sprite.graphics.endFill();
            bitmapData.draw(sprite);
            return bitmapData;
        }            
        private static function createShellTwoEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawCircle(7,8,3.5);
            sprite.graphics.endFill();
            sprite.graphics.moveTo(11,8);
            sprite = drawingArray(sprite ,0x000000 ,0 ,_outColor ,
                            [9 ,7 ,6 ,8 ,6 ,7 ,9 ,11] , 
                            [5 ,3 ,3 ,8 ,13,13,11,8 ] ); 
            sprite.graphics.moveTo(7,8);
            sprite = drawingArray(sprite ,0x000000 ,0 ,_outColor ,
                            [5 ,3 ,2 ,4 ,2 ,3 ,5 ,7 ] , 
                            [6 ,4 ,4 ,8 ,12,12,10,8 ] ); 
            sprite.graphics.endFill();
            bitmapData.draw(sprite);
            return bitmapData;
        }            
        private static function createShellThreeEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawCircle(5,8,3);
            sprite.graphics.endFill();
            sprite.graphics.moveTo(7,8);
            sprite = drawingArray(sprite ,0x000000 ,0 ,_outColor ,
                            [5 ,3 ,2 ,4 ,2 ,3 ,5 ,7 ] , 
                            [6 ,4 ,4 ,8 ,12,12,10,8 ] ); 
            sprite.graphics.endFill();
            bitmapData.draw(sprite);
            return bitmapData;
        }                
        
        // Fupaタイプの敵の画像を作成する
        private static function createFupaEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.moveTo(6,4);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_outColor ,1 ,
                            [1,1 ,8 ,15,15,8] , [4,12,12,12,4 ,4] , [1,6 ,10,15,10,6] , [8,12,12,8 ,4 ,4] ); 
            sprite.graphics.endFill();
            sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawCircle(11,8,2);
            sprite.graphics.moveTo(11,5);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_inColor ,1 ,
                            [10,6  ,6  ,8 ] , [5 ,5.5,7.5,6 ] , [8 ,5  ,8  ,11] , [5 ,7.5,7.5,5 ] ); 
            sprite.graphics.moveTo(11,11);
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_inColor ,1 ,
                            [10,6  ,6  ,8 ] , [5 ,5.5,7.5,6 ] ,  [8 ,5  ,8  ,11] , [5 ,7.5,7.5,5 ] ); 
            sprite.graphics.endFill();
            bitmapData.draw(sprite);
            return bitmapData;
        }                
        
        // Ghostタイプの敵の画像を作成する
        private static function createGhostEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawCircle(11,8,4);
            sprite.graphics.endFill();
            sprite.graphics.lineStyle(1,_outColor,1);
            sprite.graphics.drawCircle(10,8,5);
            sprite.graphics.moveTo(13,8);
            sprite = drawingCurveArray(sprite ,_outColor ,1 ,_outColor ,0 ,
                            [13,8,3,3] , 
                            [6 ,3,4,7] ,  
                            [11,1,4,1] , 
                            [5 ,2,6,8] ); 
            sprite.graphics.moveTo(13,8);
            sprite = drawingCurveArrayMILLOR(sprite ,_outColor ,1 ,_outColor ,0 ,
                            [13,8,3,3] , 
                            [6 ,3,4,7] ,  
                            [11,1,4,1] , 
                            [5 ,2,6,8] ); 
            sprite.graphics.endFill();
            bitmapData.draw(sprite);
            return bitmapData;
        }                
        
        // Left-Rightタイプの敵の画像を作成する
        private static function createDetourRightEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.moveTo(15,10);
            sprite = drawingCurveArray(sprite ,_outColor ,0 ,_outColor ,1 ,
                            [15,11,8,4 ,5 ,10,15] , 
                            [7 ,3 ,4,7 ,10,14,12] ,  
                            [13,6 ,9,0 ,7 ,13,15] , 
                            [5 ,2 ,6,11,12,13,10] ); 
            sprite.graphics.moveTo(14,13);
            sprite = drawingCurveArray(sprite ,_outColor ,0 ,_outColor ,1 ,
                            [13,12,13] , 
                            [16,15,14] ,  
                            [10,11,14] , 
                            [16,14,13] ); 
            sprite.graphics.endFill();
            sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawCircle(11.5, 10, 2.5);
            bitmapData.draw(sprite);
            return bitmapData;
        }
        private static function createDetourLeftEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.moveTo(15,6);
            sprite = drawingCurveArray(sprite ,_outColor ,0 ,_outColor ,1 ,
                            [15,11,8 ,4 ,5 ,10,15] , 
                            [9 ,13,12,9 ,6 ,2 ,4 ] ,  
                            [13,6 ,9 ,0 ,7 ,13,15] , 
                            [11,14,10,5 ,4 ,3 ,6 ] ); 
            sprite.graphics.moveTo(14,3);
            sprite = drawingCurveArray(sprite ,_outColor ,0 ,_outColor ,1 ,
                            [13,12,13] , 
                            [0 ,1 ,2 ] ,  
                            [10,11,14] , 
                            [0 ,2 ,3 ] ); 
            sprite.graphics.endFill();
            sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawCircle(11.5,6,2.5);
            bitmapData.draw(sprite);
            return bitmapData;
        }
        // Decoyerタイプの敵の画像を作成する
        private static function createDecoyerEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.moveTo(15,8);
            sprite = drawingCurveArray(sprite ,_outColor ,0 ,_outColor ,1 ,
                            [15,11,11] ,[6 ,4 ,6 ] ,[8 ,5 ,11] ,[1 ,5 ,8 ] ); 
            sprite.graphics.moveTo(10,8);
            sprite = drawingCurveArray(sprite ,_outColor ,0 ,_outColor ,1 ,
                            [10,5] ,[7 ,8] ,[8 ,0] ,[6 ,8] );
            sprite.graphics.moveTo(15,8);
            sprite = drawingCurveArrayMILLOR(sprite ,_outColor ,0 ,_outColor ,1 ,
                            [15,11,11] ,[6 ,4 ,6 ] ,[8 ,5 ,11] ,[1 ,5 ,8 ] ); 
            sprite.graphics.moveTo(10,8);
            sprite = drawingCurveArrayMILLOR(sprite ,_outColor ,0 ,_outColor ,1 ,
                            [10,5] ,[7 ,8] ,[8 ,0] ,[6 ,8] ); 
            sprite.graphics.endFill();
            sprite.graphics.beginFill(_inColor);
            sprite.graphics.drawCircle(12,8,2);
            bitmapData.draw(sprite);
            return bitmapData;
        }// デコイ画像
        private static function createDecoyEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginFill(_outColor);
            sprite.graphics.drawRect(5,7,6,2);
            sprite.graphics.drawCircle(3.5,8,2);
            sprite.graphics.drawCircle(12.5,8,2);
            bitmapData.draw(sprite);
            return bitmapData;
        }
        // Wallタイプの敵の画像を作成する
        private static function createWallEnemy(_outColor:uint, _inColor:uint):BitmapData {
            var bitmapData:BitmapData = new BitmapData(16, 16, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.moveTo(2, 8);
            sprite = drawingArray(sprite ,_outColor ,0,_outColor ,
                            [8, 2,2,8,14,14,8 ],[0 ,2,14,16,14,2,0]);
            sprite.graphics.endFill();
            sprite.graphics.moveTo(3, 8);
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_inColor ,1 ,
                            [4 ,10.5] , [5.5, 4 ] , [5, 12] , [4 ,8 ]);
            sprite.graphics.moveTo(13, 8);            
            sprite = drawingCurveArray(sprite ,0x000000 ,0 ,_inColor ,1 ,
                            [12 ,5.5] , [5.5, 4 ] , [11, 4 ] , [4 ,8 ]);
            sprite.graphics.moveTo(3, 8);                            
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_inColor ,1 ,
                            [4 ,10.5] , [5.5, 4 ] , [5, 12] , [4 ,8 ]);
            sprite.graphics.moveTo(13, 8);            
            sprite = drawingCurveArrayMILLOR(sprite ,0x000000 ,0 ,_inColor ,1 ,
                            [12 ,5.5] , [5.5, 4 ] , [11, 4 ] , [4 ,8 ]);            
            sprite.graphics.beginFill(_outColor);
            sprite.graphics.drawCircle(8,8,2);
            bitmapData.draw(sprite);
            return bitmapData;
        }        
        
        //-----------------------------------------------------       
        // 弾の画像作成【F】
        //----------------------------------------------------- 
        private static function createArrowBullet():BitmapData {
            var bitmapData:BitmapData = new BitmapData(8, 8, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(2);
            sprite.graphics.moveTo(1, 4);
            sprite.graphics.lineTo(7, 4);
            bitmapData.draw(sprite);
            return bitmapData;
        }
        // 普通の弾の画像を作成する (引数に弾の半径)
        private static function createNormalBullet(radius:int):BitmapData {
            var bitmapData:BitmapData = new BitmapData(8, 8, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginFill(0x000000);
            sprite.graphics.drawCircle(4, 4, radius);
            bitmapData.draw(sprite);
            return bitmapData;
        }        
        private static function createMissileBullet():BitmapData {
            var bitmapData:BitmapData = new BitmapData(8, 8, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginFill(0x000000);
            sprite.graphics.drawCircle(3, 2, 2);
            sprite.graphics.drawCircle(3, 6, 2);
            sprite.graphics.drawCircle(5, 4, 2);
            bitmapData.draw(sprite);
            return bitmapData;
        }
        // エフェクトのコインの画像を作成する
        private static function createCoin():BitmapData {
            var bitmapData:BitmapData = new BitmapData(8, 8, true, 0x00ffffff);
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginFill(0xcccc00);
            sprite.graphics.drawEllipse(2, 1, 4, 6);
            sprite.graphics.endFill();
            sprite.filters = [new BevelFilter(1, 45, 0xffffff, 1, 0x000000, 1, 0, 0)];
            bitmapData.draw(sprite);
            return bitmapData;
        }

        //-----------------------------------------------------       
        // テキストの作成【F】
        //-----------------------------------------------------

        // 普通のテキストを作成する
        public static function createSimpleText(posx:int, posy:int, width:int, height:int, text:String, fontSize:int, textColor:uint):TextField {
            return ImageFactory.createText(posx, posy, width, height, text, fontSize, textColor, TextFieldAutoSize.CENTER);
        }
        
        // 縁取り付きのテキストを作成する
        public static function createBorderedText(posx:int, posy:int, width:int, height:int, text:String, fontSize:int, textColor:uint, borderColor:uint):TextField {
            return ImageFactory.createText(posx, posy, width, height, text, fontSize, textColor, TextFieldAutoSize.CENTER, false, true, borderColor);
        }
        // 縁取り付き左揃えのテキストを作成する【F】
        public static function createBorderedTextLEFT(posx:int, posy:int, width:int, height:int, text:String, fontSize:int, textColor:uint, borderColor:uint):TextField {
            return ImageFactory.createText(posx, posy, width, height, text, fontSize, textColor, TextFieldAutoSize.LEFT, false, true, borderColor);
        }

        // スコア表示用のテキストを作成する
        public static function createScoreText(posx:int, posy:int, width:int, height:int, text:String, fontSize:int, textColor:uint):TextField {
            return ImageFactory.createText(posx, posy, width, height, text, fontSize, textColor, TextFieldAutoSize.RIGHT, true);
        }
        // タワーのステータス表示用テキストを作成する
        public static function createStatusText(posx:int, posy:int, width:int, height:int, text:String, fontSize:int, textColor:uint):TextField {
            return ImageFactory.createText(posx, posy, width, height, text, fontSize, textColor, TextFieldAutoSize.CENTER, true);
        }
        // タワーのステータス表示用テキスト右揃えを作成する
        public static function createStatusTextRight(posx:int, posy:int, width:int, height:int, text:String, fontSize:int, textColor:uint):TextField {
            return ImageFactory.createText(posx, posy, width, height, text, fontSize, textColor, TextFieldAutoSize.RIGHT, true);
        }
        
        private static function createText(posx:int, posy:int, width:int, height:int, text:String, fontSize:int, textColor:uint, autoSize:String, bold:Boolean = false, border:Boolean = false, borderColor:uint = 0x000000, embed:Boolean = false):TextField { 
            var textField:TextField = new TextField();
            if (embed) {
                textField.embedFonts = true;
                textField.antiAliasType = AntiAliasType.ADVANCED;
            }
            var font:String = embed ? Const.EMBED_FONT : "Arial";
            textField.defaultTextFormat = new TextFormat(font, fontSize, null, bold);
            textField.text = text;
            textField.x = posx;
            textField.y = posy + Math.ceil((height - (textField.textHeight + 4)) / 2);
            textField.width = Math.max(width, textField.textWidth + 4);
            textField.height = textField.textHeight + 4;
            textField.textColor = textColor;
            if (border) { textField.filters = [new GlowFilter(borderColor, 1, 4, 4)]; }
            textField.autoSize = autoSize;
            textField.mouseEnabled = textField.selectable = false;
            return textField;
        }
        
        // 説明用のテキストを作成する
        public static function createInstructionText(posx:int, posy:int, width:int, height:int, text:String, fontSize:int):TextField {
            return ImageFactory.createText(posx, posy, width, height, text, fontSize, 0xffffff, TextFieldAutoSize.LEFT, false, false, 0x000000, Const.USE_FONTLOADER);
        }
        
        // ウインドウを作成する
        public static function createWindow(posx:int, posy:int, width:int, height:int):Sprite {
            var sprite:Sprite = new Sprite();
            sprite.x = posx;
            sprite.y = posy;
            sprite.mouseEnabled = false;
            var matrix:Matrix = new Matrix();
            matrix.createGradientBox(width, height, Math.PI / 2);
            sprite.graphics.lineStyle(1);
            sprite.graphics.lineGradientStyle(GradientType.LINEAR, [0xf0f0f0, 0x808080], [1, 1], [0, 255], matrix);
            sprite.graphics.beginGradientFill(GradientType.LINEAR, [0x303030, 0x000000], [1, 1], [0, 255], matrix);
            sprite.graphics.drawRect(1, 1, width - 2, height - 2);
            sprite.graphics.endFill();
            return sprite;
        }
        
        
        //描画サポートファンクション【F】-----------------------------------        
        //線を描画用のファンクション引数は(スプライト、線色、線のアルファ、塗り色、x座標アレイ、y座標アレイ) 
        private  static function drawingArray(drawn:Sprite,lineColor:uint,alpha:int,bodyColor:uint,xArray:Array,yArray:Array):Sprite {
            drawn.graphics.lineStyle(1,lineColor,alpha,true);
            drawn.graphics.beginFill(bodyColor);
            if(xArray.length == yArray.length){                 
                 var len:int = xArray.length;
                 for ( var i:int=0; i<len; i++ ){drawn.graphics.lineTo(xArray[i],yArray[i])} ;
            }
            return drawn;    
        }
        
        //タワー画像の下に敷く円 引数は(線の色)
        private  static function towerCircle(lineColor:uint):Sprite{
            var _cy:Sprite = new Sprite;
            _cy.graphics.lineStyle(1,lineColor,1,true);
            _cy.graphics.drawCircle(16,16,10);
            return _cy;
        }
        //カーブ用の描画サポート、アーカーポイントの座標がnullのときはlineToする
        //引数は(スプライト、線色、線のアルファ、塗り色、塗りのアルファ、アーカーx座標アレイ、アーカーy座標アレイ、 描画x座標アレイ、 描画y座標アレイ)
        private static function drawingCurveArray(drawn:Sprite, lineColor:uint, lineAlpha:Number, bodyColor:uint, bodyAlpha:Number , AxArray:Array, AyArray:Array ,PxArray:Array, PyArray:Array):Sprite{
            drawn.graphics.lineStyle(1 ,lineColor, lineAlpha, true);
            drawn.graphics.beginFill(bodyColor ,bodyAlpha );
            if(AxArray.length == AyArray.length && PxArray.length == PyArray.length && AxArray.length == PxArray.length){                 
                 var len:int = AxArray.length;
                     for ( var i:int=0; i<len; i++ ){
                         if ( AxArray[i] == null  &&  AyArray[i] == null) {drawn.graphics.lineTo(PxArray[i], PyArray[i]); continue 
                         } else { drawn.graphics.curveTo(AxArray[i], AyArray[i] , PxArray[i], PyArray[i] ); continue ;}
                     } 
            }
            return drawn;    
        } 
        // 敵を作成する専用描画ファンクション
        // カーブを上下に反射して描画(縦16ピクセル用)
        private static function drawingCurveArrayMILLOR(drawn:Sprite, lineColor:uint, lineAlpha:Number, bodyColor:uint, bodyAlpha:Number , AxArray:Array, AyArray:Array ,PxArray:Array, PyArray:Array):Sprite{
            drawn.graphics.lineStyle(1 ,lineColor, lineAlpha, true);
            drawn.graphics.beginFill(bodyColor ,bodyAlpha );
            if(AxArray.length == AyArray.length && PxArray.length == PyArray.length && AxArray.length == PxArray.length){                 
                 var len:int = AxArray.length;
                     for ( var i:int=0; i<len; i++ ){
                         if ( AxArray[i] == null  &&  AyArray[i] == null) {drawn.graphics.lineTo(PxArray[i], PyArray[i]); continue 
                         } else { drawn.graphics.curveTo(AxArray[i], 16 - AyArray[i] , PxArray[i], 16 - PyArray[i] ); continue ;}
                     } 
            }
            return drawn;    
        }        
        
        //-----------------------------------        

    }
//}

/* ----------------------------------------------------------------------------------------------------------------------
 * Config
 * -----------------------------------------------------------------------------------------------------------------------
 */
//package {
    import flash.utils.Dictionary;
    
    //public 
    class Config {
        public static const INITIAL_LIVES:int = 10;
        public static const INITIAL_GOLD:int = 200; 
        
        //横Node0-23 縦Node0-25
        public static const NODE_TYPE:Array = [
            [1,1,1,1,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,2,2],
            [1,1,1,1,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,2,2],
            [1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
            [1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
            [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
            [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
            [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
            [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
            [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
            [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
            [1,1,0,0,0,0,0,0,0,0,3,3,3,3,0,0,0,0,0,0,0,0,1,1],
            [1,1,0,0,0,0,0,0,0,0,3,3,3,3,0,0,0,0,0,0,0,0,1,1],
            [1,1,0,0,0,0,0,0,0,0,3,3,3,3,0,0,0,0,0,0,0,0,1,1],
            [1,1,0,0,0,0,0,0,0,0,3,3,3,3,0,0,0,0,0,0,0,0,1,1],
            [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
            [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
            [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
            [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
            [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
            [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
            [1,1,1,1,1,1,1,1,0,0,2,2,0,0,0,0,0,0,0,0,1,1,1,1],
            [1,1,1,1,1,1,1,1,0,0,2,2,0,0,0,0,0,0,0,0,1,1,1,1],
            [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
            [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
        ];

        private static const XML_DATA:XML =
        <root>
            <starts>
                <start x="8"  y="0" width="4" flying="0" />
                <start x="21"  y="0" width="2" flying="0" />
                <start x="2" y="0" width="1" flying="1" />
            </starts>
            <goals>
                <goal x="10" y="20" /><goal x="11" y="20" />
                <goal x="10" y="21" /><goal x="11" y="21" />
            </goals>
           
            <tower>
                <type name="Gun" towerbase="0" ground="1" air="1" slow="0" splash="0" venom="0">
                    <status level="1" cost="8"    damage="10"   range="60"  firerate="1.6" />
                    <status level="2" cost="16"   damage="20"   range="65"  firerate="1.8" />
                    <status level="3" cost="32"   damage="40"   range="70"  firerate="2.0" />
                    <status level="4" cost="64"   damage="80"   range="80"  firerate="2.2" />
                    <status level="5" cost="192"  damage="300"  range="180" firerate="1.0" />
                </type>
                <type name="Gatling" towerbase="0" ground="1" air="1" slow="0" splash="0" venom="0">
                    <status level="1" cost="20"   damage="5"    range="55"  firerate="4.0" />
                    <status level="2" cost="35"   damage="9"    range="60"  firerate="4.5" />
                    <status level="3" cost="95"   damage="22"   range="65"  firerate="5.0" />
                    <status level="4" cost="210"  damage="50"   range="70"  firerate="5.5" />
                    <status level="5" cost="800"  damage="166"   range="80"  firerate="9.9" />
                </type>
                <type name="Cannon" towerbase="0" ground="1" air="0" slow="0" splash="24" venom="0">
                    <status level="1" cost="25"   damage="15"   range="80"  firerate="0.9" />
                    <status level="2" cost="50"   damage="40"   range="88"  firerate="1.0" />
                    <status level="3" cost="120"   damage="120"   range="96"  firerate="1.1" />
                    <status level="4" cost="280"  damage="350"  range="104" firerate="1.2" />
                    <status level="5" cost="940"  damage="980"  range="126" firerate="1.6" />
                </type>        
                <type name="Venom" towerbase="0" ground="1" air="0" slow="0" splash="0" venom="3">
                    <status level="1" cost="30"   damage="5"   range="32"  firerate="0.5" />
                    <status level="2" cost="70"   damage="35"   range="34"  firerate="0.6" />
                    <status level="3" cost="150"   damage="80"   range="36"  firerate="0.8" />
                    <status level="4" cost="320"  damage="200"   range="38"  firerate="1.2" />
                    <status level="5" cost="1050"  damage="750"   range="45"  firerate="1.6" />
                </type>        
                <type name="Voltex" towerbase="0" ground="1" air="1" slow="25" splash="42" venom="0">
                    <status level="1" cost="70"   damage="20"   range="42"  firerate="0.6" />
                    <status level="2" cost="130"  damage="50"  range="42"  firerate="0.6" />
                    <status level="3" cost="250"  damage="120"  range="54"  firerate="0.8" />
                    <status level="4" cost="490"  damage="300"  range="54"  firerate="0.8" />
                    <status level="5" cost="990"  damage="690"  range="66"  firerate="1.0" />
                </type>        
                <type name="AntiFly" towerbase="0" ground="0" air="1" slow="0" splash="1" venom="0">
                    <status level="1" cost="100"  damage="135"  range="100"  firerate="1.1" />
                    <status level="2" cost="250"  damage="255"  range="104"  firerate="1.3" />
                    <status level="3" cost="510"  damage="510"  range="108"  firerate="1.5" />
                    <status level="4" cost="990"  damage="990"  range="112"  firerate="1.7" />
                    <status level="5" cost="2000" damage="2500" range="120"  firerate="2.0" />
                </type> 
                <type name="Base" towerbase="1" ground="0" air="0" slow="0" splash="0" venom="0">
                    <status level="1" cost="5"   damage="0"   range="0"  firerate="0" />
                </type>        
            </tower>
            
           <enemy>
                // flying[0/1] immunity[0/1] regeneration[回復量(MaxHPの千分率/フレーム)] fade[時間量] born[0/1] accelerate[0/1]
                <type name="Normal" speed="1.4" MinSpeed="1.3" MaxSpeed="1.5" flying="0" immunity="0" regeneration="0" fade="0" born="0" accelerate="0"/>
                <type name="Immune" speed="0.8" MinSpeed="0.7" MaxSpeed="0.9" flying="0" immunity="1" regeneration="0" fade="0" born="0" accelerate="0"/>
                <type name="Fast"   speed="2.8" MinSpeed="2.6" MaxSpeed="3.0" flying="0" immunity="0" regeneration="0" fade="0" born="0" accelerate="0"/>
                <type name="Flying" speed="1.4" MinSpeed="1.3" MaxSpeed="1.5" flying="1" immunity="0" regeneration="0" fade="0" born="0" accelerate="0" />
                <type name="Swarm" speed="1.8" MinSpeed="1.5" MaxSpeed="2.1" flying="0" immunity="0" regeneration="0" fade="0" born="0" accelerate="1" />
                <type name="Zombie" speed="1.1" MinSpeed="1.0" MaxSpeed="1.2" flying="0" immunity="0" regeneration="10" fade="0" born="0" accelerate="0" />
                <type name="Fade" speed="1.6" MinSpeed="1.5" MaxSpeed="1.7" flying="0" immunity="0" regeneration="0" fade="80" born="0" accelerate="0" />
                <type name="Split" speed="1.1" MinSpeed="1.0" MaxSpeed="1.2" flying="0" immunity="0" regeneration="0" fade="0" born="1" accelerate="0" />
                <type name="SplitChild" speed="1.8" MinSpeed="1.6" MaxSpeed="2.0" flying="0" immunity="0" regeneration="0" fade="0" born="0" accelerate="1" />
                <type name="Fury" speed="1.6" MinSpeed="1.3" MaxSpeed="8.0" flying="0" immunity="0" regeneration="0" fade="0" born="0" accelerate="1" />
                <type name="Fupa" speed="1.5" MinSpeed="1.3" MaxSpeed="1.7" flying="0" immunity="0" regeneration="0" fade="0" born="1" accelerate="0" />
                <type name="FupaChild" speed="0.8" MinSpeed="0.7" MaxSpeed="0.9" flying="1" immunity="0" regeneration="0" fade="0" born="0" accelerate="0" />
                <type name="Ghost" speed="1.3" MinSpeed="1.2" MaxSpeed="1.4" flying="1" immunity="0" regeneration="0" fade="40" born="0" accelerate="0" />
                <type name="Shell" speed="3.8" MinSpeed="1.3" MaxSpeed="4.2" flying="0" immunity="0" regeneration="0" fade="0" born="1" accelerate="1" />
                <type name="Shell-2" speed="4.4" MinSpeed="1.4" MaxSpeed="4.6" flying="0" immunity="0" regeneration="0" fade="0" born="1" accelerate="1" />
                <type name="Shell-3" speed="5.4" MinSpeed="1.6" MaxSpeed="5.4" flying="0" immunity="0" regeneration="0" fade="0" born="0" accelerate="1" />
                <type name="Detour" speed="2.0" MinSpeed="0.7" MaxSpeed="2.3" flying="1" immunity="0" regeneration="0" fade="0" born="1" accelerate="1" />
                <type name="Detour-L" speed="2.0" MinSpeed="0.7" MaxSpeed="2.3" flying="1" immunity="0" regeneration="0" fade="0" born="0" accelerate="1" />
                <type name="Decoyer" speed="1.6" MinSpeed="1.3" MaxSpeed="1.6" flying="1" immunity="0" regeneration="0" fade="0" born="1" accelerate="0" />
                <type name="Decoy-1" speed="6.2" MinSpeed="0" MaxSpeed="6.2" flying="1" immunity="0" regeneration="0" fade="0" born="1" accelerate="1" />
                <type name="Decoy-2" speed="6.2" MinSpeed="0" MaxSpeed="6.2" flying="1" immunity="0" regeneration="0" fade="0" born="0" accelerate="1" />
                <type name="Wall" speed="0.8" MinSpeed="0.6" MaxSpeed="1.0" flying="0" immunity="1" regeneration="2" fade="0" born="0" accelerate="0" />
            </enemy>
            
            <bornAbility>
                //親名[string]、子名[string]、子HP割合[Number]、子得点割合[Number]、1回産数[int]、限度産量[int]、インターバル[int]、出産被ダメ%[0~1]、死亡出産[0/1]、お金相続[0/1]、出産後の自分除去[0/1]
                <parent name="Split" childrenName="SplitChild" childrenHP="0.2" childrenPoint="0.2" amount="4" limit="4" intervalBorn="0" HPrateBorn="0" deadBorn="1" descent="1" selfRemove="1"/>
                <parent name="Fupa" childrenName="FupaChild" childrenHP="0.5" childrenPoint="0.5" amount="1" limit="1" intervalBorn="0" HPrateBorn="0" deadBorn="1" descent="1" selfRemove="1"/>
                <parent name="Shell" childrenName="Shell-2" childrenHP="0.6" childrenPoint="1" amount="1" limit="1" intervalBorn="0" HPrateBorn="0.6" deadBorn="0" descent="1" selfRemove="1"/>
                <parent name="Shell-2" childrenName="Shell-3" childrenHP="0.5" childrenPoint="1" amount="1" limit="1" intervalBorn="0" HPrateBorn="0.5" deadBorn="0" descent="1" selfRemove="1"/>
                <parent name="Detour" childrenName="Detour-L" childrenHP="1" childrenPoint="1" amount="1" limit="1" intervalBorn="1" HPrateBorn="0" deadBorn="0" descent="1" selfRemove="0"/>
                <parent name="Decoyer" childrenName="Decoy-1" childrenHP="0.01" childrenPoint="0.01" amount="1" limit="40" intervalBorn="45" HPrateBorn="0" deadBorn="0" descent="0" selfRemove="0"/>
                <parent name="Decoy-1" childrenName="Decoy-2" childrenHP="1" childrenPoint="1" amount="1" limit="1" intervalBorn="1" HPrateBorn="0" deadBorn="0" descent="0" selfRemove="0"/>
            </bornAbility>
            
            <accelerateAbility>
                //能力者名[string]、加算変化[Number]、積変化[Number]、飛行角度[int(degree)],サイン周期変化[Number]、インターバル[int]、加速ダメ%[0~1]、加速被ダメ割合[Number]
                 <runner name="Swarm" AddPoint="0" RatePoint="1" Angle="0" sineSlip="60" intervalRun="0" HPrateRun="0" damageRun="0"/>
                 <runner name="SplitChild" AddPoint="0" RatePoint="1" Angle="0" sineSlip="90" intervalRun="0" HPrateRun="0" damageRun="0"/>
                 <runner name="Fury" AddPoint="0.15" RatePoint="1" Angle="0" sineSlip="0" intervalRun="0" HPrateRun="0" damageRun="1"/>
                 <runner name="Shell" AddPoint="-0.2" RatePoint="1" Angle="0" sineSlip="0" intervalRun="2" HPrateRun="0" damageRun="0"/>
                 <runner name="Shell-2" AddPoint="-0.2" RatePoint="1" Angle="0" sineSlip="0" intervalRun="2" HPrateRun="0" damageRun="0"/>
                 <runner name="Shell-3" AddPoint="-0.2" RatePoint="1"  Angle="0" sineSlip="0" intervalRun="2" HPrateRun="0" damageRun="0"/>
                 <runner name="Detour" AddPoint="0" RatePoint="0.99"  Angle="305" sineSlip="0" intervalRun="3" HPrateRun="0" damageRun="0"/>
                 <runner name="Detour-L" AddPoint="0" RatePoint="0.99"  Angle="55" sineSlip="0" intervalRun="3" HPrateRun="0" damageRun="0"/>
                 <runner name="Decoyer" AddPoint="0" RatePoint="1"  Angle="0" sineSlip="60" intervalRun="2" HPrateRun="0" damageRun="0"/>
                 <runner name="Decoy-1" AddPoint="0" RatePoint="0.9"  Angle="90" sineSlip="0" intervalRun="1" HPrateRun="0" damageRun="0"/>
                 <runner name="Decoy-2" AddPoint="0" RatePoint="0.9"  Angle="270" sineSlip="0" intervalRun="1" HPrateRun="0" damageRun="0"/>
            </accelerateAbility>

            <waves>
                <wave type="Normal" HP="20"   point="8"   money="1"  ><spawn num="10" /><spawn num="0" /><spawn num="0"  /></wave>
                <wave type="Normal" HP="25"   point="8"   money="1"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Normal" HP="30"   point="8"   money="1"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Swarm"  HP="8"   point="1"   money="1"  ><spawn num="20" /><spawn num="20" /><spawn num="0"  /></wave>
                <wave type="Shell" HP="90"   point="8"   money="2"  ><spawn num="5" /><spawn num="5" /><spawn num="0"  /></wave>
                <wave type="Normal" HP="50"   point="8"   money="1"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Fade" HP="70"   point="8"   money="1"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Fast"   HP="80"   point="8"   money="1"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Flying" HP="70"   point="10"  money="2"  ><spawn num="0"  /><spawn num="0"  /><spawn num="15" /></wave>
                <wave type="Zombie" HP="300"  point="50"  money="20" ><spawn num="2"  /><spawn num="2"  /><spawn num="0"  /></wave>
                
                <wave type="Split" HP="70"  point="5"  money="1"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Normal" HP="110"  point="10"  money="2"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Immune" HP="160"  point="10"  money="2"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Shell"   HP="140"  point="10"  money="2"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Flying" HP="120"  point="12"  money="2"  ><spawn num="0"  /><spawn num="0"  /><spawn num="15" /></wave>
                <wave type="Zombie" HP="180"  point="14"  money="3"  ><spawn num="6" /><spawn num="6" /><spawn num="0"  /></wave>
                <wave type="Normal" HP="170"  point="12"  money="2"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Fury" HP="1000" point="60"  money="25" ><spawn num="2"  /><spawn num="2"  /><spawn num="0"  /></wave>
                <wave type="Flying" HP="150"  point="15"  money="4"  ><spawn num="4"  /><spawn num="4"  /><spawn num="4"  /></wave>
                <wave type="Immune" HP="1600"  point="62"  money="30"  ><spawn num="3" /><spawn num="3" /><spawn num="0"  /></wave>
                
                <wave type="Normal" HP="240"  point="12"  money="3"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Fast"   HP="260"  point="12"  money="3"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Fade"   HP="400"  point="12"  money="3"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Fupa" HP="800" point="30" money="18"><spawn num="4"  /><spawn num="4"  /><spawn num="0"  /></wave>
                <wave type="Normal" HP="350"  point="14"  money="4"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Immune" HP="400"  point="14"  money="4"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Swarm"  HP="100"  point="4"  money="1"  ><spawn num="35" /><spawn num="35" /><spawn num="0"  /></wave>
                <wave type="Normal" HP="500"  point="14"  money="4"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Ghost" HP="600"  point="18"  money="8"  ><spawn num="0" /><spawn num="5" /><spawn num="5"  /></wave>
                <wave type="Split" HP="610"  point="8"  money="2"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                
                <wave type="Flying" HP="480"  point="14"  money="4"  ><spawn num="0"  /><spawn num="0"  /><spawn num="20" /></wave>
                <wave type="Fast"   HP="4000" point="150" money="80" ><spawn num="1"  /><spawn num="1"  /><spawn num="0"  /></wave>
                <wave type="Normal" HP="650"  point="15"  money="5"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Fupa" HP="750"  point="15"  money="5"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Immune" HP="900"  point="15"  money="5"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Flying" HP="800"  point="15"  money="5"  ><spawn num="6"  /><spawn num="6"  /><spawn num="6"  /></wave>
                <wave type="Normal" HP="1000" point="15"  money="5"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Immune" HP="1800" point="30"  money="10" ><spawn num="5"  /><spawn num="5"  /><spawn num="0"  /></wave>
                <wave type="Fast"   HP="1200" point="15"  money="6"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Fade" HP="2000" point="20"  money="8"  ><spawn num="20" /><spawn num="20" /><spawn num="0"  /></wave>
                
                <wave type="Swarm"   HP="550" point="5"  money="2"  ><spawn num="45" /><spawn num="45"  /><spawn num="0"  /></wave>
                <wave type="Fast"   HP="1500" point="15"  money="10"  ><spawn num="0"  /><spawn num="20" /><spawn num="0"  /></wave>
                <wave type="Shell" HP="3800" point="15"  money="12"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Immune" HP="7000" point="15"  money="16"  ><spawn num="10" /><spawn num="10" /><spawn num="0"  /></wave>
                <wave type="Detour" HP="1500" point="15"  money="20"  ><spawn num="10"  /><spawn num="0"  /><spawn num="0" /></wave>
                <wave type="Wall" HP="9500" point="15"  money="48"  ><spawn num="4" /><spawn num="4" /><spawn num="0"  /></wave>
                <wave type="Fury"   HP="5300" point="50"  money="52"  ><spawn num="5" /><spawn num="5" /><spawn num="0"  /></wave>
                <wave type="Fupa" HP="4800" point="20" money="35"><spawn num="10"  /><spawn num="10"  /><spawn num="0"  /></wave>
                <wave type="Split" HP="20000"point="200" money="40"><spawn num="3"  /><spawn num="3"  /><spawn num="0"  /></wave>
                <wave type="Decoyer" HP="12000"point="250" money="100"><spawn num="2"  /><spawn num="2"  /><spawn num="2"  /></wave>
            </waves>
        </root>;
        
        // スタート地点の配列を返す
        public static function getStarts():Vector.<Start> {
            var value:Vector.<Start> = new Vector.<Start>();
            for each(var s:XML in Config.XML_DATA.starts.*) {
                value.push(new Start(int(s.@x), int(s.@y), int(s.@width), Boolean(int(s.@flying))));
            }
            return value;
        }
        
        // ゴールの配列を返す
        public static function getGoals():Vector.<Goal> {
            var value:Vector.<Goal> = new Vector.<Goal>();
            for each(var g:XML in Config.XML_DATA.goals.*) {
                value.push(new Goal(int(g.@x), int(g.@y)));
            }
            return value;
        }
        
        //-------------        
        // タワーの種類の配列を返す
        public static function getTowerType():Vector.<TowerType> {
            var value:Vector.<TowerType> = new Vector.<TowerType>();
            for each(var t:XML in Config.XML_DATA.tower.*) {
                value.push(new TowerType(t.@name, Boolean(int(t.@towerbase)),Boolean(int(t.@ground)), Boolean(int(t.@air)), int(t.@slow), int(t.@splash) , int(t.@venom)));
            }
            return value;
        }
        
        // 引数で指定した種類の、ステータスの配列を返す
        public static function getTowerStatus(towerTypeName:String):Vector.<TowerStatus> {
            var value:Vector.<TowerStatus> = new Vector.<TowerStatus>();
            for each(var s:XML in Config.XML_DATA.tower.*.(@name == towerTypeName).*) {
                value.push(new TowerStatus(int(s.@level), int(s.@cost), int(s.@damage), int(s.@range), Number(s.@firerate)));
            }
            //value.sortOn("level", Array.NUMERIC);
            return value;
        }

        //-------------        
        // 敵の種類の連想配列を返す
        public static function getEnemyType():Dictionary {
            var value:Dictionary = new Dictionary();
            for each(var e:XML in Config.XML_DATA.enemy.*) {
                var typeName:String = e.@name;
                value[typeName] = new EnemyType(typeName, Number(e.@speed),  Number(e.@MinSpeed), Number(e.@MaxSpeed),Boolean(int(e.@flying)), Boolean(int(e.@immunity)),int(e.@regeneration),int(e.@fade),Boolean(int(e.@born)),Boolean(int(e.@accelerate)) ) ;
            }
            return value;
        }        
        // 出産能力の連想配列を返す
        public static function getBornAbility():Dictionary {
            var value:Dictionary = new Dictionary();
            for each(var b:XML in Config.XML_DATA.bornAbility.*) {
                var parentName:String = b.@name;
                value[parentName] = new BornAbility( parentName, String(b.@childrenName), Number(b.@childrenHP), Number(b.@childrenPoint), int(b.@amount),  int(b.@limit),  int(b.@intervalBorn), Number(b.@HPrateBorn), Boolean(int(b.@deadBorn)), Boolean(int(b.@descent)), Boolean(int(b.@selfRemove)) );
            }
            return value;
        }
        // 加速能力の連想配列を返す
        public static function getAccelerateAbility():Dictionary {
            var value:Dictionary = new Dictionary();
            for each(var a:XML in Config.XML_DATA.accelerateAbility.*) {
                var runnerName:String = a.@name ;
                value[runnerName] = new AccelerateAbility( runnerName, Number(a.@AddPoint), Number(a.@RatePoint), Number(a.@Angle), int(a.@sineSlip), int(a.@intervalRun), Number(a.@HPrateRun), Number(a.@damageRun));
            }
            return value;
        }               
        //-------------                
        // ウェーブの配列を返す
        public static function getWaves():Vector.<Wave> {
            var waveNumber:int = 1;
            var value:Vector.<Wave> = new Vector.<Wave>();
            for each(var w:XML in Config.XML_DATA.waves.*) {
                var spawn:Vector.<int> = new Vector.<int>();
                for each(var s:XML in w.*) { spawn.push(int(s.@num)); }
                value.push(new Wave(waveNumber, EnemyType.getType(String(w.@type)), int(w.@HP), int(w.@point), int(w.@money), spawn));
                waveNumber++;
            }
            return value;
        }
    }
//}