使用FLEX和 Actionscript 开发FLASH游戏(六) -3

使用FLEXActionscript开发FLASH 游戏-碰撞检测(第三页)

GameObjectManager.as

package

{

    import flash.display.*;

    import flash.events.*;

    import flash.utils.*;

    import mx.collections.*;

    import mx.core.*;

    public class GameObjectManager

    {

        //double buffer

        public var backBuffer:BitmapData;

        //colour to use to clear backbuffer with

        public var clearColour:uint=0xFF0043AB;

        //static instance

        protected static var instance:GameObjectManager=null;

        //the last frame time

        protected var lastFrame:Date;

        //a collection of the GameObjects

        protected var gameObjects:ArrayCollection=new ArrayCollection();

        // a collection where new GameObjects are placed,to void adding items

        //to gameObjects while in the gameObjects collection while it is in a loop

        protected var newGameObjects:ArrayCollection=new ArrayCollection();

        //a collection where removed GameObjects are placed,to avoid removing items

        //to gameObjects while in the gameObjects collection while it is in a loop

        protected var removedGameObjects:ArrayCollection=new ArrayCollection();

        protected var collisionMap:Dictionary=new Dictionary();

        static public function get Instance():GameObjectManager

        {

            if(instance==null)

                instance=new GameObjectManager();

            return instance;

        }

        public function GameObjectManager()

        {

            if(instance!=null)

                throw new Error("Only one Singleton instance should be instantiated");

            backBuffer=new BitmapData(Application.application.width,Application.application.height,false);

        }

        public function startup():void

        {

            lastFrame=new Date();

        }

        public function shutdown():void

        {

            shutdownAll();

        }

        public function enterFrame():void

        {

            //Calculate the time since the last frame

            var thisFrame:Date=new Date();

            var seconds:Number=(thisFrame.getTime()-lastFrame.getTime())/1000.0;

            lastFrame=thisFrame;

            removeDeletedGameObjects();

            insertNewGameObjects();

            Level.Instance.enterFrame(seconds);

            checkCollisions();

            //now allow objects to update themselves

            for each(var gameObject:GameObject in gameObjects)

            {

                if(gameObject.inuse)

                    gameObject.enterFrame(seconds);

            }

            drawObjects();

        }

        public function click(event:MouseEvent):void

        {

            for each(var gameObject:GameObject in gameObjects)

            {

                if(gameObject.inuse)

                    gameObject.click(event);

            }

        }

        public function mouseDown(event:MouseEvent):void

        {

            for each(var gameObject:GameObject in gameObjects)

            {

                if(gameObject.inuse)

                    gameObject.mouseDown(event);

            }

        }

        public function mouseUp(event:MouseEvent):void

        {

            for each(var gameObject:GameObject in gameObjects)

            {

                if(gameObject.inuse)

                    gameObject.mouseUp(event);

            }

        }

        public function mouseMove(event:MouseMove):void

        {

            for each(var gameObject:GameObject in gameObjects)

            {

                if(gameObject.inuse)

                    gameObject.mouseMove(event);

            }

        }

        protected function drawObjects():void

        {

            backBuffer.fillRect(backBuffer.rect,clearColor);

            //draw the objects

            for each(var gameObject:GameObject in gameObjects)

            {

                if(gameObject.inuse)

                    gameObject.copyToBackBuffer(backBuffer);

            }

        }

        public function addGameObject(gameObject:GameObject):void

        {

            newGameObjects.addItem(gameObject);

        }

        public function removeGameObject(gameObject:GameObject):void

        {

            removedGameObjects.addItem(gameObject);

        }

        protected function shutdownAll():void

        {

            //don't dispose objects twice

            for each(var gameObject:GameObject in gameObjects)

            {

                var found:Boolean=false;

                for each(var removedObject:GameObject in removedGameObjects)

                {

                    if(removedObject==gameObject)

                    {

                        found=true;

                        break;

                    }

                }

                if(!found)

                    gameObject.shutdown();

            }

        }

        protected function insertNewGameObjects():void

        {

            for each(var gameObject:GameObject in newGameObjects)

            {

                for(var i:int=0;i<gameObjects.length;++i)

                {

                    if(gameObjects.getItemAt(i).zOrder>gameObject.zOrder||

                    gameObjects.getItemAt(i).zOrder==-1

                        break;

                }

                gameObjects.addItemAt(gameObject,i);

            }

            newGameObjects.removeAll();

        }

        protected function removeDeletedGameObjects():void

        {

            //insert the object according to it's z position

            for each(var removedObject:GameObject in removedGameObjects)

            {

                var i:int=0;

                for (i=0;i<gameObjects.length;++i)

                {

                    if(gameObjects.getItemAt(i)==removedObject)

                    {

                        gameObjects.removeItemAt(i);

                        break;

                    }

                }

            }

            removedGameObjects.removeAll();

        }  

        public function addCollidingPair(collider1:String,collider2:String):void

        {

            if(collisionMap[collider1]==null)

                collisionMap[collider1]=new Array();

            if(collisionMap[collider2]==null)

                collisionMap[collider2]=new Array();

            collisionMap[collider1].push(collider2);

        }

        protected function checkCollision():void

        {

            for(var i:int=0;i<gameObjects.length;++i)

            {

                var gameObjectI:GameObject=gameObjects.getItemAt(i) as GameObject;

                for(var j:int=i+1;j<gameObjects.length;++j)

                {

                    var gameObjectJ:GameObject=gameObjects.getItemAt(j) as GameObject;

                    //early out for non=colliders

                    var collisionNameNotNothing:Boolean=gameObjectI.collisionName!=

                    CollisionIdentifiers.NONE;

                    //objects can still exist in the gameObjects collection after being disposed,

                    so check

                    var bothInUse:Boolean=gameObjectI.inuse&&gameObjectJ.inuse;

                    //make sure we have an entry in the collisionMap

                    var collisionMapEntryExists:Boolean=collisionMap

                    [gameObject.collisionName]!=null;

                    //make sure the two objects are set to collide

                    var testForCollision:Boolean=collisionMapEntryExists&&collisionMap

                    [gameObjectI.collisionName].indexOf(gameObjectJ.collsionName)!=-1

                    if(collisionNameNotNothing&&

                        bothInUse&&

                        collisionMapEntryExists&&

                        testForCollision)

                    {

                        if(gameObjectI.CollisionArea.intersects(gameObjectJ.CollisionArea))

                        {

                            gameObjectI.collision(gameObjectJ);

                            gameObjectJ.collision(gameObjectI);

                        }

                    }

                }

            }

        }

    }

}

我们已经给GameObjectManager增加了一个属性:collisionMap。这是一个字典属性其关键码为游戏对象的碰撞名,而且值是一个所有可能与之碰撞的游戏对象的碰撞名的数组。当数量增加时它看起来像下面的形式。

关键码:”Player”值:{“Enemy”,”EnemyWeapon”,”Powerup”}

关键码:”Enemy”值:{“Player”,”PlayerWeapon”}

关键码:”PlayerWeapon”值:{“Enemy”}

关键码:”Powerup”值:{“Player”}

 

等等诸如此类。

addCollidingPair函数被用来填充collisionMap字典。我们将在main.mxml文件中的creationComplete函数中调用它。checkCollision函数用来实际检测出碰撞,而且同时游戏对象被告知。函数看起来比较复杂,实际上非常简单。

最初它在gameObjects集合(包括所有活跃的GameObjects)上循环两次,在这样的结构上来把所有的游戏对象和其它的对象比较一遍。它做了下面一系列的检查:

l         是否两个游戏对象的碰撞名都是”None”?两个游戏对象都需要其碰撞名为None来参与一个碰撞。

l         是不是两个游戏对象都是使用状态?(即它们在游戏中都是活跃的)这应该总是情况属实,但是也不影响检测。

l         是否游戏对象的碰撞名在collisionMap中都已经作为碰撞者注册了?collisionMap的目的是决定与之碰撞的对象是哪些

如果所有这些检测都是为真,那么我们使用矩形的重叠函数来看是否游戏对象实际上碰撞。如果他们是碰撞了那么通过它们的collision函数被告知。

正如我之前在论文中提过的碰撞检测是一个被用来整本整本探讨的主题。我们不会使用哪些很聪明的方式来优化碰撞检测系统。我们在这里的用到的是一种简单的检测系统,但是它也是很有用的因为我们在整个屏幕中在任何时候拥有的最多的游戏对象不会超过两打(24个)。

   为了能够检测到所有的碰撞我们需要调用addColllidingPair函数。这将在我们的应用程序对象的creationComplete函数中调用。现在让我们看看所做的一些变化。

 

<Previous Page |  page: 1 2 3 4 5 6 | Next Page>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值