使用FLEX和Actionscript开发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>