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

A*を使った経路探索

案の定メインのコードじゃないところが肥大化したw

ステージをクリックしていくとマップの構造が変わります。
Get Adobe Flash player
by okoi 15 Jun 2011
/**
 * Copyright okoi ( http://wonderfl.net/user/okoi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/pTIE
 */

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.display.BitmapData;
    import flash.display.Bitmap;
    import flash.display.Shape;
    
    import flash.geom.Matrix;
    import flash.geom.Rectangle;
    import flash.geom.Point;
    import flash.filters.BlurFilter;
    import flash.filters.ColorMatrixFilter;
    
    [SWF(width = "465", height = "465", frameRate="60")]
    
    /**
     * ...
     * @author 
     */
    public class Main extends Sprite 
    {
        public static const WIDTH:int = 465;
        public static const HEIGHT:int = 465;
        
        private var _step:int;
        
        private var _maincanvas:BitmapData;
        private var _gridcanvas:BitmapData;
        private var _blurcanvas:BitmapData;
        
        private var _filter:ColorMatrixFilter;
        
        private var _mouseDown:Boolean = false;
        private var _mouseGridIndex:Point = new Point();
        private var _mousePrevGridIndex:Point = new Point();
        
        private var _field:Field;
        
        private var _gridimage:GridImage;
        
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            graphics.beginFill(0);
            graphics.drawRect(0, 0, WIDTH, HEIGHT);
            graphics.endFill();
            
            _gridcanvas = new BitmapData(WIDTH, HEIGHT, true, 0);
            addChild( new Bitmap(_gridcanvas) );
            
            _blurcanvas = new BitmapData(WIDTH, HEIGHT, true, 0);
            addChild( new Bitmap(_blurcanvas) );
            
            _maincanvas = new BitmapData(WIDTH, HEIGHT, true, 0);
            addChild( new Bitmap(_maincanvas) );
            
            
            _gridimage = new GridImage();
                        
            _field = new Field();
            _field.InitGrid();
            _field.InitMoveObject();
            DrawField();
        
            _filter = new ColorMatrixFilter([
                1, 0, 0, 0, 0,
                0, 1, 0, 0, 0,
                0, 0, 1, 0, 0,
                0, 0, 0, 0.5, 0
            ]); 
                        
            _step = 0;
            
            addEventListener( Event.ENTER_FRAME, EnterFrameHandler );
            stage.addEventListener( MouseEvent.MOUSE_DOWN, MouseDownHandler );
            stage.addEventListener( MouseEvent.MOUSE_UP, MouseUpHandler );
            

            
        }
        
        private function EnterFrameHandler( e:Event ) : void
        {
            
            _field.UpdateMoveObject();
            
            //    道と壁の切り替え
            if ( _mouseDown )
            {
                _mouseGridIndex = GetMouseGridIndex();
                if ( _mouseGridIndex.x >= 0 && _mouseGridIndex.x < _field.gridNumX && _mouseGridIndex.y >= 0 && _mouseGridIndex.y < _field.gridNumY )
                {            
                    if ( _mouseGridIndex.x != _mousePrevGridIndex.x || _mouseGridIndex.y != _mousePrevGridIndex.y )
                    {
                        _field.ChangeGridType( _mouseGridIndex.x, _mouseGridIndex.y );                        
                        DrawField();
                    }
                }
                _mousePrevGridIndex = _mouseGridIndex;
            }
            
            _maincanvas.lock();
            _maincanvas.applyFilter( _maincanvas, _maincanvas.rect, new Point(), _filter );        
            var objnum:int = _field.moveobjectlist.length;
            for ( var i:int = 0; i < objnum; i++ )
            {
                var moveobj:MoveObject = _field.moveobjectlist[i];
                _maincanvas.fillRect( new Rectangle(moveobj.x+5, moveobj.y+5, GridInfo.GRID_W/3, GridInfo.GRID_H/3), 0xAAffd700 );
            }
            _maincanvas.unlock();
            
            _blurcanvas.lock();
            _blurcanvas.draw( _maincanvas, null, null, "add" );
            _blurcanvas.applyFilter( _blurcanvas, _blurcanvas.rect, new Point(), new BlurFilter(2,2) );
            _blurcanvas.unlock();
            
        }
        
        /**
         * ステージ上でマウスを押した時に呼ばれる
         * @param    event
         */
        private function MouseDownHandler( event:MouseEvent ) : void
        {
            _mouseDown = true;
            _mouseGridIndex = GetMouseGridIndex();
        }
        
        /**
         * ステージ上でマウスを離した時に呼ばれる
         * @param    event
         */
        private function MouseUpHandler( event:MouseEvent ) : void
        {
            _mouseDown = false;
            _mouseGridIndex = new Point( -1, -1);
            _mousePrevGridIndex = new Point( -1, -1 );
        }
        
        /**
         * 現在のマウス位置をグリッドのインデックスで返す
         * @return
         */
        private function GetMouseGridIndex() : Point
        {
            return    new Point( int(mouseX / GridInfo.GRID_W), int(mouseY / GridInfo.GRID_H) );
        }
        
        private function DrawField() : void
        {
            _gridcanvas.lock();
            var gridnum:int = _field.gridlist.length;    
            var grid:GridInfo;
            for ( var y:int = 0; y < _field.gridNumY; y++ )
            {
                for ( var x:int = 0; x < _field.gridNumX; x++ )
                {
                    var gridrect:Rectangle = new Rectangle( x * GridInfo.GRID_W, y * GridInfo.GRID_H, GridInfo.GRID_W, GridInfo.GRID_H );
                    grid = _field.gridlist[y][x];
                    if ( _field.GetGridType( x, y ) == GridInfo.TYPE_ROAD )
                    {
                        
                        var newdispimageid:int = _gridimage.GetImageID( grid );
                        if ( newdispimageid != -1 && grid.dispImageID != newdispimageid )
                        {
                            _gridcanvas.copyPixels( _gridimage.imagelist[newdispimageid], _gridimage.imagelist[newdispimageid].rect, new Point(x * GridInfo.GRID_W, y * GridInfo.GRID_H) );
                        }
                        grid.dispImageID = newdispimageid;
                        //_gridcanvas.fillRect( gridrect, 0 );
                    }
                    else
                    {
                        _gridcanvas.fillRect( gridrect, 0xFF228b22);
                        grid.dispImageID = -1;
                    }
                }
            }
            _gridcanvas.unlock();
            
        }
        
        
    }
}

    import flash.geom.Point;
    import flash.display.BitmapData;
    import flash.geom.Rectangle;

    
    /**
     * ...
     * @author 
     */
    class Field
    {
        public var gridNumX:int = Main.WIDTH / GridInfo.GRID_W;
        public var gridNumY:int = Main.HEIGHT / GridInfo.GRID_H;
        
        private var _gridList:Array;
        public function get gridlist():Array { return    _gridList;    }
        
        private var _moveObjectList:/*MoveObject*/Array;
        public function get moveobjectlist():Array { return    _moveObjectList;    }
        
        public function Field() 
        {
            trace( gridNumX, gridNumY );
        }
        
        public function InitGrid() : void
        {
            var x:int, y:int;
            
            _gridList = new Array( gridNumY );
            for ( y = 0; y < gridNumY; y++ )
            {
                _gridList[y] = new Array( gridNumX );
                for ( x = 0; x < gridNumX; x++ )
                {
                    var grid:GridInfo = new GridInfo();
                    _gridList[y][x] = grid;
                    
                    grid.type = GridInfo.TYPE_ROAD;
                    
                    //    端のグリッドだった場合
                    if ( x == 0 )                grid.SetMoveDirFlag( MoveConst.DIR_LEFT, false );
                    if ( x == gridNumX - 1 )    grid.SetMoveDirFlag( MoveConst.DIR_RIGHT, false );
                    if ( y == 0 )                grid.SetMoveDirFlag( MoveConst.DIR_UP, false );
                    if ( y == gridNumY - 1 )    grid.SetMoveDirFlag( MoveConst.DIR_DOWN, false );    
                }
            }
    
            for ( y = 0; y < gridNumY; y++ )
            {
                for ( x = 0; x < gridNumX; x++ )
                {
                    if ( int(Math.random() * 10) == 0 )    ChangeGridType(x, y);
                }
            }    
            
        }
        
        /**
         * 指定した場所のグリッドタイプを変更する
         * @param    x
         * @param    y
         */
        public function ChangeGridType( x:int, y:int ) : void
        {
            var grid:GridInfo = _gridList[y][x];
            grid.type = (grid.type + 1) % 2;
            
            var flag:Boolean = false;
            if ( grid.type == GridInfo.TYPE_ROAD )    flag = true;
            
            if ( x > 0 )                _gridList[y][x - 1].SetMoveDirFlag( MoveConst.DIR_RIGHT, flag );
            if ( x < gridNumX - 1 )        _gridList[y][x + 1].SetMoveDirFlag( MoveConst.DIR_LEFT, flag );
            if ( y > 0 )                _gridList[y - 1][x].SetMoveDirFlag( MoveConst.DIR_DOWN, flag );
            if ( y < gridNumY - 1 )        _gridList[y + 1][x].SetMoveDirFlag( MoveConst.DIR_UP, flag );
            
        }
        
        /**
         * 指定した場所のグリッドタイプを取得する
         * @param    x
         * @param    y
         * @return
         */
        public function GetGridType( x:int, y:int ) : int
        {
            return    _gridList[y][x].type;
        }
        
        
        //=======================================================
        //    MoveObject
        //=======================================================
        public function InitMoveObject() : void
        {
            _moveObjectList = [];
        }
        
        /**
         * 移動オブジェクトを追加する
         */
        public function AddMoveObject() : void
        {
            var rand:int = 0;
            var moveobject:MoveObject = new MoveObject( this );
            //    出現グリッド
            rand = int(Math.random() * 4);
            if ( rand == 0 )        moveobject.gridIndex = new Point( int(Math.random() * gridNumX), 0 );
            else if( rand == 1 )    moveobject.gridIndex = new Point( 0, int(Math.random() * gridNumY) );
            else if ( rand == 2 )    moveobject.gridIndex = new Point( int(Math.random() * gridNumX), gridNumY - 1 );
            else if ( rand == 3 )    moveobject.gridIndex = new Point( gridNumX - 1, int(Math.random() * gridNumY) );
            
            //    目標グリッド
            rand = int(Math.random() * 4);
            if ( rand == 0 )        moveobject.target = new Point( int(Math.random() * gridNumX), 0  );
            else if( rand == 1 )    moveobject.target = new Point( 0, int(Math.random() * gridNumY) );
            else if ( rand == 2 )    moveobject.target = new Point( int(Math.random() * gridNumX), gridNumY - 1 );
            else if ( rand == 3 )    moveobject.target = new Point( gridNumX - 1, int(Math.random() * gridNumY) );
            
            moveobject.x = moveobject.gridIndex.x * GridInfo.GRID_W;
            moveobject.y = moveobject.gridIndex.y * GridInfo.GRID_H;
            
            var ret:Boolean = moveobject.InitRoute( moveobject.gridIndex, moveobject.target );
            if ( ret )    _moveObjectList.push( moveobject );
        }
        
        private var ss:int = 0;
        public function UpdateMoveObject() : void
        {
            //if ( int(Math.random() * 30) == 0 )
            if( ss % 10 == 0 )
            {
                AddMoveObject();
            }
            ss++;
            var objnum:int = _moveObjectList.length;
            for ( var i:int = objnum - 1; i >= 0; i-- )
            {
                var moveobj:MoveObject = _moveObjectList[i];
                moveobj.Move();
                if( moveobj.deleteFlag )    _moveObjectList.splice( i, 1 );
            }
        }
        
    }

    /**
     * ...
     * @author 
     */
    class MoveConst
    {
        public static const DIR_LEFT:int = 0;
        public static const DIR_UP:int = 1;
        public static const DIR_RIGHT:int = 2;
        public static const DIR_DOWN:int = 3;
        public static const DIR_NUM:int = 4;
    
        //    各方向に対しての移動パラメータ
        public static const DIR_MOVE_PARAM:/*Object*/Array = [
            { "x":-1, "y": 0, "cost":1.0 },    //    DIR_LEFT
            { "x": 0, "y":-1, "cost":1.0 },    //    DIR_UP
            { "x": 1, "y": 0, "cost":1.0 },    //    DIR_RIGHT
            { "x": 0, "y": 1, "cost":1.0 }    //    DIR_DOWN
        ];

    }

    /**
     * A*経路探索用ノードクラス
     * @author 
     */
    class AStarNode
    {
        public var x:int;
        public var y:int;
        public var parent:AStarNode = null;
            
        public var g:Number = 0;                    //    スタートからこのノードまでのコスト
        public var h:Number;                        //    このノードからゴールまでの予測コスト
        public var f:Number = 0;                    //    g + h
        
        /**
         * 親ノードからの方向
         */
        public function get dirFromParent() : int {
            var dir:int = -1;

            if ( parent == null )    return    dir;
            
            var sx:int = x - parent.x;
            var sy:int = y - parent.y;
            if ( sx == 0 && sy > 0 )    dir = MoveConst.DIR_DOWN;
            if ( sx <  0 && sy == 0 )    dir = MoveConst.DIR_LEFT;
            if ( sx == 0 && sy < 0 )    dir = MoveConst.DIR_UP;
            if ( sx >  0 && sy == 0 )    dir = MoveConst.DIR_RIGHT;
            
            return    dir;
        }
        
    }

    /**
     * どの方向に移動するかを示すクラス
     * @author 
     */
    class MoveOrder
    {
        public var dir:int = -1;        
    }

    /**
     * 移動オブジェクト
     * @author 
     */
    class MoveObject
    {            
        public var field:Field = null;
        public var gridIndex:Point = null;        //    現在のグリッドインデックス
        public var target:Point;
        public var x:Number;                        //    座標
        public var y:Number;                        //    座標
        public var step:int;
        public var moveOrderList:Array;
        public var moveOrderStep:int;
        public var deleteFlag:Boolean = false;
        
        public function MoveObject( f:Field ) 
        {
            step = 0;
            field = f;
        }
        
        public function Move() : void
        {
            if ( moveOrderList != null && moveOrderStep < moveOrderList.length )
            {
                var nowOrder:MoveOrder = moveOrderList[moveOrderStep];
                var mx:Number = 0;
                var my:Number = 0;
                
                if ( nowOrder.dir == MoveConst.DIR_LEFT )    mx = -1 * (GridInfo.GRID_W / 3);
                if ( nowOrder.dir == MoveConst.DIR_UP )        my = -1 * (GridInfo.GRID_H / 3);
                if ( nowOrder.dir == MoveConst.DIR_RIGHT )    mx = (GridInfo.GRID_W / 3);
                if ( nowOrder.dir == MoveConst.DIR_DOWN )    my = (GridInfo.GRID_H / 3);
                
                x += mx;
                y += my;
                
                step++;
                
                if ( step % 3 == 0 )
                {
                    moveOrderStep++;
                    gridIndex.x += MoveConst.DIR_MOVE_PARAM[nowOrder.dir].x;
                    gridIndex.y += MoveConst.DIR_MOVE_PARAM[nowOrder.dir].y;
                    
                    x = gridIndex.x * GridInfo.GRID_W;
                    y = gridIndex.y * GridInfo.GRID_H;
                    
                    if( moveOrderStep == moveOrderList.length )    deleteFlag = true;
                    else
                    {
                        CheckMoveObjectRoute();        //    ルート変更をしなくていいか確認
                    }
                }
                
            }else
            {
                deleteFlag = true;
            }
        }
        
        /**
         * 移動ルートを初期化する
         * @param    start
         * @param    goal
         * @return
         */
        public function InitRoute( start:Point, goal:Point ) : Boolean
        {
            moveOrderList = SearchRoute( start, goal );
            moveOrderStep = 0;
            step = 0;
            if ( moveOrderList == null )    return    false;
            return    true;
        }
        
        /**
         * 目的地までのルートをA*アルゴリズムを使って検索する
         * @param    start
         * @param    goal
         * @return
         */
        private function SearchRoute( start:Point, goal:Point ) : Array
        {
            var open:Array = [];
            var close:Array = [];
            var result:Array = [];
            var node:AStarNode = null;
            var gridlist:/*Array*/Array = field.gridlist;
            var grid:GridInfo;
            
            //    スタート地点が既に壁だったら失敗
            if ( gridlist[start.y][start.x].type == GridInfo.TYPE_WALL )    return    null;
            
            
            //    マップに対応するノードを用意する
            var nodes:Array = new Array( field.gridNumY );
            for ( var y:int = 0; y < field.gridNumY; y++ )
            {
                nodes[y] = new Array( field.gridNumX );
                for ( var x:int = 0; x < field.gridNumX; x++ )
                {
                    node = new AStarNode();
                    node.x = x;
                    node.y = y;
                    nodes[y][x] = node;
                }
            }
            
            //    スタート地点のノードをopen(移動候補)配列に加える
            open.push( nodes[ start.y ][ start.x ] );    
            while ( true )
            {
                //    fの小さい順に並べて、先頭ノードを取り出す
                open.sortOn("f", Array.NUMERIC);
                node = open.shift();
                if ( node == null )    return null;
                close.push( node );
                
                if ( node.x == goal.x && node.y == goal.y )    break;
                
                for ( var i:int = 0; i < MoveConst.DIR_NUM; i++ )
                {
                    //    移動できるかを判定
                    grid = gridlist[node.y][node.x];
                    if ( !grid.GetMoveDirFlag( i ) )    continue;
                    
                    //    次のノード候補を取り出す
                    var tx:int = node.x + MoveConst.DIR_MOVE_PARAM[i].x;
                    var ty:int = node.y + MoveConst.DIR_MOVE_PARAM[i].y;                
                    var next:AStarNode = nodes[ty][tx];
                    
                    
                    var g:Number = node.g + MoveConst.DIR_MOVE_PARAM[i].cost;                    //    スタートからここまでのコスト
                    var h:Number = Math.abs( goal.x - next.x ) + Math.abs( goal.y - next.y );    //    (next)からゴールまでの推定コスト
                    var f:Number = g + h;                                                        //    スタートから(next)を通って、ゴールまで行った時の推定コスト
                    
                    //    既にopenかcloseに登録されている場合
                    if ( open.indexOf( next ) != -1 || close.indexOf( next ) != -1 )
                    {
                        //    新しいルートの方がコストが低かった場合そちらに書き換える
                        if ( next.f > f )
                        {
                            next.g = g;
                            next.h = h;
                            next.f = f;
                            next.parent = node;
                        }
                    }else
                    {
                        next.g = g;
                        next.h = h;
                        next.f = f;
                        next.parent = node;
                        open.push( next );
                    }
                }
            }
            
            //    最後からたどる
            while ( true )
            {
                if ( node.parent == null )    break;
                var order:MoveOrder = new MoveOrder();
                order.dir = node.dirFromParent;    
                result.push( order );            
                node = node.parent;
            }
            result.reverse();
            
            return    result;
        }
        
        /**
         * ルートが健在かどうかを調べる
         * @param depth    調べる深さ
         */
        private function CheckMoveObjectRoute( depth:int = 3 ) : void
        {
            var gridlist:Array = field.gridlist;
            var nowOrder:MoveOrder;
            var gridx:int = gridIndex.x;
            var gridy:int = gridIndex.y;
            for ( var i:int = 0; i < depth && moveOrderStep + i < moveOrderList.length; i++ )
            {
                nowOrder = moveOrderList[moveOrderStep + i];
                gridx += MoveConst.DIR_MOVE_PARAM[nowOrder.dir].x;
                gridy += MoveConst.DIR_MOVE_PARAM[nowOrder.dir].y;
                
                //    ルート再検索が必要
                if ( gridlist[gridy][gridx].type == GridInfo.TYPE_WALL )
                {
                    if ( !InitRoute( gridIndex, target ) )
                    {
                        deleteFlag = true;
                    }else
                    {
                        return;
                    }
                }
            }
        }
    }

    /**
     * グリッド情報クラス
     * @author 
     */
    class GridInfo
    {
        public static const GRID_W:Number = 15;
        public static const GRID_H:Number = 15;
        
        public static const TYPE_ROAD:int = 0;    //    道
        public static const TYPE_WALL:int = 1;    //    壁
        
        public var index:Point;
        public var type:int;    //    このグリッドのタイプ
                
        private var _moveFlagTable:Array = new Array( MoveConst.DIR_NUM );
        
        public var dispImageID:int;
        
        public function GridInfo() 
        {
            index = new Point();
            type = TYPE_ROAD;
            for ( var i:int = 0; i < MoveConst.DIR_NUM; i++ )    SetMoveDirFlag( i, true );    
            dispImageID = -1;
        }
                
        /**
         * 隣接するグリッドの移動可能フラグを取得する
         * @param    dir
         * @return
         */
        public function GetMoveDirFlag( dir:int ) : Boolean
        {
            return    _moveFlagTable[dir];
        }
        
        /**
         * 隣接するグリッドに移動可能かどうかを設定する
         * @param    dir
         * @param    flag
         */
        public function SetMoveDirFlag( dir:int, flag:Boolean ) : void
        {
            _moveFlagTable[dir] = flag;
        }    
    }


    /**
     * 道のグラフィック用クラス
     * @author 
     */
    class GridImage
    {
        public static const IMAGE_NUM:int = 15;
        public static const LURD:int = 0;
        public static const LUD:int = 1;
        public static const LUR:int = 2;
        public static const URD:int = 3;
        public static const LRD:int = 4;
        public static const LU:int = 5;
        public static const UR:int = 6;
        public static const RD:int = 7;
        public static const LD:int = 8;
        public static const LR:int = 9;
        public static const UD:int = 10;
        public static const L:int = 11;
        public static const U:int = 12;
        public static const R:int = 13;
        public static const D:int = 14;
        
        public var imagelist:/*BitmapData*/Array;
        
        
        public function GridImage() 
        {
            var gridw:int = GridInfo.GRID_W;
            var gridh:int = GridInfo.GRID_H;
            var color_wall_shadow:uint = 0xFF006400;
            var color_wall_highlight:uint = 0xFF555555;
            var color_road:uint = 0xFF556b2f;
            
            
            imagelist = new Array(IMAGE_NUM);
            for ( var i:int = 0; i < IMAGE_NUM; i++ )
            {
                imagelist[i] = new BitmapData(gridw, gridh, true, color_road);
            }
            
            
            var blockw:int = gridw / 3;
            var blockh:int = gridh / 3;
            
            //    ■□■    
            //  □□□
            //    ■□■
        //    imagelist[LURD].fillRect( new Rectangle(0, 0, gridw, gridh), color_road );
            imagelist[LURD].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[LURD].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[LURD].fillRect( new Rectangle(0, blockh*2, blockw, blockh), color_wall_shadow );
            imagelist[LURD].fillRect( new Rectangle(blockw * 2, blockh*2, blockw, blockh), color_wall_shadow );
            
            //    ■□■    
            //    □□■
            //    ■□■
            imagelist[LUD].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[LUD].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[LUD].fillRect( new Rectangle(blockw * 2, blockh*1, blockw, blockh), color_wall_shadow );
            imagelist[LUD].fillRect( new Rectangle(0, blockh*2, blockw, blockh), color_wall_shadow );
            imagelist[LUD].fillRect( new Rectangle(blockw * 2, blockh*2, blockw, blockh), color_wall_shadow );
            
            
            //    ■□■
            //    □□□
            //    ■■■
            imagelist[LUR].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[LUR].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[LUR].fillRect( new Rectangle(0, blockh * 2, blockw, blockh), color_wall_shadow );
            imagelist[LUR].fillRect( new Rectangle(blockw*1, blockh*2, blockw, blockh), color_wall_shadow );            
            imagelist[LUR].fillRect( new Rectangle(blockw * 2, blockh*2, blockw, blockh), color_wall_shadow );

            
            //    ■□■
            //    ■□□
            //    ■□■
            imagelist[URD].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[URD].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[URD].fillRect( new Rectangle(0, blockw * 1, blockw, blockh), color_wall_shadow );
            imagelist[URD].fillRect( new Rectangle(0, blockh*2, blockw, blockh), color_wall_shadow );
            imagelist[URD].fillRect( new Rectangle(blockw * 2, blockh*2, blockw, blockh), color_wall_shadow );
            
            //    ■■■
            //    □□□
            //    ■□■
            imagelist[LRD].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[LRD].fillRect( new Rectangle(blockw * 1, 0, blockw, blockh), color_wall_shadow );
            imagelist[LRD].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[LRD].fillRect( new Rectangle(0, blockh*2, blockw, blockh), color_wall_shadow );
            imagelist[LRD].fillRect( new Rectangle(blockw * 2, blockh*2, blockw, blockh), color_wall_shadow );
            
            //    ■□■
            //    □□■
            //    ■■■
            imagelist[LU].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[LU].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[LU].fillRect( new Rectangle(blockw * 2, blockh * 1, blockw, blockh), color_wall_shadow );
            imagelist[LU].fillRect( new Rectangle(0, blockh * 2, blockw, blockh), color_wall_shadow );
            imagelist[LU].fillRect( new Rectangle(blockw*1, blockh*2, blockw, blockh), color_wall_shadow );            
            imagelist[LU].fillRect( new Rectangle(blockw * 2, blockh*2, blockw, blockh), color_wall_shadow );
            
            //    ■□■
            //    ■□□
            //    ■■■
            imagelist[UR].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[UR].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[UR].fillRect( new Rectangle(0, blockh * 1, blockw, blockh), color_wall_shadow );
            imagelist[UR].fillRect( new Rectangle(0, blockh * 2, blockw, blockh), color_wall_shadow );
            imagelist[UR].fillRect( new Rectangle(blockw*1, blockh*2, blockw, blockh), color_wall_shadow );            
            imagelist[UR].fillRect( new Rectangle(blockw * 2, blockh*2, blockw, blockh), color_wall_shadow );
            
            //    ■■■
            //    ■□□
            //    ■□■
            imagelist[RD].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[RD].fillRect( new Rectangle(blockw*1, 0, blockw, blockh), color_wall_shadow );            
            imagelist[RD].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[RD].fillRect( new Rectangle(0, blockh * 1, blockw, blockh), color_wall_shadow );
            imagelist[RD].fillRect( new Rectangle(0, blockh * 2, blockw, blockh), color_wall_shadow );
            imagelist[RD].fillRect( new Rectangle(blockw * 2, blockh*2, blockw, blockh), color_wall_shadow );
            
            //    ■■■
            //    □□■
            //    ■□■
            imagelist[LD].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[LD].fillRect( new Rectangle(blockw*1, 0, blockw, blockh), color_wall_shadow );            
            imagelist[LD].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[LD].fillRect( new Rectangle(blockw * 2, blockh * 1, blockw, blockh), color_wall_shadow );
            imagelist[LD].fillRect( new Rectangle(0, blockh * 2, blockw, blockh), color_wall_shadow );
            imagelist[LD].fillRect( new Rectangle(blockw * 2, blockh*2, blockw, blockh), color_wall_shadow );
            
            //    ■■■
            //    □□□
            //    ■■■
            imagelist[LR].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[LR].fillRect( new Rectangle(blockw*1, 0, blockw, blockh), color_wall_shadow );            
            imagelist[LR].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[LR].fillRect( new Rectangle(0, blockh * 2, blockw, blockh), color_wall_shadow );
            imagelist[LR].fillRect( new Rectangle(blockw*1, blockh*2, blockw, blockh), color_wall_shadow );            
            imagelist[LR].fillRect( new Rectangle(blockw * 2, blockh*2, blockw, blockh), color_wall_shadow );
        
            //    ■□■
            //    ■□■
            //    ■□■
            imagelist[UD].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[UD].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[UD].fillRect( new Rectangle(0, blockh * 1, blockw, blockh), color_wall_shadow );
            imagelist[UD].fillRect( new Rectangle(blockw * 2, blockh * 1, blockw, blockh), color_wall_shadow );
            imagelist[UD].fillRect( new Rectangle(0, blockh * 2, blockw, blockh), color_wall_shadow );
            imagelist[UD].fillRect( new Rectangle(blockw * 2, blockh * 2, blockw, blockh), color_wall_shadow );

            
            //    ■■■
            //    □□■
            //    ■■■
            imagelist[L].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[L].fillRect( new Rectangle(blockw*1, 0, blockw, blockh), color_wall_shadow );            
            imagelist[L].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[L].fillRect( new Rectangle(blockw * 2, blockh * 1, blockw, blockh), color_wall_shadow );            
            imagelist[L].fillRect( new Rectangle(0, blockh * 2, blockw, blockh), color_wall_shadow );
            imagelist[L].fillRect( new Rectangle(blockw*1, blockh*2, blockw, blockh), color_wall_shadow );            
            imagelist[L].fillRect( new Rectangle(blockw * 2, blockh*2, blockw, blockh), color_wall_shadow );
            
            //    ■□■
            //    ■□■
            //    ■■■
            imagelist[U].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[U].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            imagelist[U].fillRect( new Rectangle(0, blockh * 1, blockw, blockh), color_wall_shadow );
            imagelist[U].fillRect( new Rectangle(blockw * 2, blockh * 1, blockw, blockh), color_wall_shadow );
            imagelist[U].fillRect( new Rectangle(0, blockh * 2, blockw, blockh), color_wall_shadow );
            imagelist[U].fillRect( new Rectangle(blockw*1, blockh*2, blockw, blockh), color_wall_shadow );                        
            imagelist[U].fillRect( new Rectangle(blockw * 2, blockh * 2, blockw, blockh), color_wall_shadow );
            
            //    ■■■
            //    ■□□
            //    ■■■
            imagelist[R].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[R].fillRect( new Rectangle(blockw*1, 0, blockw, blockh), color_wall_shadow );            
            imagelist[R].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );
            
            imagelist[R].fillRect( new Rectangle(0, blockh * 1, blockw, blockh), color_wall_shadow );
            
            imagelist[R].fillRect( new Rectangle(0, blockh * 2, blockw, blockh), color_wall_shadow );
            imagelist[R].fillRect( new Rectangle(blockw*1, blockh*2, blockw, blockh), color_wall_shadow );            
            imagelist[R].fillRect( new Rectangle(blockw * 2, blockh*2, blockw, blockh), color_wall_shadow );
            
            
            //    ■■■
            //    ■□■
            //    ■□■
            imagelist[D].fillRect( new Rectangle(0, 0, blockw, blockh), color_wall_shadow );
            imagelist[D].fillRect( new Rectangle(blockw * 1, 0, blockw, blockh), color_wall_shadow );            
            imagelist[D].fillRect( new Rectangle(blockw * 2, 0, blockw, blockh), color_wall_shadow );

            imagelist[D].fillRect( new Rectangle(0, blockh * 1, blockw, blockh), color_wall_shadow );
            imagelist[D].fillRect( new Rectangle(blockw * 2, blockh * 1, blockw, blockh), color_wall_shadow );
            
            imagelist[D].fillRect( new Rectangle(0, blockh * 2, blockw, blockh), color_wall_shadow );
            imagelist[D].fillRect( new Rectangle(blockw * 2, blockh * 2, blockw, blockh), color_wall_shadow );
            
        }
        
        /**
         * 表示するイメージのIDを取得する
         * @param    grid
         */
        public function GetImageID( grid:GridInfo ) : int
        {
            var left:Boolean = grid.GetMoveDirFlag( MoveConst.DIR_LEFT );
            var up:Boolean     = grid.GetMoveDirFlag( MoveConst.DIR_UP );
            var right:Boolean = grid.GetMoveDirFlag( MoveConst.DIR_RIGHT );
            var down:Boolean = grid.GetMoveDirFlag( MoveConst.DIR_DOWN );
            
            var ret:int = -1;
            
            if ( left && up && right && down )    ret = LURD;
            if ( left && up && !right && down )    ret = LUD;
            if ( left && up && right && !down ) ret = LUR;
            if ( !left && up && right && down ) ret = URD;
            if ( left && !up && right && down )    ret = LRD;
            if ( left && up && !right && !down ) ret = LU;
            if ( !left && up && right && !down ) ret = UR;
            if ( !left && !up && right && down ) ret = RD;
            if ( left && !up && !right && down ) ret = LD;
            if ( left && !up && right && !down ) ret = LR;
            if ( !left && up && !right && down ) ret = UD;
            if ( left && !up && !right && !down ) ret = L;
            if ( !left && up && !right && !down ) ret = U;
            if ( !left && !up && right && !down ) ret = R;
            if ( !left && !up && !right && down ) ret = D;
            
            return    ret;
        }
        
    }