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

Bomberman test v3

forked from: Bomberman test v2
http://wonderfl.net/c/4Id1
Get Adobe Flash player
by NewKrok 28 Jun 2013
/**
 * Copyright NewKrok ( http://wonderfl.net/user/NewKrok )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/ykq4
 */

// forked from NewKrok's Bomberman test v2
package  {
    
    import caurina.transitions.Tweener;
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.geom.Point;
    import flash.geom.Matrix;
    import flash.geom.Rectangle;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    import flash.ui.Keyboard;

    [SWF(width="465", height="465", frameRate="60", backgroundColor="#000000")]
    public class Bman extends Sprite {

        private var _menu:                        Menu;
        private var _world:                        World;
        private var _terrainData:                Vector.<Vector.<uint>>;
        private var _backgroundElementData:        Vector.<Vector.<int>>;
        
        private var _keyDatas:                    Array = [];
        
        private const _terrainSpriteURL:        String = "http://assets.wonderfl.net/images/related_images/b/bc/bcf7/bcf7f1e72a6f525681121e87b9c8bcc805b6e9da";
        public static var _terrainSpriteBMD:    BitmapData;
        private const _elementSpriteURL:        String = "http://assets.wonderfl.net/images/related_images/1/1f/1f84/1f846fffc06a1af15d3e2cbf53ac556066032ace";
        public static var _elementSpriteBMD:    BitmapData;
        private const _characterSpriteURL:        String = "http://assets.wonderfl.net/images/related_images/4/48/4836/48361bbcee5d9bf4ce0c59975e785b6642e37ccd";
        private var _characterSpriteBMD:        BitmapData;
        private const _bombSpriteURL:            String = "http://assets.wonderfl.net/images/related_images/3/35/35f1/35f19e020a8b93df8362cebbb70a49ac8c683cf3";
        private var _bombSpriteBMD:                BitmapData;
        private const _guiSpriteURL:            String = "http://assets.wonderfl.net/images/related_images/6/64/6479/64794b178ec7808420e149fa9646564a1a3cabe8";
        private var _guiSpriteBMD:                BitmapData;
        
        private var _character:                    BaseUnit;
        
        private var _loading:                   Bitmap;

        public function Bman () :void {
            loadImage ( _guiSpriteURL, guiSpriteLoaded );
        }
        
        private function loadImage ( $url:String, $onComplete:Function ) :void {
            var imageLoader:Loader = new Loader ();
            imageLoader.contentLoaderInfo.addEventListener ( Event.COMPLETE, $onComplete );
            var image:URLRequest = new URLRequest ( $url );
            imageLoader.load ( image, new LoaderContext ( true ) );
        }
        
        private function guiSpriteLoaded ( event:Event ) :void {
            _guiSpriteBMD = new BitmapData ( event.currentTarget.content.width, event.currentTarget.content.height, true, 0x60 );
            _guiSpriteBMD.draw ( event.currentTarget.content );
            addChild ( _loading = new Bitmap ( new BitmapData ( stage.stageWidth, stage.stageHeight, false, 0x000000 ) ) );
            var tmpBitmapData:BitmapData = new BitmapData ( 241, 40, true, 0x60 );
            tmpBitmapData.copyPixels ( _guiSpriteBMD, new Rectangle ( 669, 0, 241, 40 ), new Point ( 0, 0 ) );
            var offsetMatrix:Matrix = new Matrix ();
            offsetMatrix.tx = stage.stageWidth / 2 - tmpBitmapData.width / 2;
            offsetMatrix.ty = stage.stageHeight / 2 - tmpBitmapData.height / 2;
            _loading.bitmapData.draw ( tmpBitmapData, offsetMatrix );
            loadImage ( _terrainSpriteURL, terrainSpriteLoaded );
        }
        
        private function terrainSpriteLoaded ( event:Event ) :void {
            _terrainSpriteBMD = new BitmapData ( event.currentTarget.content.width, event.currentTarget.content.height, true, 0x60 );
            _terrainSpriteBMD.draw ( event.currentTarget.content );
            loadImage ( _elementSpriteURL, elementSpriteLoaded );
        }
        
        private function elementSpriteLoaded ( event:Event ) :void {
            _elementSpriteBMD = new BitmapData ( event.currentTarget.content.width, event.currentTarget.content.height, true, 0x60 );
            _elementSpriteBMD.draw ( event.currentTarget.content );
            loadImage ( _characterSpriteURL, characterSpriteLoaded );
        }
        
        private function characterSpriteLoaded ( event:Event ) :void {
            _characterSpriteBMD = new BitmapData ( event.currentTarget.content.width, event.currentTarget.content.height, true, 0x60 );
            _characterSpriteBMD.draw ( event.currentTarget.content );
            loadImage ( _bombSpriteURL, bombSpriteLoaded );
        }
        
        private function bombSpriteLoaded ( event:Event ) :void {
            _bombSpriteBMD = new BitmapData ( event.currentTarget.content.width, event.currentTarget.content.height, true, 0x60 );
            _bombSpriteBMD.draw ( event.currentTarget.content );
            loaded ();
        }
        
        private function loaded () :void {
            _loading.bitmapData.dispose ();
            removeChild ( _loading );
            _loading = null;
            addChild ( _menu = new Menu ( _guiSpriteBMD, _characterSpriteBMD, startGame ) );
        }
        
        private function startGame ( $characterType:uint ) :void {
            // Set terrain
            _terrainData = new Vector.<Vector.<uint>>;
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            _terrainData.push ( new <uint> [ 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 ] );
            // Set elements
            _backgroundElementData = new Vector.<Vector.<int>>;
            _backgroundElementData.push ( new <int> [ 1, 2,     3,     3,     3,     3,     3,     3,     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     0,     20, 0,     20, 0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     19, 0,     19, 0,     19, 0, 19, 0, 19, 0, 19, 0, 19, 0, 19, 0, 19, 0, 19, 0, 19, 0, 19, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     20, 0,     20, 0,     20, 0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     19, 0,     19, 0,     19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, 19, 0, 19, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     20, 0,     20, 0,     20, 0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     19, 0,     19, 0,     19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, 19, 0, 19, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     20, 0,     20, 0,     20, 0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     19, 0,     19, 0,     19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, 19, 0, 19, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     20, 0,     20, 0,     20, 0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     19, 0,     19, 0,     19,    0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, 19, 0, 19, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     20, 0,     20, 0,     20, 0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     19, 0,     19, 0,     19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, 19, 0, 19, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     20, 0,     20, 0,     20, 0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     19, 0,     19, 0,     19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, 19, 0, 19, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     20, 0,     20, 0,     20, 0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     19, 0,     19, 0,     19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, 19, 0, 19, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     20, 0,     20, 0,     20, 0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     19, 0,     19, 0,     19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, 19, 0, 19, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     20, 0,     20, 0,     20, 0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     19, 0,     19, 0,     19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, 19, 0, 19, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     20, 0,     20, 0,     20, 0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     19, 0,     19, 0,     19, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0, 19, 0, 19, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     20, 0,     20, 0,     20, 0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 6, 7,     0,     19, 0,     19, 0,     19, 0, 19, 0, 19, 0, 19, 0, 19, 0, 19, 0, 19, 0, 19, 0, 19, 0, 19, 0, 8, 9 ] );
            _backgroundElementData.push ( new <int> [ 10, 11,     0,     0,     20,    0,     20,    0,     20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 0, 12, 13 ] );
            _backgroundElementData.push ( new <int> [ 14, 15,     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 18 ] );
            // Set world
            addChild ( _world = new World ( _terrainData[0].length, _terrainData.length, 16, false ) );
            _world.setTerrainSprite ( _terrainSpriteBMD );
            _world.setTerrain ( _terrainData );
            _world.setElementSprite ( _elementSpriteBMD );
            _world.setBackgroundElement ( _backgroundElementData );
            _world.setBombSprite ( _bombSpriteBMD );
            // 1-18 frame graphic
            // 19 hard block
            // 20 destructible block
            _world.blockerElements = new <uint> [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
            _world.destructibleElements = new <uint> [20];
            _world.x = stage.stageWidth;
            _world.y = stage.stageHeight / 2 - _world.height / 2;
            // Add character
            var baseUnitSetting:BaseUnitSetting = new BaseUnitSetting ();
            baseUnitSetting.speed = .2;
            baseUnitSetting.type = $characterType;
            baseUnitSetting.characterSpriteBMD = _characterSpriteBMD;
            _character = _world.addUnit ( new BaseUnit ( baseUnitSetting ) ) as BaseUnit;
            _world.characterMoveTo ( _character, 10, 10, true );
            // Start
            _world.render ();
            Tweener.addTween ( this, { time: .5, x: - stage.stageWidth, onComplete: startAnimationEnded } );
        }
        
        private function startAnimationEnded () :void {
            _world.x = 0;
            x = 0;
            _menu.visible = false;
            stage.addEventListener ( KeyboardEvent.KEY_DOWN, keyDown );
            stage.addEventListener ( KeyboardEvent.KEY_UP, keyUp );
            stage.addEventListener ( Event.ENTER_FRAME, core );
            _keyDatas["UP"] = false;
            _keyDatas["DOWN"] = false;
            _keyDatas["LEFT"] = false;
            _keyDatas["RIGHT"] = false;
            _world.start ();
        }
        
        private function keyDown ( event:KeyboardEvent ) :void {
            switch ( event.keyCode ) {
                case Keyboard.UP:
                    _keyDatas["UP"] = true;
                    break;
                case Keyboard.DOWN:
                    _keyDatas["DOWN"] = true;
                    break;
                case Keyboard.LEFT:
                    _keyDatas["LEFT"] = true;
                    break;
                case Keyboard.RIGHT:
                    _keyDatas["RIGHT"] = true;
                    break;
                case Keyboard.SPACE:
                    _world.addBomb ( _world.convertOptimisedPosition ( new Point ( _character.x, _character.y ), _character.direction ) );
                    break;
            }
        }
        
        private function core ( event:Event ) :void {
            if ( _character.controllEnabled ) {
                if ( _keyDatas["UP"] )
                    _world.characterMoveTo ( _character, -1, _character.nodePosition.y - 1 );
                else if ( _keyDatas["DOWN"] )
                    _world.characterMoveTo ( _character, -1, _character.nodePosition.y + 1 );
                else if ( _keyDatas["LEFT"] )
                    _world.characterMoveTo ( _character, _character.nodePosition.x - 1, -1 );
                else if ( _keyDatas["RIGHT"] )
                    _world.characterMoveTo ( _character, _character.nodePosition.x + 1, -1 );
            }
        }
        
        private function keyUp ( event:KeyboardEvent ) :void {
            switch ( event.keyCode ) {
                case Keyboard.UP:
                    _keyDatas["UP"] = false;
                    break;
                case Keyboard.DOWN:
                    _keyDatas["DOWN"] = false;
                    break;
                case Keyboard.LEFT:
                    _keyDatas["LEFT"] = false;
                    break;
                case Keyboard.RIGHT:
                    _keyDatas["RIGHT"] = false;
                    break;
            }
        }
        
    }
    
}

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
import flash.geom.Matrix;
class World extends Sprite {
    
    private var _clearBitmapData:            BitmapData;
    
    private var _units:                        Vector.<BaseUnit> = new Vector.<BaseUnit>;
    private var _bombs:                        Vector.<Bomb> = new Vector.<Bomb>;
    private var _fires:                        Vector.<Vector.<FireInfo>> = new Vector.<Vector.<FireInfo>>;
    
    private var _terrain:                    Vector.<Vector.<uint>> = new Vector.<Vector.<uint>>;    
    private var _backgroundElements:        Vector.<Vector.<int>> = new Vector.<Vector.<int>>;
    private var _foregroundElements:        Vector.<Vector.<uint>> = new Vector.<Vector.<uint>>;
    public var blockerElements:                Vector.<uint> = new Vector.<uint>;
    public var destructibleElements:        Vector.<uint> = new Vector.<uint>;

    private var _unitContainer:                Sprite;
    private var debugSprite:                Sprite;
    
    private var _world:                        Bitmap;
    
    private var _terrainLayer:                BitmapData;
    private var _backgroundElementLayer:    BitmapData;
    private var _foregroundElementLayer:    BitmapData;
    private var _fireLayer:                    BitmapData;

    private var _terrainSprite:                BitmapData;
    private var _elementSprite:                BitmapData;
    private var _bombSprite:                BitmapData;
    private var _bombSpriteRight:            BitmapData;
    private var _bombSpriteTop:                BitmapData;
    private var _bombSpriteBottom:            BitmapData;

    private var _drawFrom:                    Point = new Point;
    
    private var _nodeSize:                    uint;
    private var _col:                        uint;
    private var _row:                        uint;
    
    private var _debug:                        Boolean;
    private var _backgroundElementLayerIsDirty:        Boolean = true;
    
    public function World ( $col:uint, $row:uint, $nodeSize:uint, $debug:Boolean = false ) :void {
        _col = $col;
        _row = $row;
        for ( var i:uint = 0; i < _row; i++ ) {
            _fires.push ( new Vector.<FireInfo> );
            for ( var j:uint = 0; j < _col; j++ ) {
                _fires[i].push ( null );
            }
        }
        _nodeSize = $nodeSize;
        _clearBitmapData = new BitmapData ( _nodeSize, _nodeSize, true, 0x60 );
        _debug = $debug;
        var worldWidth:uint = $col * $nodeSize;
        var worldHeight:uint = $row * $nodeSize;
        _unitContainer = new Sprite ();
        addChild ( _world = new Bitmap ( new BitmapData ( worldWidth, worldHeight, true, 0x60 ) ) );
        _terrainLayer = new BitmapData ( worldWidth, worldHeight, false );
        _backgroundElementLayer = new BitmapData ( worldWidth, worldHeight, true, 0x60 );
        _foregroundElementLayer = new BitmapData ( worldWidth, worldHeight, true, 0x60 );
        _fireLayer = new BitmapData ( worldWidth, worldHeight, true, 0x60 );
        if ( _debug )
            addChild ( debugSprite = new Sprite () );
    }
    
    public function setTerrainSprite ( $terrainSprite:BitmapData ) :void {
        _terrainSprite = $terrainSprite;
    }

    public function setTerrain ( $terrainData:Vector.<Vector.<uint>> ) :void {
        _terrain = $terrainData;
    }

    public function setElementSprite ( $elementSprite:BitmapData ) :void {
        _elementSprite = $elementSprite;
    }

    public function setBackgroundElement ( $backgroundElements:Vector.<Vector.<int>> ) :void {
        _backgroundElements = $backgroundElements;
    }
    
    public function setBombSprite ( $bombSprite:BitmapData ) :void {
        _bombSprite = $bombSprite;
        _bombSpriteRight = new BitmapData ( 160, 16, true, 0x60 );
        var tmpBMD:BitmapData = new BitmapData ( _bombSpriteRight.width, _bombSpriteRight.height, true, 0x60 )
        _bombSpriteRight.copyPixels ( _bombSprite, new Rectangle ( 130, 0, 160, 16 ), new Point ( 0, 0 ) );
        var rotationMatrix:Matrix = new Matrix ();
        rotationMatrix.rotate ( Math.PI );
        rotationMatrix.translate ( _bombSpriteRight.width, _bombSpriteRight.height );
        tmpBMD.draw ( _bombSpriteRight, rotationMatrix );
        _bombSpriteRight.dispose ();
        _bombSpriteRight = tmpBMD;
        _bombSpriteTop = new BitmapData ( 160, 16, true, 0x60 );
        tmpBMD = new BitmapData ( _bombSpriteRight.height, _bombSpriteRight.width, true, 0x60 )
        _bombSpriteTop.copyPixels ( _bombSprite, new Rectangle ( 130, 0, 160, 16 ), new Point ( 0, 0 ) );
        rotationMatrix = new Matrix ();
        rotationMatrix.rotate ( Math.PI / 2 );
        rotationMatrix.translate ( _bombSpriteRight.height, 0 );
        tmpBMD.draw ( _bombSpriteTop, rotationMatrix );
        _bombSpriteTop.dispose ();
        _bombSpriteTop = tmpBMD;
        _bombSpriteBottom = new BitmapData ( 160, 160, true, 0x60 );
        tmpBMD = new BitmapData ( _bombSpriteRight.height, _bombSpriteRight.width, true, 0x60 )
        _bombSpriteBottom.copyPixels ( _bombSprite, new Rectangle ( 130, 0, 160, 16 ), new Point ( 0, 0 ) );
        rotationMatrix = new Matrix ();
        rotationMatrix.rotate ( -Math.PI / 2 );
        rotationMatrix.translate ( 0, _bombSpriteRight.width );
        tmpBMD.draw ( _bombSpriteBottom, rotationMatrix );
        _bombSpriteBottom.dispose ();
        _bombSpriteBottom = tmpBMD;
    }
    
    public function addUnit ( $unit:BaseUnit ) :BaseUnit {
        _units.push ( _unitContainer.addChild ( $unit ) as BaseUnit );
        _units[_units.length -1].setNodeSize ( _nodeSize );
        return _units[_units.length -1];
    }
    
    public function addBomb ( $position:Point ) :Bomb {
        if ( !isBlocker ( _backgroundElements[$position.y][$position.x] ) ) {
            _backgroundElements[$position.y][$position.x] = -1;
            var bombSetting:BombSetting = new BombSetting ();
            bombSetting.characterSpriteBMD = _bombSprite;
            _bombs.push ( _unitContainer.addChildAt ( new Bomb ( $position, bombSetting ), 0 ) as Bomb );
            Tweener.addTween ( _bombs[_bombs.length -1], { time: bombSetting.lifeTime, onComplete: activateBomb, onCompleteParams: [_bombs[_bombs.length -1]] } );
            _bombs[_bombs.length -1].x = $position.x * _nodeSize;
            _bombs[_bombs.length -1].y = $position.y * _nodeSize;
            return _bombs[_bombs.length -1];
        } else
            return null;
    }
    
    private function activateBomb ( $bomb:Bomb ) :void {
        Tweener.removeTweens ( $bomb );
        var length:int = _bombs.length;
        var selectedBomb:Bomb;
        for ( var i:int = 0; i < length; i++ ) {
            if ( _bombs[i] == $bomb ) {
                selectedBomb = _bombs[i];
                _backgroundElements[selectedBomb.position.y][selectedBomb.position.x] = 0;
                _fires[selectedBomb.position.y][selectedBomb.position.x] = new FireInfo ( 0 );
                damage ( selectedBomb.position.x, selectedBomb.position.y, selectedBomb.damage );
                var tmpPosition:Point = new Point ();
                tmpPosition.x = selectedBomb.position.x;
                tmpPosition.y = selectedBomb.position.y;
                var fireLength:uint = selectedBomb.fireLength
                for ( var j:uint = 0; j < fireLength; j++ ) {
                    tmpPosition.x--;
                    if ( isDestructible ( _backgroundElements[tmpPosition.y][tmpPosition.x] ) ) {
                        _backgroundElements[tmpPosition.y][tmpPosition.x] = 0;
                        _backgroundElementLayer.copyPixels ( _clearBitmapData, new Rectangle ( 0, 0, _nodeSize, _nodeSize ), new Point ( tmpPosition.x * _nodeSize, tmpPosition.y * _nodeSize ) );
                        _fires[tmpPosition.y][tmpPosition.x] = new FireInfo ( 2 );
                        break;
                    } else if ( _backgroundElements[tmpPosition.y][tmpPosition.x] == -1 ) {
                        var bombLength:uint = _bombs.length;
                        for ( var k:uint = 0; k < bombLength; k++ ) {
                            if ( _bombs[k].position.x == tmpPosition.x && _bombs[k].position.y == tmpPosition.y ) {
                                Tweener.addTween ( this, { time: .1, onComplete: activateBomb, onCompleteParams: [ _bombs[k] ] } );
                                break;
                            }
                        }
                    } else if ( !isBlocker ( _backgroundElements[tmpPosition.y][tmpPosition.x] ) ) {
                        if ( _fires[tmpPosition.y][tmpPosition.x] != null && ( _fires[tmpPosition.y][tmpPosition.x].type == 1 || _fires[tmpPosition.y][tmpPosition.x].type == 2 ) )
                            break;
                        _fires[tmpPosition.y][tmpPosition.x] = new FireInfo ( j < fireLength - 1 ? 1 : 2 );
                        damage ( tmpPosition.x, tmpPosition.y, selectedBomb.damage );
                    } else
                        break;
                }
                tmpPosition.x = selectedBomb.position.x;
                for ( j = 0; j < fireLength; j++ ) {
                    tmpPosition.x++;
                    if ( isDestructible ( _backgroundElements[tmpPosition.y][tmpPosition.x] ) ) {
                        _backgroundElements[tmpPosition.y][tmpPosition.x] = 0;
                        _backgroundElementLayer.copyPixels ( _clearBitmapData, new Rectangle ( 0, 0, _nodeSize, _nodeSize ), new Point ( tmpPosition.x * _nodeSize, tmpPosition.y * _nodeSize ) );
                        _fires[tmpPosition.y][tmpPosition.x] = new FireInfo ( 4 );
                        break;
                    } else if ( _backgroundElements[tmpPosition.y][tmpPosition.x] == -1 ) {
                        bombLength = _bombs.length;
                        for ( k = 0; k < bombLength; k++ ) {
                            if ( _bombs[k].position.x == tmpPosition.x && _bombs[k].position.y == tmpPosition.y ) {
                                Tweener.addTween ( this, { time: .1, onComplete: activateBomb, onCompleteParams: [ _bombs[k] ] } );
                                break;
                            }
                        }
                    } else if ( !isBlocker ( _backgroundElements[tmpPosition.y][tmpPosition.x] ) ) {
                        if ( _fires[tmpPosition.y][tmpPosition.x] != null && ( _fires[tmpPosition.y][tmpPosition.x].type == 3 || _fires[tmpPosition.y][tmpPosition.x].type == 4 ) )
                            break;
                        _fires[tmpPosition.y][tmpPosition.x] = new FireInfo ( j < fireLength - 1 ? 3 : 4 );
                        damage ( tmpPosition.x, tmpPosition.y, selectedBomb.damage );
                    } else
                        break;
                }
                tmpPosition.x = selectedBomb.position.x;
                tmpPosition.y = selectedBomb.position.y;
                for ( j = 0; j < fireLength; j++ ) {
                    tmpPosition.y--;
                    if ( isDestructible ( _backgroundElements[tmpPosition.y][tmpPosition.x] ) ) {
                        _backgroundElements[tmpPosition.y][tmpPosition.x] = 0;
                        _backgroundElementLayer.copyPixels ( _clearBitmapData, new Rectangle ( 0, 0, _nodeSize, _nodeSize ), new Point ( tmpPosition.x * _nodeSize, tmpPosition.y * _nodeSize ) );
                        _fires[tmpPosition.y][tmpPosition.x] = new FireInfo ( 6 );
                        break;
                    } else if ( _backgroundElements[tmpPosition.y][tmpPosition.x] == -1 ) {
                        bombLength = _bombs.length;
                        for ( k = 0; k < bombLength; k++ ) {
                            if ( _bombs[k].position.x == tmpPosition.x && _bombs[k].position.y == tmpPosition.y ) {
                                Tweener.addTween ( this, { time: .1, onComplete: activateBomb, onCompleteParams: [ _bombs[k] ] } );
                                break;
                            }
                        }
                    } else if ( !isBlocker ( _backgroundElements[tmpPosition.y][tmpPosition.x] ) ) {
                        if ( _fires[tmpPosition.y][tmpPosition.x] != null && ( _fires[tmpPosition.y][tmpPosition.x].type == 5 || _fires[tmpPosition.y][tmpPosition.x].type == 6 ) )
                            break;
                        _fires[tmpPosition.y][tmpPosition.x] = new FireInfo ( j < fireLength - 1 ? 5 : 6 );
                        damage ( tmpPosition.x, tmpPosition.y, selectedBomb.damage );
                    } else
                        break;
                }
                tmpPosition.y = selectedBomb.position.y;
                for ( j = 0; j < fireLength; j++ ) {
                    tmpPosition.y++;
                    if ( isDestructible ( _backgroundElements[tmpPosition.y][tmpPosition.x] ) ) {
                        _backgroundElements[tmpPosition.y][tmpPosition.x] = 0;
                        _backgroundElementLayer.copyPixels ( _clearBitmapData, new Rectangle ( 0, 0, _nodeSize, _nodeSize ), new Point ( tmpPosition.x * _nodeSize, tmpPosition.y * _nodeSize ) );
                        _fires[tmpPosition.y][tmpPosition.x] = new FireInfo ( 8 );
                        break;
                    } else if ( _backgroundElements[tmpPosition.y][tmpPosition.x] == -1 ) {
                        bombLength = _bombs.length;
                        for ( k = 0; k < bombLength; k++ ) {
                            if ( _bombs[k].position.x == tmpPosition.x && _bombs[k].position.y == tmpPosition.y ) {
                                Tweener.addTween ( this, { time: .1, onComplete: activateBomb, onCompleteParams: [ _bombs[k] ] } );
                                break;
                            }
                        }
                    } else if ( !isBlocker ( _backgroundElements[tmpPosition.y][tmpPosition.x] ) ) {
                        if ( _fires[tmpPosition.y][tmpPosition.x] != null && ( _fires[tmpPosition.y][tmpPosition.x].type == 7 || _fires[tmpPosition.y][tmpPosition.x].type == 8 ) )
                            break;
                        _fires[tmpPosition.y][tmpPosition.x] = new FireInfo ( j < fireLength - 1 ? 7 : 8 );
                        damage ( tmpPosition.x, tmpPosition.y, selectedBomb.damage );
                    } else
                        break;
                }
                for ( var l:uint = 0; l < _bombs.length; l++ ) {
                    if ( _bombs[l] == selectedBomb )
                        _bombs.splice ( l, 1 );
                }
                selectedBomb.dispose ();
                selectedBomb = null;
                length--;
                i = 0;
                break;
            }
        }
    }
    
    private function damage ( $x:Number, $y:Number, $damage:Number ) :void {
        var length:uint = _units.length;
        for ( var i:uint; i < length; i++ ) {
            if ( _units[i].nodePosition.x == $x && _units[i].nodePosition.y == $y )
                _units[i].damage ( $damage );
        }
    }
    
    public function convertOptimisedPosition ( $position:Point, $direction:String ) :Point {
        var point:Point = new Point ();
        switch ( $direction ) {
            case BaseUnit.LT:
            case BaseUnit.RT:
                point.x = Math.round ( $position.x / _nodeSize );
                point.y = Math.ceil ( $position.y / _nodeSize );
                break;
            case BaseUnit.LB:
            case BaseUnit.RB:
                point.x = Math.round ( $position.x / _nodeSize );
                point.y = Math.floor ( $position.y / _nodeSize );
                break;
            case BaseUnit.L:
                point.x = Math.ceil ( $position.x / _nodeSize );
                point.y = Math.round ( $position.y / _nodeSize );
                break;
            case BaseUnit.R:
                point.x = Math.floor ( $position.x / _nodeSize );
                point.y = Math.round ( $position.y / _nodeSize );
                break;
        }
        return point;
    }
    
    public function start () :void {
        addEventListener ( Event.ENTER_FRAME, core );
    }
    
    public function pause () :void {
        removeEventListener ( Event.ENTER_FRAME, core );
    }
    
    public function characterMoveTo ( $character:BaseUnit, $x:int, $y:int, $instant:Boolean = false ) :void {
        if ( !$character.controllEnabled )
            return;
        $x = $x == -1 ? $character.nodePosition.x : $x;
        $y = $y == -1 ? $character.nodePosition.y : $y;
        if ( !isBlocker ( _backgroundElements[$y][$x] ) )
            $character.moveTo ( $x, $y, $instant );
    }
    
    private function isBlocker ( $elementID:int ) :Boolean {
        return $elementID == -1 ? true : blockerElements.indexOf ( $elementID ) != -1;
    }
    
    private function isDestructible ( $elementID:int ) :Boolean {
        return destructibleElements.indexOf ( $elementID ) != -1;
    }
    
    private function core ( event:Event ) :void {
        var length:uint = _units.length;
        for ( var i:uint = 0; i < length; i++ ) {
            if ( !_units[i].controllEnabled )
                _units[i].update ();
        }                
        length = _bombs.length;
        for ( i = 0; i < length; i++ )
            _bombs[i].update ();
        
        for ( i = 0; i < _row; i++ ) {
            _fires.push ( new Vector.<FireInfo> );
            for ( var j:uint = 0; j < _col; j++ ) {
                if ( _fires[i][j] != null ) {
                    _fires[i][j].animationDelay++;
                    if ( _fires[i][j].animationDelay == _fires[i][j].animationMaxDelay ) {
                        _fires[i][j].animationIndex++;
                        _fires[i][j].animationDelay = 0;
                    }
                }
            }
        }
        render ();
    }
    
    public function render () :void {
        _world.bitmapData.lock ();
        var length:uint = _col;
        var innerLength:uint = _row;
        _terrainLayer.lock ();
        for ( var i:uint = 0; i < length; i++ ) {
             for ( var j:uint = 0; j < innerLength; j++ ) {
                 var selectedElement:uint = _terrain[j][i] - 1;
                 if ( selectedElement != -1 )
                     _terrainLayer.copyPixels ( _terrainSprite, new Rectangle ( selectedElement * _nodeSize, 0, _nodeSize, _nodeSize ), new Point ( i * _nodeSize, j * _nodeSize ) );
             }
        }
        _terrainLayer.unlock ();
        _world.bitmapData.draw ( _terrainLayer );
        if ( _backgroundElementLayerIsDirty ) {
            _backgroundElementLayerIsDirty = false;
            _backgroundElementLayer.lock ();
            if ( _debug )
                debugSprite.graphics.clear ();
            for ( i = 0; i < length; i++ ) {
                for ( j = 0; j < innerLength; j++ ) {
                    selectedElement = _backgroundElements[j][i] - 1;
                    if ( selectedElement != -1 ) {
                        if ( _debug ) {
                            debugSprite.graphics.lineStyle ( 1, 0, .1 )
                            debugSprite.graphics.drawRect ( i * _nodeSize, j * _nodeSize, _nodeSize, _nodeSize )
                        }
                        _backgroundElementLayer.copyPixels ( _elementSprite, new Rectangle ( selectedElement * _nodeSize, 0, _nodeSize, _nodeSize ), new Point ( i * _nodeSize, j * _nodeSize ) );
                    }
                }
            }
            _backgroundElementLayer.unlock ();
        }
        _world.bitmapData.draw ( _backgroundElementLayer );
        _world.bitmapData.draw ( _unitContainer );
        _fireLayer.lock ();
        _fireLayer.copyPixels ( new BitmapData ( _fireLayer.width, _fireLayer.height, true, 0x60 ), new Rectangle ( 0, 0, _fireLayer.width, _fireLayer.height ), new Point );
        for ( i = 0; i < length; i++ ) {
            for ( j = 0; j < innerLength; j++ ) {
                if ( _fires[j][i] ) {
                    var newAnimationIndex:uint = _fires[j][i].animationIndex < _fires[j][i].frames / 2 ? _fires[j][i].animationIndex : _fires[j][i].frames - _fires[j][i].animationIndex;
                    if ( _fires[j][i].animationIndex == _fires[j][i].frames ) {
                        _fires[j][i] = null;
                        _fireLayer.copyPixels ( _clearBitmapData, new Rectangle ( 0, 0, _nodeSize, _nodeSize ), new Point ( i * _nodeSize, j * _nodeSize ) );
                    } else {
                        switch ( _fires[j][i].type ) {
                            case 0:
                                _fireLayer.copyPixels ( _bombSprite, new Rectangle ( 50 + newAnimationIndex * _nodeSize, 0, _nodeSize, _nodeSize ), new Point ( i * _nodeSize, j * _nodeSize ), null, null, true );                        
                                break;
                            case 1:
                                _fireLayer.copyPixels ( _bombSprite, new Rectangle ( 130 + newAnimationIndex * _nodeSize, 0, _nodeSize, _nodeSize ), new Point ( i * _nodeSize, j * _nodeSize ), null, null, true );                        
                                break;
                            case 2:
                                _fireLayer.copyPixels ( _bombSprite, new Rectangle ( 210 + newAnimationIndex * _nodeSize, 0, _nodeSize, _nodeSize ), new Point ( i * _nodeSize, j * _nodeSize ), null, null, true );                        
                                break;
                            case 3:
                                _fireLayer.copyPixels ( _bombSpriteRight, new Rectangle ( _bombSpriteRight.width - newAnimationIndex * _nodeSize - _nodeSize, 0, _nodeSize, _nodeSize ), new Point ( i * _nodeSize, j * _nodeSize ), null, null, true );                        
                                break;
                            case 4:
                                _fireLayer.copyPixels ( _bombSpriteRight, new Rectangle ( _bombSpriteRight.width - 80 - newAnimationIndex * _nodeSize - _nodeSize, 0, _nodeSize, _nodeSize ), new Point ( i * _nodeSize, j * _nodeSize ), null, null, true );                        
                                break;
                            case 5:
                                _fireLayer.copyPixels ( _bombSpriteTop, new Rectangle ( 0, newAnimationIndex * _nodeSize, _nodeSize, _nodeSize ), new Point ( i * _nodeSize, j * _nodeSize ), null, null, true );                        
                                break;
                            case 6:
                                _fireLayer.copyPixels ( _bombSpriteTop, new Rectangle ( 0, 80 + newAnimationIndex * _nodeSize, _nodeSize, _nodeSize ), new Point ( i * _nodeSize, j * _nodeSize ), null, null, true );                        
                                break;
                            case 7:
                                _fireLayer.copyPixels ( _bombSpriteBottom, new Rectangle ( 0, _bombSpriteRight.width - newAnimationIndex * _nodeSize - _nodeSize, _nodeSize, _nodeSize ), new Point ( i * _nodeSize, j * _nodeSize ), null, null, true );                        
                                break;
                            case 8:
                                _fireLayer.copyPixels ( _bombSpriteBottom, new Rectangle ( 0, _bombSpriteRight.width - 80 - newAnimationIndex * _nodeSize - _nodeSize, _nodeSize, _nodeSize ), new Point ( i * _nodeSize, j * _nodeSize ), null, null, true );                        
                                break;
                        }
                    }
                }
            }
        }
        _fireLayer.unlock ();
        _world.bitmapData.draw ( _fireLayer );
        _world.bitmapData.unlock ();
    }
    
}

import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import caurina.transitions.Tweener;
class BaseUnit extends Sprite {
    
    public static const LT:                 String = "BaseUnit.LT";
    public static const RT:                 String = "BaseUnit.RT";
    public static const L:                  String = "BaseUnit.L";
    public static const R:                  String = "BaseUnit.R";
    public static const LB:                 String = "BaseUnit.LB";
    public static const RB:                 String = "BaseUnit.RB";
    
    private var _characterSpriteSetting:    CharacterSpriteSetting;
    private var _baseUnitSettings:            BaseUnitSetting;
    
    private var characterSprite:            BitmapData;
    private var characterBitmap:            Bitmap;
    
    private var _nodePosition:                Point = new Point;
    
    private var _direction:                 String;
    
    public var characterRotation:           Number = 0;
    
    private var animationIndex:             int = 0;
    private var animationDelay:             uint = 0;
    
    public var rotateUnit:                  Boolean = false;
    private var _controllEnabled:            Boolean = true;
    private var invulnerable:                Boolean = false;
    
    public function BaseUnit ( $baseUnitSettings:BaseUnitSetting ) :void {
        _baseUnitSettings = $baseUnitSettings;
        _characterSpriteSetting = new CharacterSpriteSetting ();
        _characterSpriteSetting.baseBitmapData = _baseUnitSettings.characterSpriteBMD;
        _characterSpriteSetting.animationDelay = 4;
        _characterSpriteSetting.startDirection = BaseUnit.LB;
        _characterSpriteSetting.spriteSize = new Point ( 18, 26 );
        _characterSpriteSetting.spriteOffset = new Point ( 0, -11 );
        _characterSpriteSetting.moveAnimationLTStartPoint = new Point ( 167, 0 );
        _characterSpriteSetting.moveAnimationLTFrameCount = 3;
        _characterSpriteSetting.moveAnimationRTStartPoint = new Point ( 167, 0 );
        _characterSpriteSetting.moveAnimationRTFrameCount = 3;
        _characterSpriteSetting.moveAnimationLStartPoint = new Point ( 55, 0 );
        _characterSpriteSetting.moveAnimationLFrameCount = 3;
        _characterSpriteSetting.moveAnimationRStartPoint = new Point ( 109, 0 );
        _characterSpriteSetting.moveAnimationRFrameCount = 3;
        _characterSpriteSetting.moveAnimationLBStartPoint = new Point ( 0, 0 );
        _characterSpriteSetting.moveAnimationLBFrameCount = 3;
        _characterSpriteSetting.moveAnimationRBStartPoint = new Point ( 0, 0 );
        _characterSpriteSetting.moveAnimationRBFrameCount = 3;
        _characterSpriteSetting.reverseAtEnd = true;
        setCharacterSprite ( _characterSpriteSetting );
    }
    
    public function update () :void {
        updateGraphic ();
    }
    
    public function setNodeSize ( $size:Number ) :void {
        _baseUnitSettings.nodeSize = $size;
    }
    
    public function damage ( $value:Number ) :void {
        if ( !invulnerable ) {
            for ( var i:uint; i < 21; i++ ) {
                Tweener.addTween ( this, { alpha: i % 2 != 0 ? .1 : 1, time: .2, delay: i * .2, onComplete: i == 4 ? resetFromDamage : null } );
            }
        }
    }
    
    private function resetFromDamage () :void {
        invulnerable = false;
        alpha = 1;
    }
    
    public function moveTo ( $x:int, $y:int, $instant:Boolean = false ) :void {
        if ( _controllEnabled ) {
            $x = $x == -1 ? _nodePosition.x : $x;
            $y = $y == -1 ? _nodePosition.y : $y;
            var tmpDirection:String = direction;
            if ( _nodePosition.y > $y ) {
                if ( _nodePosition.x > $x )
                    tmpDirection = BaseUnit.LT;
                else if ( _nodePosition.x < $x )
                    tmpDirection = BaseUnit.RT;
                else
                    tmpDirection = BaseUnit.RT;
            } else if ( _nodePosition.y < $y ) {
                if ( _nodePosition.x > $x )
                    tmpDirection = BaseUnit.LB;
                else if ( _nodePosition.x < $x )
                    tmpDirection = BaseUnit.RB;
                else
                    tmpDirection = BaseUnit.RB;
            } else if ( _nodePosition.x > $x ) {
                if ( _nodePosition.y > $y )
                    tmpDirection = BaseUnit.LT;
                else if ( _nodePosition.y < $y )
                    tmpDirection = BaseUnit.LB;
                else
                    tmpDirection = BaseUnit.L;
            } else if ( _nodePosition.x < $x ) {
                if ( _nodePosition.y > $y )
                    tmpDirection = BaseUnit.LT;
                else if ( _nodePosition.y < $y )
                    tmpDirection = BaseUnit.RB;
                else
                    tmpDirection = BaseUnit.R;
            }
            if ( tmpDirection != direction ) {
                direction = tmpDirection;
                update ();
            }
            _nodePosition.x = $x;
            _nodePosition.y = $y;
            if ( $instant ) {
                x = $x * _baseUnitSettings.nodeSize;
                y = $y * _baseUnitSettings.nodeSize;
            } else {
                _controllEnabled = false;
                Tweener.addTween ( this, { x: $x * _baseUnitSettings.nodeSize, y: $y * _baseUnitSettings.nodeSize, time: _baseUnitSettings.speed, onComplete: resetControll, transition: "linear" } );
            }
        }
    }
    
    private function resetControll () :void {
        _controllEnabled = true;
    }
    
    public function setCharacterSprite ( $characterSpriteSetting:CharacterSpriteSetting ) :void {
        _characterSpriteSetting = $characterSpriteSetting;
        characterSprite = _characterSpriteSetting.baseBitmapData;
        characterBitmap = new Bitmap ();
        characterBitmap.bitmapData = new BitmapData ( _characterSpriteSetting.spriteSize.x, _characterSpriteSetting.spriteSize.y, true, 0x60 );
        addChild ( characterBitmap );
        characterBitmap.x = _characterSpriteSetting.spriteOffset.x;
        characterBitmap.y = _characterSpriteSetting.spriteOffset.y;
        direction = _characterSpriteSetting.startDirection;
        updateGraphic ( true );
    }
    
    private function updateGraphic ( $forceRefresh:Boolean = false ) :void {
        animationDelay++;
        if ( $forceRefresh )
            animationDelay = _characterSpriteSetting.animationDelay + 1;
        if ( animationDelay > _characterSpriteSetting.animationDelay ) {
            switch ( characterRotation ) {
                case 180:
                    _direction = L;
                    break;
                case 0:
                    _direction = R;
                    break;
                case -120:
                    _direction = LT;
                    break;
                case -45:
                    _direction = RT;
                    break;
                case 135:
                    _direction = LB;
                    break;
                case 60:
                    _direction = RB;
                    break;
            }
            animationDelay = 0;
            characterBitmap.bitmapData.dispose ();
            characterBitmap.bitmapData = new BitmapData ( _characterSpriteSetting.spriteSize.x, _characterSpriteSetting.spriteSize.y, true, 0x60 );
            var copyRectangle:Rectangle = new Rectangle ( 0, 0, _characterSpriteSetting.spriteSize.x, _characterSpriteSetting.spriteSize.y );
            switch ( _direction ) {
                case LT:
                    if ( animationIndex >= _characterSpriteSetting.moveAnimationLTFrameCount ) {
                        if ( _characterSpriteSetting.reverseAtEnd ) {
                            _characterSpriteSetting.animationDirection *= -1;
                            animationIndex -= 2;
                        } else
                            animationIndex = 0;
                    }
                    if ( animationIndex < 0 && _characterSpriteSetting.reverseAtEnd ) {
                        _characterSpriteSetting.animationDirection *= -1;
                        animationIndex += 2;
                    }
                    copyRectangle.x = _characterSpriteSetting.moveAnimationLTStartPoint.x + animationIndex * _characterSpriteSetting.spriteSize.x;
                    copyRectangle.y = _characterSpriteSetting.moveAnimationLTStartPoint.y + _baseUnitSettings.type * _characterSpriteSetting.spriteSize.y;
                    break;
                case RT:
                    if ( animationIndex >= _characterSpriteSetting.moveAnimationRTFrameCount ) {
                        if ( _characterSpriteSetting.reverseAtEnd ) {
                            _characterSpriteSetting.animationDirection *= -1;
                            animationIndex -= 2;
                        } else
                            animationIndex = 0;
                    }
                    if ( animationIndex < 0 && _characterSpriteSetting.reverseAtEnd ) {
                        _characterSpriteSetting.animationDirection *= -1;
                        animationIndex += 2;
                    }
                    copyRectangle.x = _characterSpriteSetting.moveAnimationRTStartPoint.x + animationIndex * _characterSpriteSetting.spriteSize.x;
                    copyRectangle.y = _characterSpriteSetting.moveAnimationRTStartPoint.y + _baseUnitSettings.type * _characterSpriteSetting.spriteSize.y;
                    break;
                case L:
                    if ( animationIndex >= _characterSpriteSetting.moveAnimationLFrameCount ) {
                        if ( _characterSpriteSetting.reverseAtEnd ) {
                            _characterSpriteSetting.animationDirection *= -1;
                            animationIndex -= 2;
                        } else
                            animationIndex = 0;
                    }
                    if ( animationIndex < 0 && _characterSpriteSetting.reverseAtEnd ) {
                        _characterSpriteSetting.animationDirection *= -1;
                        animationIndex += 2;
                    }
                    copyRectangle.x = _characterSpriteSetting.moveAnimationLStartPoint.x + animationIndex * _characterSpriteSetting.spriteSize.x;
                    copyRectangle.y = _characterSpriteSetting.moveAnimationLStartPoint.y + _baseUnitSettings.type * _characterSpriteSetting.spriteSize.y;
                    break;
                case R:
                    if ( animationIndex >= _characterSpriteSetting.moveAnimationRFrameCount ) {
                        if ( _characterSpriteSetting.reverseAtEnd ) {
                            _characterSpriteSetting.animationDirection *= -1;
                            animationIndex -= 2;
                        } else
                            animationIndex = 0;
                    }
                    if ( animationIndex < 0 && _characterSpriteSetting.reverseAtEnd ) {
                        _characterSpriteSetting.animationDirection *= -1;
                        animationIndex += 2;
                    }
                    copyRectangle.x = _characterSpriteSetting.moveAnimationRStartPoint.x + animationIndex * _characterSpriteSetting.spriteSize.x;
                    copyRectangle.y = _characterSpriteSetting.moveAnimationRStartPoint.y + _baseUnitSettings.type * _characterSpriteSetting.spriteSize.y;
                    break;
                case LB:
                    if ( animationIndex >= _characterSpriteSetting.moveAnimationLBFrameCount ) {
                        if ( _characterSpriteSetting.reverseAtEnd ) {
                            _characterSpriteSetting.animationDirection *= -1;
                            animationIndex -= 2;
                        } else
                            animationIndex = 0;
                    }
                    if ( animationIndex < 0 && _characterSpriteSetting.reverseAtEnd ) {
                        _characterSpriteSetting.animationDirection *= -1;
                        animationIndex += 2;
                    }
                    copyRectangle.x = _characterSpriteSetting.moveAnimationLBStartPoint.x + animationIndex * _characterSpriteSetting.spriteSize.x;
                    copyRectangle.y = _characterSpriteSetting.moveAnimationLBStartPoint.y + _baseUnitSettings.type * _characterSpriteSetting.spriteSize.y;
                    break;
                case RB:
                    if ( animationIndex >= _characterSpriteSetting.moveAnimationRBFrameCount ) {
                        if ( _characterSpriteSetting.reverseAtEnd ) {
                            _characterSpriteSetting.animationDirection *= -1;
                            animationIndex -= 2;
                        } else
                            animationIndex = 0;
                    }
                    if ( animationIndex < 0 && _characterSpriteSetting.reverseAtEnd ) {
                        _characterSpriteSetting.animationDirection *= -1;
                        animationIndex += 2;
                    }
                    copyRectangle.x = _characterSpriteSetting.moveAnimationRBStartPoint.x + animationIndex * _characterSpriteSetting.spriteSize.x;
                    copyRectangle.y = _characterSpriteSetting.moveAnimationRBStartPoint.y + _baseUnitSettings.type * _characterSpriteSetting.spriteSize.y;
                    break;
            }
            animationIndex += _characterSpriteSetting.animationDirection;
            characterBitmap.bitmapData.copyPixels ( characterSprite, copyRectangle, new Point ( 0, 0 ) );
        }
    }
    
    public function get direction () :String {
        return _direction;
    }
    
    public function set direction ( $direction:String ) :void {
        _direction = $direction;
        switch ( $direction ) {
            case L:
                characterRotation = 180;
                break;
            case R:
                characterRotation = 0;
                break;
            case LT:
                characterRotation = -120;
                break;
            case RT:
                characterRotation = -45;
                break;
            case LB:
                characterRotation = 135;
                break;
            case RB:
                characterRotation = 60;
                break;
        }
        animationDelay = _characterSpriteSetting.animationDelay
        if ( rotateUnit )
            rotation = characterRotation;
    }
    
    public function get controllEnabled () :Boolean {
        return _controllEnabled;
    }

    public function get nodePosition () :Point {
        return _nodePosition;
    }
    
}

import flash.geom.Point;
import flash.display.BitmapData;
class CharacterSpriteSetting {
    
    public var baseBitmapData:                BitmapData;
    
    public var moveAnimationLTStartPoint:    Point; // Left Top
    public var moveAnimationRTStartPoint:    Point; // Right Top
    public var moveAnimationLStartPoint:    Point; // Left
    public var moveAnimationRStartPoint:    Point; // Right
    public var moveAnimationLBStartPoint:    Point; // Left Bottom
    public var moveAnimationRBStartPoint:    Point; // Right Bottom
    public var spriteSize:                    Point;
    public var spriteOffset:                Point;
    
    public var startDirection:                String;
    
    public var animationDelay:                uint;
    public var moveAnimationLTFrameCount:    uint; // Left Top
    public var moveAnimationRTFrameCount:    uint; // Right Top
    public var moveAnimationLFrameCount:    uint; // Left
    public var moveAnimationRFrameCount:    uint; // Right
    public var moveAnimationLBFrameCount:    uint; // Left Bottom
    public var moveAnimationRBFrameCount:    uint; // Right Bottom
    
    public var reverseAtEnd:                Boolean = false;
    public var animationDirection:            int = 1;
    
}

import flash.display.BitmapData;
class BaseUnitSetting {
    public var characterSpriteBMD:    BitmapData
    public var speed:                 Number;
    public var nodeSize:            Number;
    public var type:                uint = 0;
}

import flash.display.BitmapData;
class BombSetting {
    public var characterSpriteBMD:    BitmapData;
    public var lifeTime:            Number = 5;
    public var fireLength:            Number = 3;
    public var damage:                Number = 1;
}

class FireInfo {
    public var type:                uint = 0; // 0:center | 1:left-middle | 2:left-end | 3:right-middle | 4:right-end | 5:top-middle | 6:top-end | 7:bottom-middle | 8:bottom-end
    public var animationIndex:        uint = 0;
    public var animationDelay:        uint = 0;
    public var animationMaxDelay:    uint = 4;
    public var frames:                uint = 9;
    public function FireInfo ( $type:uint ) :void {
        type = $type;
    }
}

import flash.geom.Point;
import flash.display.Sprite;
class Bomb extends Sprite {
    
    private var _characterSpriteSetting:    CharacterSpriteSetting;
    private var _bombSetting:               BombSetting;
    
    private var characterSprite:            BitmapData;
    private var characterBitmap:            Bitmap;
    
    private var _position:                    Point;
    
    private var animationIndex:             int = 0;
    
    private var animationDelay:             uint = 0;
    
    private var _activated:                    Boolean = false;
    
    public function Bomb ( $position:Point, $bombSetting:BombSetting ) :void {
        _position = $position;
        _bombSetting = $bombSetting;
        _characterSpriteSetting = new CharacterSpriteSetting ();
        _characterSpriteSetting.baseBitmapData = $bombSetting.characterSpriteBMD;
        _characterSpriteSetting.animationDelay = 8;
        _characterSpriteSetting.startDirection = BaseUnit.LT;
        _characterSpriteSetting.spriteSize = new Point ( 16, 17 );
        _characterSpriteSetting.spriteOffset = new Point ( 0, 0 );
        _characterSpriteSetting.moveAnimationLTStartPoint = new Point ( 0, 0 );
        _characterSpriteSetting.moveAnimationLTFrameCount = 3;
        _characterSpriteSetting.reverseAtEnd = true;
        setCharacterSprite ( _characterSpriteSetting );
    }
    
    public function update () :void {
        updateGraphic ();
    }
    
    private function setCharacterSprite ( $characterSpriteSetting:CharacterSpriteSetting ) :void {
        _characterSpriteSetting = $characterSpriteSetting;
        characterSprite = _characterSpriteSetting.baseBitmapData;
        characterBitmap = new Bitmap ();
        characterBitmap.bitmapData = new BitmapData ( _characterSpriteSetting.spriteSize.x, _characterSpriteSetting.spriteSize.y, true, 0x60 );
        addChild ( characterBitmap );
        characterBitmap.x = _characterSpriteSetting.spriteOffset.x;
        characterBitmap.y = _characterSpriteSetting.spriteOffset.y;
        updateGraphic ( true );
    }
    
    private function updateGraphic ( $forceRefresh:Boolean = false ) :void {
        if ( !_activated ) {
            animationDelay++;
            if ( $forceRefresh )
                animationDelay = _characterSpriteSetting.animationDelay + 1;
            if ( animationDelay > _characterSpriteSetting.animationDelay ) {
                animationDelay = 0;
                characterBitmap.bitmapData.dispose ();
                characterBitmap.bitmapData = new BitmapData ( _characterSpriteSetting.spriteSize.x, _characterSpriteSetting.spriteSize.y, true, 0x60 );
                var copyRectangle:Rectangle = new Rectangle ( 0, 0, _characterSpriteSetting.spriteSize.x, _characterSpriteSetting.spriteSize.y );
                if ( animationIndex >= _characterSpriteSetting.moveAnimationLTFrameCount ) {
                    if ( _characterSpriteSetting.reverseAtEnd ) {
                        _characterSpriteSetting.animationDirection *= -1;
                        animationIndex -= 2;
                    } else
                        animationIndex = 0;
                }
                if ( animationIndex < 0 && _characterSpriteSetting.reverseAtEnd ) {
                    _characterSpriteSetting.animationDirection *= -1;
                    animationIndex += 2;
                }
                copyRectangle.x = _characterSpriteSetting.moveAnimationLTStartPoint.x + animationIndex * _characterSpriteSetting.spriteSize.x;
                copyRectangle.y = _characterSpriteSetting.moveAnimationLTStartPoint.y;
                animationIndex += _characterSpriteSetting.animationDirection;
                characterBitmap.bitmapData.copyPixels ( characterSprite, copyRectangle, new Point ( 0, 0 ) );
            }
        }
    }
    
    public function dispose () :void {
        if ( !_activated ) {
            _activated = true;
            characterBitmap.bitmapData.dispose ();
            characterBitmap = null;
            characterSprite = null;
            parent.removeChild ( this );
        }
    }
    
    public function get position () :Point {
        return _position;
    }
    
    public function get fireLength () :uint {
        return _bombSetting.fireLength;
    }

    public function get damage () :Number {
        return _bombSetting.damage;
    }
    
}

import flash.display.Sprite;
import flash.display.SimpleButton;
import flash.display.MovieClip;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.events.MouseEvent;
import caurina.transitions.Tweener;
class Menu extends Sprite {
    
    private var _startGameCallBack:    Function;
    
    private var _units:                Vector.<MovieClip> = new Vector.<MovieClip>;
    
    private var _logoContainer:     Sprite;
    private var _startButton:        SimpleButton;
    
    private var _back:              Bitmap;
    private var _logo:              Bitmap;
    private var _selectedGraphic:   Bitmap;
    
    private var _guiSpriteBMD:       BitmapData;
    
    private var _selected:            int = -1;
    
    public function Menu ( $guiSpriteBMD:BitmapData, $characterSpriteBMD:BitmapData, $startGameCallBack:Function ) :void {
        _guiSpriteBMD = $guiSpriteBMD;
        _startGameCallBack = $startGameCallBack;
        addChild ( _back = new Bitmap ( new BitmapData ( 465, 465, false, 0 ) ) );
        _back.bitmapData.copyPixels ( _guiSpriteBMD, new Rectangle ( 0, 0, _back.width, _back.height ), new Point ( 0, 0 ) );
        addChild ( _logoContainer = new Sprite );
        _logoContainer.buttonMode = true;
        _logoContainer.addChild ( _logo = new Bitmap ( new BitmapData ( 151, 37, false, 0 ) ) );
        _logo.bitmapData.copyPixels ( _guiSpriteBMD, new Rectangle ( 518, 0, _logo.width, _logo.height ), new Point ( 0, 0 ) );
        _logoContainer.x = 294;
        _logoContainer.y = 52;
        var tmpUpState:Bitmap = new Bitmap ( new BitmapData ( 465, 64, false, 0 ) );
        tmpUpState.bitmapData.copyPixels ( _guiSpriteBMD, new Rectangle ( 465, 65, tmpUpState.width, tmpUpState.height ), new Point ( 0, 0 ) );
        var tmpDownState:Bitmap = new Bitmap ( new BitmapData ( 465, 64, false, 0 ) );
        tmpDownState.bitmapData.copyPixels ( _guiSpriteBMD, new Rectangle ( 465, 129, tmpUpState.width, tmpUpState.height ), new Point ( 0, 0 ) );
        addChild ( _startButton = new SimpleButton ( tmpUpState, tmpDownState, tmpDownState, tmpDownState ) );
        _startButton.x = 0;
        _startButton.y = 170;
        for ( var i:uint = 0; i < 4; i++ ) {
            _units.push ( addChild ( new MovieClip ) as MovieClip );
            var image:Bitmap = _units[_units.length - 1].addChild ( new Bitmap ( new BitmapData ( 53, 65, false, 0x666666 ) ) ) as Bitmap;
            image.bitmapData.copyPixels ( $characterSpriteBMD, new Rectangle ( 18, 26 * i, 18, 26 ), new Point ( 53 / 2 - 18 / 2, 65 / 2 - 26 / 2 ) );
            _units[_units.length - 1].x = 115 + i * 60;
            _units[_units.length - 1].y = 380;
            _units[_units.length - 1].id = i;
        }
        addChild ( _selectedGraphic = new Bitmap ( new BitmapData ( 53, 65, true, 0x60 ) ) );
        _selectedGraphic.bitmapData.copyPixels ( _guiSpriteBMD, new Rectangle ( 465, 0, _selectedGraphic.width, _selectedGraphic.height ), new Point ( 0, 0 ) );
        _selectedGraphic.x = _units[0].x;
        _selectedGraphic.y = _units[0].y;
        resume ();
        _units[0].dispatchEvent ( new MouseEvent ( MouseEvent.CLICK ) );
    }
    
    private function selectCharacter ( event:MouseEvent ) :void {
        _selected = event.currentTarget.id;
        Tweener.removeTweens ( _selectedGraphic );
        Tweener.addTween ( _selectedGraphic, { time: .5, x: event.currentTarget.x } );
        pause ();
        resume ();
    }
    
    private function startGame ( event:MouseEvent ) :void {
        _startGameCallBack.call ( this, _selected );
        pause ();
    }
    
    public function pause () :void {
        _logoContainer.buttonMode = false;
        _logoContainer.removeEventListener ( MouseEvent.CLICK, toHome );
        var length:uint = _units.length;
        for ( var i:uint = 0; i < length; i++ ) {
            _units[i].buttonMode = false;
            _units[i].removeEventListener ( MouseEvent.CLICK, selectCharacter );
        }
        _startButton.enabled = false;
        _startButton.removeEventListener ( MouseEvent.CLICK, startGame );
    }
    
    public function resume () :void {
        _logoContainer.buttonMode = true;
        _logoContainer.addEventListener ( MouseEvent.CLICK, toHome );
        var length:uint = _units.length;
        for ( var i:uint = 0; i < length; i++ ) {
            if ( _selected != i ) {
                _units[i].buttonMode = true;
                _units[i].addEventListener ( MouseEvent.CLICK, selectCharacter );
            }
        }
        _startButton.enabled = true;
        _startButton.addEventListener ( MouseEvent.CLICK, startGame );
    }
    
    private function toHome ( event:MouseEvent ) :void {
        navigateToURL ( new URLRequest ( "http://flashplusplus.net" ), "_blank" );
    }
    
}