ActionScript3でパックマンっぽいのを作ってみた2



パック○ン風ゲームの更新です。


今回はソースコード付きです。
ソースコード一式のダウンロードはこちら↓
http://www.geocities.jp/finnissy/Blog/as3/pac_src.zip










ColorDefined.as

package game 
{
    import adobe.utils.CustomActions;
    import Math;
    /**
     * ...
     * @author Korsakov
     */
    public final class ColorDefined
    {
        public static const COLOR_RED:uint = 0xFF0000;
        public static const COLOR_BLUE:uint = 0x0000ff;
        public static const COLOR_GREEN:uint = 0x00ff00;
        public static const COLOR_PINK:uint = 0xff1493;
        public static const COLOR_WHITE:uint = 0xFFFFFF;
        public static const COLOR_BLACK:uint = 0x000000;
        public static const COLOR_YELLOW:uint = 0xFFFF00;
        public static const COLOR_SKYBLUE:uint = 0x0033FF;
        public static const COLOR_ORANGE:uint = 0xFF9900;
        public static const COLOR_GRAY:uint = 0xDDDDDD;
        public static const COLOR_TMP:uint = 0x6a5acd;
        
        public function ColorDefined() 
        {
            
        }
        
        public static function choiceRandomColor(idx:int = 0):uint
        {
            var color:uint = 0x000000;
            
            idx = idx * (Math.random() * 10);
            trace(idx);
            switch (idx % 10) 
            {
                case 0: color = ColorDefined.COLOR_BLACK;   break;
                case 1: color = ColorDefined.COLOR_BLUE;    break;
                case 3: color = ColorDefined.COLOR_GREEN;   break;
                case 4: color = ColorDefined.COLOR_PINK;    break;
                case 5: color = ColorDefined.COLOR_RED;     break;
                case 6: color = ColorDefined.COLOR_WHITE;   break;
                case 7: color = ColorDefined.COLOR_YELLOW;  break;
                case 8: color = ColorDefined.COLOR_ORANGE;  break;
                case 9: color = ColorDefined.COLOR_TMP;     break;
            }
            trace("color = " + color);
            return color;
        }
    }

}





Enemy.as

package game 
{
    import flash.display.ActionScriptVersion;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.events.Event;
    import flash.geom.Point;
    import flash.display.Loader;
    /**
     * ...
     * @author Korsakov
     */
    public class Enemy extends PacObj
    {
        private static var imgType1:Vector.<BitmapData>;
        private static var imgType2:Vector.<BitmapData>;
        private static var imgType3:Vector.<BitmapData>;
        private static var imgType4:Vector.<BitmapData>;
        private static var imgType5:Vector.<BitmapData>;
        private static var eIndex:int;
        private static const ENEMY_MAX:int = 4;
        private static const LONG_DISTANCE:int = 1024*11;   //適当...
        private static const MID_DISTANCE:int = 1024*7;
        private static const SHOUT_DISTANCE:int = 1024 * 4;
        private static const STATE_HOME:int = 0;
        private static const STATE_ATTACK:int = 1;
        private static const STATE_GETAWAY:int = 2;
        private static const STATE_RETURN:int = 3;
        private static const STATE_RUN:int = 3;
        private var img:Vector.<BitmapData>;
        private var type:int;
        private var dumyPoint:Point;
        private var ePosition:Point;
        private var pacp:Point;
        private var funcArray:Array;
        private var state:int;
        private var doorEv:Event;
        private var death:Event;
        private var enemyEating:Event;
        
        ////////////////////////////////////////////////////////////////////////////
        //      ここからパブリックメソッド
        ////////////////////////////////////////////////////////////////////////////
        public function Enemy(x:int, y:int) 
        {
            old_direction = now_direction = Field.LEFT;
            super(x, y);
            type = eIndex++ % ENEMY_MAX;
            setImage(type);
            ePosition = new Point();
            pacp = new Point();
            
            //関数ポインタ配列
            funcArray = new Array();
            funcArray.push(home);
            funcArray.push(getNewDirection);
            funcArray.push(returnHome);
            funcArray.push(home);
            funcArray.push(home);
            
            //巣の入り口を設定
            dumyPoint = homePosition();
            state = STATE_HOME;
            
            doorEv = new GameEvent(GameEvent.DOOR, 0);
            death = new GameEvent(GameEvent.DEATH, 0);
            enemyEating = new GameEvent(GameEvent.EATING, 1000);
        }
        
        public static function makeImage(loadObj:Loader):void
        {
            var bmp:BitmapData = new BitmapData(loadObj.width, loadObj.height, true, 0x00000000);
            bmp.draw(loadObj);
            
            imgType1 = new Vector.<BitmapData>();
            imgType1 = makeImageSub(bmp, 0,      4 * 16, 16, 16);
            imgType2 = makeImageSub(bmp, 4 * 16, 8 * 16, 16, 16);
            imgType3 = makeImageSub(bmp, 0,      4 * 16, 32, 16);
            imgType4 = makeImageSub(bmp, 4 * 16, 8 * 16, 32, 16);
            imgType5 = makeImageSub(bmp, 0,      4 * 16, 48, 16);
        }
        
        override public function draw():void
        {
            var i:int;
            switch(now_direction)
            {
                case Field.LEFT:    i = 0;  break;
                case Field.UP:      i = 1;  break;
                case Field.DOWN:    i = 2;  break;
                case Field.RIGHT:   i = 3;  break;
                default:    trace("imageUpdate NG");break;
            }
            
            if (this.canvas == null || this.img == null)
                return;
            
            canvas.copyPixels(img[i], img[i].rect, new Point(x, y));
        }
        
        override public function updatePosition():Boolean 
        {
            var r:Boolean = super.updatePosition();
            
            if (r == false)
            {
                now_direction = changeDrc(now_direction, false);
                r = super.updatePosition();
                if (r == false)
                {
                    now_direction = changeDrc(now_direction, false);
                    r = super.updatePosition();
                    if (r == false)
                    {
                        now_direction = changeDrc(now_direction, true);
                        r = super.updatePosition();
                    }
                }
            }
            switch (state)
            {
                case STATE_HOME:
                    if (++numCycle > 60 + (type * 30))
                    {
                        Field.door = false;
                        state = STATE_RUN;
                        dispatchEvent(doorEv);
                        dumyPoint = doorPosition();
                    }
                    break;
                case STATE_RUN:
                    if (isHit(dumyPoint, position))
                    {
                        state = STATE_ATTACK;
                        Field.door = true;
                        dispatchEvent(doorEv);
                    }
                    break;
                case STATE_ATTACK:
                    if (isHit(pacp, position))
                    {
                        //TODO:死んだときのイベントを実装する
                        state = STATE_HOME;
                        dispatchEvent(death);
                    }
                    break;
                case STATE_GETAWAY:
                    if (isHit(pacp, position))
                    {
                        state = STATE_RETURN;
                        dumyPoint = new Point(Field.DOOR_Y + 1, Field.DOOR_X - 1);
                        dispatchEvent(enemyEating);
                    }
                    break;
                case STATE_RETURN:
                    if (isHit(dumyPoint, position))
                    {
                        state = STATE_ATTACK;
                        dumyPoint = doorPosition();
                        dispatchEvent(enemyEating);
                    }
                    break;
                default:
                    break;
            }
            return r;
        }
        
        private function changeDrc(drc:int,drcFlg:Boolean):int
        {
            switch (drc)
            {
                case Field.LEFT:
                case Field.RIGHT:
                    if (drcFlg == false)
                    {
                        return Field.UP;
                    }   return Field.DOWN;
                case Field.DOWN:
                case Field.UP:
                    if (drcFlg == false)
                    {
                        return Field.LEFT;
                    }   return Field.RIGHT;
                default:
                    return drc;
            }
        }
        
        public function updateDirection():void
        {
            reloadPacposition();
            now_direction = funcArray[state](pacp, position);
        }
        
        public function resetState():void 
        {
            state = STATE_HOME;
            dumyPoint = homePosition();
        }
        
        ////////////////////////////////////////////////////////////////////////////
        //      ここからプライベートメソッド    
        ////////////////////////////////////////////////////////////////////////////
        private function  getNewDirection(pac:Point, ene:Point):int
        {
            switch (this.type) 
            {
                case 0:     return ambush(pac, ene);    break;
                case 1:     return free(pac, ene);      break;
                case 2:     return intercept(pac, ene); break;
                case 3:     return pursuit(pac, ene);   break;
                default:    break;
            }
            return now_direction;
        }
        
        //ひたすら追跡型
        private function  pursuit(pac:Point, ene:Point):int     //int... return value is New Direction
        {
            var t1:int = now_direction;
            var t2:int;
            if (Math.abs(pac.x - this.x) < Math.abs(pac.y - this.y)) 
            {
                if ((t2 = checkLR(pac, ene)) != t1) return t2;  else 
                return checkUD(pac, ene);
            } else {
                if ((t2 = checkUD(pac, ene)) != t1) return t2;  else 
                return checkLR(pac, ene);
            }
        }
        
        //迎撃型
        private function  intercept(pac:Point, ene:Point):int
        {
            var distance:Number = 
                Math.pow(pac.x - ene.x, 2) + Math.pow(pac.y - ene.y, 2);
            if (distance <= SHOUT_DISTANCE || distance > MID_DISTANCE)
            {
                return pursuit(pac, ene);
            }
            return now_direction;
        }
        
        //自由型
        private function  free(pac:Point, ene:Point):int
        {
            if (!(numCycle % 10))
            {
                trace("dumy update");
                dumyPoint = pointGenerator();
            }
            
            if (Math.abs(pac.x - this.x) < Math.abs(pac.y - this.y)) 
            {
                return checkLR(pac, ene);
            } else {
                return checkUD(pac, ene);
            }
        }
        
        //待ち伏せ型
        private function  ambush(pac:Point, ene:Point):int
        {
            var distance:Number = 
                Math.pow(pac.x - ene.x, 2) + Math.pow(pac.y - ene.y, 2);
            if (distance <= SHOUT_DISTANCE)
            {
                return pursuit(pac, ene);
            } else {
                return free(pac, ene);
            }
        }
        
        //ひたすら逃げる
        private function getaway(pac:Point, ene:Point):int      //int... return value is New Direction
        {
            var t1:int = now_direction;
            var t2:int;
            if (Math.abs(pac.x - this.x) < Math.abs(pac.y - this.y)) 
            {
                if ((t2 = getawayLR(pac, ene)) != t1)   return t2;  else 
                return getawayUD(pac, ene);
            } else {
                if ((t2 = getawayUD(pac, ene)) != t1)   return t2;  else
                return getawayLR(pac, ene);
            }
        }
        
        //巣の中をうろつく
        private function home(pac:Point, ene:Point):int
        {
            var dumy:Point = dumyPoint;
            return pursuit(dumyPoint, ene);
        }
        
        //巣に帰る
        private function returnHome(ene:Point):int
        {
            return pursuit(dumyPoint, ene);
        }
        
        private function checkLR(pp:Point, pe:Point):int
        {
            if (pp.x < pe.x && now_direction != Field.RIGHT &&
                Field.moving(pe.x - move_value, pe.y, Field.LEFT))  return Field.LEFT;  else
            if (pp.x > pe.x && now_direction != Field.LEFT  && 
                Field.moving(pe.x + move_value, pe.y, Field.RIGHT)) return Field.RIGHT;
            
            return now_direction;
        }
        
        private function checkUD(pp:Point, pe:Point):int
        {
            if (pp.y < pe.y && now_direction != Field.DOWN &&
                Field.moving(pe.x, pe.y - move_value, Field.UP))    return Field.UP;    else
            if (pp.y > pe.y && now_direction != Field.UP &&
                Field.moving(pe.x, pe.y + move_value, Field.LEFT))  return Field.DOWN;
                
            return now_direction;
        }
        
        private function getawayLR(pp:Point, pe:Point):int
        {
            if (pp.x < pe.x && now_direction != Field.LEFT) return Field.RIGHT; else
            if (pp.x > pe.x && now_direction != Field.RIGHT)return Field.LEFT;
            return now_direction;
        }
        
        private function getawayUD(pp:Point, pe:Point):int
        {
            if (pp.y < pe.y && now_direction != Field.UP)   return Field.DOWN;  else
            if (pp.y > pe.y && now_direction != Field.DOWN) return Field.UP;
            return now_direction;
        }
        
        private function pointGenerator():Point
        {
            var x:int = int(Math.random() * Field.FRAME_W) / Field.FIELD_GRID;
            var y:int = int(Math.random() * Field.FRAME_H) / Field.FIELD_GRID;
            var f:int = Field.field[y][x];
            if (f == Field.NOTHING || f == Field.AFTER_EATING)
            {
                trace(x, y);
                return new Point(x, y);
            }
            return pointGenerator();
        }
        
        private function doorPosition():Point
        {
            return new Point(Field.DOOR_Y * Field.FIELD_GRID,
                                Field.DOOR_X * Field.FIELD_GRID);
        }
        private function homePosition():Point
        {
            return new Point((Field.DOOR_Y + 2) * Field.FIELD_GRID,
                                (Field.DOOR_X + 2) * Field.FIELD_GRID);
        }
        
        private function isHit(pac:Point,ene:Point):Boolean
        {
            var x:int = pac.x - ene.x;
            var y:int = pac.y - ene.y;
            var g:int = Field.FIELD_GRID / 2;
            if (x * x + y * y < g * g)
                return true;
            return false;
        }
        
        private function get position():Point
        {
            ePosition.x = Number(this.x);
            ePosition.y = Number(this.y);
            return ePosition;
        }
        
        private function reloadPacposition():Point
        {
            var target:Array = new Array();
            
            for each(var p:Point in game.Pacman.position)
            {
                var X:int = Math.abs(p.x - this.x);
                var Y:int = Math.abs(p.y - this.y);
                target.push(int(Math.pow(X, 2) + Math.pow(Y, 2)));
            }
            var t:Array = target.sort(function(p1:int, p2:int):int {
                return p1 - p2;
            });
            pacp = Pacman.position[target.indexOf(t[0])];
            return pacp;
        }
        
        private function setImage(type:int):void 
        {
            switch (type) 
            {
                case 0: this.img = imgType1;    break;
                case 1: this.img = imgType2;    break;
                case 2: this.img = imgType3;    break;
                case 3: this.img = imgType4;    break;
                case 4: this.img = imgType5;    break;
                default:    break;
            }
        }
    }
}





Field.as

package game 
{
    import RangeError;
    
    /**
     * 移動可能な範囲を定義したクラス
     * オブジェクトを移動させる場合は、moving()でチェック
     */
    public class Field
    {
        /*******************************************************
         *  定数宣言領域
         ******************************************************/
        public static const WINDOW_COLOR:uint = 0xFF000000;
        public static const WINDOW_W:uint = 465;
        public static const WINDOW_H:uint = 465;
        public static const FIELD_W:uint = 25;
        public static const FIELD_H:uint = 27;
        public static const FIELD_GRID:int = 16;
        public static const FRAME_W:uint = FIELD_GRID * FIELD_W;
        public static const FRAME_H:uint = FIELD_GRID * FIELD_H;
        public static const UP:int  = 1;
        public static const LEFT:int = 2;
        public static const DOWN:int = 4;
        public static const RIGHT:int = 8;
        public static const NOTHING:int = 0;
        public static const WALL:int = 1;
        public static const AFTER_EATING:int = -1;
        public static const ENEMY_HOME:int = -2;
        public static const DOOR_X:int = 11;
        public static const DOOR_Y:int = 11;
        public static const OUTDOOR_X:int = 12;
        public static const OUTDOOR_Y:int = 12;
        public static const DOOR_CLOSE:int = 2;
        
        /*******************************************************
         *  変数宣言領域
         ******************************************************/
         
        //注意 上記パラメーターを変えた場合、以下のフィールド変数も更新すること
        public static var field:Array = [
    //  0   1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 
        [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, ],//0
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//1
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ],//2
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//3
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ],//4
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//5
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ],//6
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//7
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ],//8
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//9
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ],//10
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//11
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ],// 12
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,-2,-2,-2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//13
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ],// 14
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//15
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ],// 16
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//17
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ],// 18
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//19
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ],// 20
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//21
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ],// 22
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//23
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ],// 24
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],//25
        [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, ],//26
        ];
        
        public function Field() { }
        
        /***********************************************************************
         *      進行方向に進めるか調べる
         *      進行可能:  true
         *      進行不可能:    false
         **********************************************************************/
        public static function moving(x:int, y:int, dirc:int):Boolean
        {
            var x1:int = x / FIELD_GRID;
            var y1:int = y / FIELD_GRID;
            var x2:int = (x + FIELD_GRID-1) / (FIELD_GRID);
            var y2:int = (y + FIELD_GRID-1) / (FIELD_GRID);
            var l1:Boolean, l2:Boolean, r1:Boolean, r2:Boolean;
            var u1:Boolean, u2:Boolean, d1:Boolean, d2:Boolean;
            var fi:Array = [field[y1][x1], field[y2][x1], field[y1][x2], field[y2][x2]];

            l1 = (fi[0] == NOTHING) || (fi[0] == AFTER_EATING) || (fi[0] == ENEMY_HOME);
            l2 = (fi[1] == NOTHING) || (fi[1] == AFTER_EATING) || (fi[1] == ENEMY_HOME);
            r1 = (fi[2] == NOTHING) || (fi[2] == AFTER_EATING) || (fi[2] == ENEMY_HOME);
            r2 = (fi[3] == NOTHING) || (fi[3] == AFTER_EATING) || (fi[3] == ENEMY_HOME);
            u1 = l1;
            u2 = r1;
            d1 = l2;
            d2 = r2;

            switch( dirc )
            {
            case LEFT:  return (l1 && l2);
            case RIGHT: return (r1 && r2);
            case UP:    return (u1 && u2);
            case DOWN:  return (d1 && d2);
            default:    break;
            }
            
            return false;
        }
        
        public static function set door(toggle:Boolean):void 
        {
            field[OUTDOOR_Y][OUTDOOR_X] = (toggle == false ? NOTHING:DOOR_CLOSE);
        }
        
        public static function get isdoor():Boolean
        {
            return (field[OUTDOOR_Y][OUTDOOR_X] == NOTHING ? false:true);
        }
    }

}





GameEvent.as

package game 
{
    import flash.events.Event;
    
    /**
     * ...
     * @author Korsakov
     */
    public class GameEvent extends Event 
    {
        public static const UPDATE:String = "update";
        public static const POWERUP:String = "powerup";
        public static const GAME_OVER:String = "gameover";
        public static const GAME_CLEAR:String = "gameclear";
        public static const DOOR:String = "doorevent";
        public static const DEATH:String = "death";
        public static const EATING:String = "eating";
        public var value:int;
        public function GameEvent(type:String, value:int,bubbles:Boolean = false)
        { 
            super(type, bubbles);
            this.value = value;
        } 
        
        public override function clone():Event 
        { 
            return new GameEvent(type, value);
        } 
        
        public override function toString():String 
        { 
            return formatToString("GameEvent", "type", "bubbles", "cancelable", "eventPhase"); 
        }
        
    }
    
}





Main.as

package game
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.InteractiveObject;
    import flash.display.Sprite;
    import flash.display.GradientType;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.KeyboardEvent;
    import flash.events.SecurityErrorEvent;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.net.URLRequest;
    import flash.net.URLRequestHeader;
    import flash.text.TextField;
    import flash.display.Stage;
    import flash.display.StageAlign;
    import flash.display.Loader;
    import flash.system.LoaderContext;
    import flash.geom.Rectangle;
    import flash.text.TextFormat;
    import flash.text.TextFormatAlign;
    
    /**
     * ...
     * @author Korsakov
     */
    [SWF(width="465", height="465", frameRate="30", backgraundColor="0x000000")]
    public class Main extends Sprite 
    {        
        /*******************************************************
         *  変数宣言領域
         ******************************************************/
        private var play_field:PlayField;
        private var demonstration:Sprite;
        private var reposeDisplay:Sprite;
        private var gameComplete:Sprite;
        private var pacman:Pacman;
        private var enemys:Vector.<Enemy>;
        private var help:TextField;
        private var scoreText:TextField;
        private var loader:Loader;
        private var playing:Boolean;
        private var isdead:Boolean;
        private var score:int = 0;
        private var playerNum:int = 4;
        private var waitcnt:int;
        private static const speed:int = 4;//1,2,4,8のみ対応
        private static const PAC_INITPOSTION_X:int = 12;
        private static const PAC_INITPOSTION_Y:int = 19;
        private static const WAIT_NUM:int = 60;
        
        /*******************************************************
         *  関数定義
         ******************************************************/
        public function Main():void 
        {
            help = new TextField();
            help.defaultTextFormat = new TextFormat("_sans", 10, 0xCCDDEE);
            scoreText = new TextField();
            scoreText.defaultTextFormat = new TextFormat("_sans", 20, 0xCCDDEE);
            
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
            
            var context:LoaderContext = new LoaderContext(true);
            loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadingComplete);
            loader.load(new URLRequest("http://www.geocities.jp/finnissy/Blog/as3/pac.png"),context);
            //loader.load(new URLRequest("file:///E:/ブログ/pac.png"));
        }
        
        private function loadingComplete(ev:Event):void
        {
            //パックマンのモジュールを初期化
            pacInit();
            
            //タイトル画面の作成
            demonstration = new Sprite();
            demonstration.x = 25;
            demonstration.y = 15;
            var pacTitle:TextField = new TextField();
            pacTitle.defaultTextFormat = new TextFormat("_sans", 30, 0xFF0000,
                                null,null,null,null,null,TextFormatAlign.CENTER);
            pacTitle.width = 400;
            pacTitle.y = 50;
            pacTitle.text = "パクマン";
            var ctl:TextField = new TextField();
            ctl.defaultTextFormat = new TextFormat("_sans", 12, 0x3322AA,
                                null, null, null, null, null, TextFormatAlign.CENTER);
            ctl.width = 400;
            ctl.y = 100;
            ctl.text = "Enterを押すとゲーム開始";
            
            //休憩画面の作成
            reposeDisplay = new Sprite();
            reposeDisplay.x = 25;
            reposeDisplay.y = 15;
            var reposetitle:TextField = new TextField();
            reposetitle.defaultTextFormat = new TextFormat("_sans", 30, 0xFF3300,
                                null,null,null,null,null,TextFormatAlign.CENTER);
            reposetitle.width = 400;
            reposetitle.y = 50;
            reposetitle.text = "Dead...";
            
            //ゲームクリアーの画面
            gameComplete = new Sprite();
            gameComplete.x = 25;
            gameComplete.y = 15;
            var endtitle:TextField = new TextField();
            endtitle.defaultTextFormat = new TextFormat("_sans", 30, 0x0055EE,
                                null, null, null, null, null, TextFormatAlign.CENTER);
            endtitle.multiline = true;
            endtitle.y = 100;
            endtitle.width = 400;
            endtitle.height = 100;
            endtitle.text = "Complete Stage!!\n(;´Д`)ハァハァ";
            
            demonstration.addChild(pacTitle);
            demonstration.addChild(ctl);
            addChild(demonstration);
            
            reposeDisplay.addChild(reposetitle);
            gameComplete.addChild(endtitle);
            
            playing = true;
            isdead = false;
            waitcnt = WAIT_NUM;
            addEventListener(Event.ENTER_FRAME, title, false, 0);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, gameStartAction);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            //ヘルプ画面作成
            help.width = 60;
            help.y = 10;
            help.x = 400;
            help.text = "移動\n  ←↑↓→\n\n\n終了  Esc";
            scoreText.x = 16;
            scoreText.y = Field.FRAME_H;
            scoreText.text = "" + 0;
        }
        
        private function  pacInit():void 
        {
            Pacman.makeImage(loader);
            Enemy.makeImage(loader);
            
            play_field = new PlayField(Field.FRAME_W, Field.FRAME_H,
                                            Field.WINDOW_COLOR, loader);
            pacman = new Pacman(12, 19);
            enemys = new Vector.<Enemy>();
            for (var i:int = 0; i < 4; i++) 
            {
                enemys.push(new Enemy(11 + (i % 3), 13));
            }
            
            play_field.addEventListener(GameEvent.UPDATE, updateScore);
            play_field.addEventListener(GameEvent.GAME_CLEAR, gameClear);
            play_field.addEventListener(GameEvent.DEATH, deathGame);
            pacman.setMoveValue = speed;//パックの移動量
            play_field.addPacObj(pacman);//パックをプレイフィールドに追加
            play_field.putPacImg(playerNum);
            for each(var em:Enemy in enemys)
            {
                play_field.addPacObj(em);
            }
        }
        
        private function resetGame():void 
        {
            score = 0;
            scoreText.text = "";
            play_field.resetField(true);
            play_field.putPacImg(playerNum);
        }
        
        private function deathGame(e:Event):void
        {
            playing = false;
            isdead = true;
            if (playerNum < 1)
            {
                resetGame();
            } else {
                play_field.resetField(false);
                play_field.putPacImg(playerNum);
                pacman.changeDirection(Field.LEFT);
            }
        }
        
        private function  gameClear(e:Event):void 
        {
            removeChild(play_field);
            removeChild(help);
            removeChild(scoreText);
            removeEventListener(Event.ENTER_FRAME, drawing);
            stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyboardEvent);
            playing = true;
            addChild(gameComplete);
            addEventListener(Event.ENTER_FRAME, complete, false, 0);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, gameRotation);
        }
        
        private function updateScore(e:GameEvent):void
        {
            score += e.value;
            scoreText.text = "" + score;
        }
        
        //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
        //          KeyboardEvent
        private function gameStartAction(ev:KeyboardEvent):void
        {
            switch(ev.keyCode) {//Enter,Z
                case 13:case 90:    playing = false; break;
            }
        }
        
        private function keyboardEvent(ev:KeyboardEvent):void 
        {
            switch(ev.keyCode) {//Escape
                case 27:
                    resetGame();
                    playing = false;
                    break;
            }
            pacman.updateDirection(ev);
        }
        
        private function gameRotation(ev:KeyboardEvent):void 
        {
            switch(ev.keyCode) {//Escape
                case 13:case 27:    playing = false;    break;
            }
        }
        //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
        
        //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
        //          EnterFrameEvent
        private function title(ev:Event):void
        {
            //  TODO:デモ画面作成
            if (!playing)
            {
                //ゲーム開始画面に遷移
                removeChild(demonstration);
                removeEventListener(Event.ENTER_FRAME, title);
                stage.removeEventListener(KeyboardEvent.KEY_DOWN, gameStartAction);
                
                playing = true;
                addChild(play_field);
                addChild(help);
                addChild(scoreText);
                addEventListener(Event.ENTER_FRAME, drawing, false, 0);
                stage.addEventListener(KeyboardEvent.KEY_DOWN, keyboardEvent);
            }
        }
        
        private function drawing(ev:Event):void 
        {
            //FPS30で毎フレーム実行される処理
            play_field.updateAll();
            if (!playing)
            {
                if (isdead)
                {
                    //休憩画面に切り替える
                    removeChild(play_field);
                    removeChild(help);
                    removeChild(scoreText);
                    removeEventListener(Event.ENTER_FRAME, drawing);
                    stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyboardEvent);
                    addChild(reposeDisplay);
                    addEventListener(Event.ENTER_FRAME, repose, false, 0);
                } else {
                    //タイトル画面に切り替える
                    removeChild(play_field);
                    removeChild(help);
                    removeChild(scoreText);
                    removeEventListener(Event.ENTER_FRAME, drawing);
                    stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyboardEvent);
                    playing = true;
                    addChild(demonstration);
                    addEventListener(Event.ENTER_FRAME, title, false, 0);
                    stage.addEventListener(KeyboardEvent.KEY_DOWN, gameStartAction);
                }
            }
        }
        
        private function repose(ev:Event):void
        {
            if (--waitcnt < 1)  //30fps = 1sec...
            {
                playing = true;
                isdead = false;
                waitcnt = WAIT_NUM;
                removeChild(reposeDisplay);
                removeEventListener(Event.ENTER_FRAME, repose);
                if (playerNum > 0)
                {
                    //プレイ画面に戻す
                    playerNum--;
                    addChild(play_field);
                    addChild(help);
                    addChild(scoreText);
                    addEventListener(Event.ENTER_FRAME, drawing, false, 0);
                    stage.addEventListener(KeyboardEvent.KEY_DOWN, keyboardEvent);
                } else {
                    //残奇数ゼロならタイトル画面に遷移
                    playerNum = 4;
                    addChild(demonstration);
                    addEventListener(Event.ENTER_FRAME, title, false, 0);
                    stage.addEventListener(KeyboardEvent.KEY_DOWN, gameStartAction);
                }
            }
        }
        
        private function complete(ev:Event):void 
        {
            if (!playing)
            {
                //タイトル画面に切り替える
                removeChild(gameComplete);
                removeEventListener(Event.ENTER_FRAME, complete);
                stage.removeEventListener(KeyboardEvent.KEY_DOWN, gameRotation);
                playing = true;
                resetGame();
                addChild(demonstration);
                addEventListener(Event.ENTER_FRAME, title, false, 0);
                stage.addEventListener(KeyboardEvent.KEY_DOWN, gameStartAction);
            }
        }
        //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    }
}





Pacman.as

package game 
{
    import flash.display.BitmapData;
    import flash.display.IBitmapDrawable;
    import flash.display.Loader;
    import flash.display.Shape;
    import flash.events.KeyboardEvent;
    import flash.filters.BlurFilter;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.display.BlendMode;
    import flash.geom.Rectangle;
    /**
     * ...
     * @author Korsakov
     */
    public class Pacman extends PacObj
    {
        private static var imgBase:Vector.<BitmapData>;
        public static var position:Vector.<Point>;
        public static const MOTION:int = 2;
        private var motionIndex:int;
        public var pacIdx:int;
        
        
        public function Pacman(x:int, y:int)
        {
            old_direction = now_direction = Field.LEFT;
            super(x, y);
            
            if (position == null)
                position = new Vector.<Point>();
            pacIdx = position.length;
            position.push(new Point(this.x, this.y));
        }
        
        public static function makeImage(loadObj:Loader):void
        {
            var bmp:BitmapData = new BitmapData(loadObj.width, loadObj.height, true, 0x00000000);
            bmp.draw(loadObj);
            imgBase = makeImageSub(bmp, 0, 8 * 16, 0, 16);
        }
        
        override public function draw():void
        {
            var i:int;
            switch(now_direction)
            {
                case Field.LEFT:    i = 0;  break;
                case Field.UP:      i = 2;  break;
                case Field.DOWN:    i = 4;  break;
                case Field.RIGHT:   i = 6;  break;
                default:    trace("imageUpdate NG");break;
            }
            
            if (this.canvas == null || imgBase == null)
                return;
            
            i += motionIndex;
            canvas.copyPixels(imgBase[i], imgBase[i].rect, new Point(x, y));
            if (++numCycle % updateCycle == 0)
            {
                motionIndex = (motionIndex + 1) % MOTION;
            }
        }
        
        public function updateDirection(ev:KeyboardEvent):Boolean
        {
            switch(ev.keyCode) {
                case 38:    now_direction = Field.UP;   break;  //up key
                case 40:    now_direction = Field.DOWN; break;  //down key
                case 37:    now_direction = Field.LEFT; break;  //left key
                case 39:    now_direction = Field.RIGHT;break;  //right key
                default:    return false;
            }
            trace("0: up, 1: down, 2: left, 3: rgith ");
            trace("updateDirection ok" + now_direction);
            return true;
        }
        
        public function changeDirection(dr:int):void 
        {
            switch (dr) 
            {
                case Field.UP:      now_direction = Field.UP;   break;  //up key
                case Field.DOWN:    now_direction = Field.DOWN; break;  //down key
                case Field.LEFT:    now_direction = Field.LEFT; break;  //left key
                case Field.RIGHT:   now_direction = Field.RIGHT;break;  //right key
                default:            break;
            }
        }
        
        override public function updatePosition():Boolean 
        {
            var bool:Boolean = super.updatePosition();
            if (bool) {
                position[pacIdx].x = this.x;
                position[pacIdx].y = this.y;
            }
            return bool;
        }
    }
}





PacObj.as

package game 
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display.GradientType;
    import flash.events.EventDispatcher;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    
    /**
     * ...
     * @author Korsakov
     * 動き回るオブジェクトの基底クラス
     */
    public class PacObj extends EventDispatcher {
        public static const updateCycle:int = 2;    //アニメーションする頻度
        protected var x:int;
        protected var y:int;
        protected var numCycle:uint;
        protected var move_value:int;           //移動量
        protected var now_direction:int;        //方向(現在)
        protected var old_direction:int;        //方向(1フレーム前)
        protected var old_rect:Rectangle;       //前回描画された矩形情報
        protected var canvas:BitmapData = null; //描画対象となるキャンバス
        public var x_init:int;
        public var y_init:int;
        
        public static function makeImageSub(bmp:BitmapData,
                sx:int, ex:int, y:int, spacing:int):Vector.<BitmapData>
        {
            var v:Vector.<BitmapData> = new Vector.<BitmapData>();
            for (var i:int = sx; i < ex; i += spacing)
            {
                v.push(clipImage(bmp, i, y));
            }
            return v;
        }
        
        public static function clipImage(bmp:BitmapData, x:int, y:int):BitmapData
        {
            var b:BitmapData = new BitmapData(16, 16, true, 0x00000000);
            b.copyPixels(bmp, new Rectangle(x, y, 16, 16), new Point(0, 0));
            return b;
        }
        
        public function PacObj(x:int, y:int, move_value:int = 4) {
            this.x = (x % Field.FRAME_W) * Field.FIELD_GRID;
            this.y = (y % Field.FRAME_H) * Field.FIELD_GRID;
            this.move_value = move_value % Field.FIELD_GRID;
            this.old_rect = new Rectangle(Number(this.x), Number(this.y), Number(Field.FIELD_GRID), Number(Field.FIELD_GRID));
            this.x_init = this.x;
            this.y_init = this.y;
        }
        
        public function set setCanvas(canvas:BitmapData):void
        {
            this.canvas = canvas;
        }
        
        public function set setMoveValue(val:int):void
        {
            this.move_value = val % Field.FIELD_GRID;
        }
        
        public function setMovePosition(x:int, y:int):void
        {
            this.x = x;
            this.y = y;
        }
        
        public function draw():void {}
        
        public function get rectInfo():Rectangle
        {
            return this.old_rect;
        }
        
        /****************************************************
         *  updatePosition()
         *  返却値  :  更新OK...true, 更新NG...false
         *  概要    :  directionで決められた方向に直進する
         ****************************************************/
        public function updatePosition():Boolean
        {
            var x:int = this.x;
            var y:int = this.y;
            switch (this.now_direction)
            {
                case Field.UP:      y -= move_value;    break;
                case Field.DOWN:    y += move_value;    break;
                case Field.LEFT:    x -= move_value;    break;
                case Field.RIGHT:   x += move_value;    break;
                default:            break;
            }

            {   //無条件でオブジェクトを更新する。
                //オブジェクトが動いた時だけ更新する場合は以下の2行を消す
                this.old_rect.x = Number(this.x);
                this.old_rect.y = Number(this.y);
            }
            
            var result:Boolean = false;
            /*******************目的の進行方向にトライ*******************/
            if(result = Field.moving(x, y, now_direction) )
            {
                /*  注意 x,y変数を更新する前に前回の描画箇所をoldに記録する    */
                this.old_rect.x = Number(this.x), this.old_rect.y = Number(this.y);
                old_direction = now_direction;
                this.x = x, this.y = y;
            } else
            if(old_direction != now_direction)  //前回と今回の進行方向が同じ場合は無理
            {   
                x = this.x, y = this.y;
                var mv:int = move_value;
                var drc:int = old_direction;
                
                /*******************前回の進行方向にトライ*******************/
                switch(drc) {
                    case Field.LEFT:if (result = Field.moving(x - mv, y, drc) ) 
                                        this.x -= mv;               break;
                    case Field.RIGHT:if (result = Field.moving(x + mv, y, drc) )
                                        this.x += mv;               break;
                    case Field.UP:  if (result = Field.moving(x, y - mv, drc) )
                                        this.y -= mv;               break;
                    case Field.DOWN:if (result = Field.moving(x, y + mv, drc) )
                                        this.y += mv;               break;
                    default:    break;
                }
                
                if (result) {
                    this.old_rect.x = Number(x);
                    this.old_rect.y = Number(y);
                }
            }
            return result;
        }
        
        public function resetCycle():void 
        {
            numCycle = 0;
        }
    }
}





PlayField.as

package game 
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Shape;
    import flash.display.Stage;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IEventDispatcher;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.display.GradientType;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import flash.utils.ByteArray;
    
    /**
     * ...
     * @author Korsakov
     */
    
     // TODO:プレイヤーの残機数を表示
    public class PlayField extends Bitmap
    {
        private const foodSize:int = Field.FIELD_GRID / 10;
        private const SCORE_FOOD:int = 100;
        private var w:uint, h:uint;
        private var num_obj:Vector.<PacObj>;
        private var back_color:uint;
        private var back_buffer:BitmapData = null;
        private var scoreEvent:Event;
        private var gameclearEvent:Event;
        private var foodnum:int;
        private var img_pacman:BitmapData;
        private var img_fruit_01:BitmapData;
        private var img_fruit_02:BitmapData;
        private var img_fruit_03:BitmapData;
        private var img_door_open:BitmapData;
        private var img_door_close:BitmapData;
        
        ////////////////////////////////////////////////////////////////////////////
        //      ここからパブリックメソッド
        ////////////////////////////////////////////////////////////////////////////
        public function PlayField(w:uint, h:uint, color:uint, loadImage:Loader = null) 
        {
            this.w = w;
            this.h = h;
            this.back_color = color;
            var field:BitmapData = new BitmapData(w, h, false, color);
            super(field);
            
            num_obj = new Vector.<PacObj>();
            scoreEvent = new GameEvent(GameEvent.UPDATE, SCORE_FOOD);
            gameclearEvent = new GameEvent(GameEvent.GAME_CLEAR, 0);
            
            if (loadImage != null)
            {
                makeImage(loadImage);
                makeBackBuffer(w, h);
            }
        }
        
        public function addPacObj(obj:PacObj):void
        {
            num_obj.push(obj);
            //  ドアオープンイベント
            PacObj(num_obj[num_obj.indexOf(obj)]).
                addEventListener(GameEvent.DOOR, toggleDoorEvent);
            //  死亡したときのイベント
            PacObj(num_obj[num_obj.indexOf(obj)]).
                addEventListener(GameEvent.DEATH, deathEvent);
            //追加したオブジェクトの描画先を、自クラスのbitmapDataに設定
            obj.setCanvas = this.bitmapData;
        }
        
        public function resetField(foodclear:Boolean):void 
        {
            Field.door = true;      //ドアを閉じる
            toggleDoor();           //ドア画像を更新
            resetPacObjAll();       //パック達を元に戻す
            if (foodclear)
                resetFood(Field.FRAME_W, Field.FRAME_H);    //餌を戻す
            else
                cleanDisplay(Field.FRAME_W, Field.FRAME_H);
        }
        
        public function updateAll():void
        {
            var rects:Vector.<Rectangle> = new Vector.<Rectangle>();
            for each(var pc:PacObj in num_obj)
            {
                if (pc is Enemy)
                {
                    Enemy(pc).updateDirection();
                }
            }
            
            for (var i:int = 0; i < num_obj.length; i++)
            {
                var b:Boolean = num_obj[i].updatePosition();    //オブジェクトを更新
                rects.push(num_obj[i].rectInfo);
                //trace("rect push");
                if (num_obj[i] is Pacman)
                {
                    eating(num_obj[i].rectInfo);
                }
            }
            
            for (i = 0; i < rects.length; i++)
            {
                /***********************************
                **  更新された箇所のみ背景色で塗りつぶす
                ***********************************/
                if (back_buffer != null)
                {
                    this.bitmapData.copyPixels(back_buffer, rects[i],
                                    new Point(rects[i].x, rects[i].y));
                }
            }
            
            for (i = 0; i < num_obj.length; i++)
            {
                /***********************************
                **  全てのオブジェクトを再描画
                ***********************************/
                num_obj[i].draw();
            }
        }
        
        public function putPacImg(num:int):void 
        {
            var sh:Shape = makeColorRectShape
                (back_color,Field.FRAME_W,Field.FRAME_H);
            var mx:Matrix = makeGridMatrix(64, Field.FRAME_H);
            this.bitmapData.draw(sh, mx);
            for (var i:int = 0; i < num; i++) 
            {
                this.bitmapData.copyPixels(
                    img_pacman,
                    new Rectangle(0, 0, Field.FIELD_GRID, Field.FIELD_GRID),
                    new Point(64 + (i*Field.FIELD_GRID), Field.FRAME_H)
                );
            }
        }
        
        ////////////////////////////////////////////////////////////////////////////
        //      ここからプライベートメソッド    
        ////////////////////////////////////////////////////////////////////////////        
        private function toggleDoorEvent(e:GameEvent):void 
        {
            toggleDoor();
        }
        
        private function deathEvent(ev:GameEvent):void 
        {
            dispatchEvent(new GameEvent(GameEvent.DEATH, 0));
        }
        
        //ドアを開けたり閉めたりする
        private function toggleDoor():void 
        {
            var x:int = Field.OUTDOOR_X;
            var y:int = Field.OUTDOOR_Y;
            var p:Point = new Point(
                x * Field.FIELD_GRID,y * Field.FIELD_GRID);
            
            if (Field.field[y][x] == Field.DOOR_CLOSE) 
            {
                fillBackbuffer(x, y);
                back_buffer.copyPixels(img_door_close, img_door_close.rect,p);
                bitmapData.copyPixels(img_door_close, img_door_close.rect,p);
            }else {
                fillBackbuffer(x, y);
                back_buffer.copyPixels(img_door_open, img_door_open.rect,p);
                bitmapData.copyPixels(img_door_open, img_door_open.rect,p);
            }
        }
        
        private function makeImage(loadObj:Loader):void 
        {
            var bmp:BitmapData = new BitmapData(loadObj.width, loadObj.height, true, 0x00000000);
            bmp.draw(loadObj);
            
            img_door_open = PacObj.clipImage(bmp, 16, 64);
            img_door_close = PacObj.clipImage(bmp, 0, 64);
            img_fruit_01 = PacObj.clipImage(bmp, 64, 64);
            img_fruit_02 = PacObj.clipImage(bmp, 80, 64);
            img_fruit_03 = PacObj.clipImage(bmp, 96, 64);
            img_pacman = PacObj.clipImage(bmp, 0, 0);
        }
        
        private function makeBackBuffer(w:uint, h:uint):void
        {
            back_buffer = new BitmapData(w, h, false, 0xFF000000);
            var s:Sprite = new Sprite();
            var r:Rectangle = new Rectangle();
            var color:uint = 0x90c012;
            var inc:Number = 0.5;

            //下地作成
            s.graphics.beginFill(back_color);
            s.graphics.drawRect(0, 0, Field.FRAME_W, Field.FRAME_H);
            s.graphics.endFill();
            for (var y:int = 0; y < Field.FIELD_H; y++)
            {
                for (var x:int = 0; x < Field.FIELD_W; x++)
                {
                    var v:int = Field.field[y][x];
                    if (v == Field.NOTHING) //餌を置く
                    {
                        r.x = Number(x * Field.FIELD_GRID) + (Field.FIELD_GRID/2);
                        r.y = Number(y * Field.FIELD_GRID) + (Field.FIELD_GRID/2);
                        s.graphics.beginFill(0xEEFF00, 1);
                        s.graphics.drawCircle(r.x, r.y, foodSize);
                        s.graphics.endFill();
                        foodnum++;
                    } else if (v == Field.WALL){    //壁を置く
                        r.x = Number(x * Field.FIELD_GRID);
                        r.y = Number(y * Field.FIELD_GRID);
                        r.width = Field.FIELD_GRID;
                        r.height = Field.FIELD_GRID;
                        
                        s.graphics.beginFill(color, 1);
                        s.graphics.drawRoundRect
                            (r.x, r.y, r.width, r.height, r.width / 3, r.height / 3);
                        s.graphics.endFill();
                        color++;
                    } else if (v == Field.DOOR_CLOSE) { //扉
                        s.graphics.beginBitmapFill(img_door_close);
                        s.graphics.drawRect(x * Field.FIELD_GRID, y * Field.FIELD_GRID,
                                        Field.FIELD_GRID, Field.FIELD_GRID);
                        s.graphics.endFill();
                    }
                }
            }
            back_buffer.draw(s);
            this.bitmapData.draw(s);
        }
        
        //  餌を食う
        private function eating(rect:Rectangle):void
        {
            var x:int = (rect.x / Field.FIELD_GRID) % Field.FIELD_W;
            var y:int = (rect.y / Field.FIELD_GRID) % Field.FIELD_H;
            if (Field.field[y][x] == Field.NOTHING)
            {
                Field.field[y][x] = Field.AFTER_EATING;
                fillBackbuffer(x, y);
                dispatchEvent(scoreEvent);
                
                //餌が0になったらゲームクリアー
                if (--foodnum < 1)
                    dispatchEvent(gameclearEvent);
            }
        }
        
        private function fillBackbuffer(x:int, y:int):void 
        {
            var r:int = Field.FIELD_GRID;
            var sh:Shape = makeColorRectShape(back_color, r, r);
            var mx:Matrix = makeGridMatrix(x, y);
            back_buffer.draw(sh, mx);
            this.bitmapData.draw(sh, mx);
        }
        
        private function makeColorRectShape(color:int, w:int, h:int):Shape
        {
            var sh:Shape = new Shape();
            sh.graphics.beginFill(color);
            sh.graphics.drawRect(0,0, w, h);
            sh.graphics.endFill();
            return sh;
        }
        
        private function makeGridMatrix(x:int, y:int):Matrix
        {
            var mx:Matrix = new Matrix();
            mx.tx = x * Field.FIELD_GRID;
            mx.ty = y * Field.FIELD_GRID;
            return mx;
        }
        
        private function resetFood(w:int, h:int):void
        {
            foodnum = 0;    //餌の数をリセット
            for (var y:int = 0; y < Field.FIELD_H; y++)
            {
                for (var x:int = 0; x < Field.FIELD_W; x++)
                {
                    if (Field.field[y][x] == Field.AFTER_EATING)    //食後なら
                    {
                        Field.field[y][x] = Field.NOTHING;
                    } 
                }
            }
            makeBackBuffer(w, h);
        }
        
        private function cleanDisplay(w:int, h:int):void
        {
            this.bitmapData.draw(back_buffer);
        }
        
        private function resetPacObjAll():void 
        {
            for each(var pc:PacObj in num_obj)
            {
                pc.setMovePosition(pc.x_init, pc.y_init);
                if (pc is Enemy)
                {
                    Enemy(pc).resetCycle();
                    Enemy(pc).resetState();
                }
            }
        }
    }
}