使用FLEX和Actionscript开发FLASH 游戏-嵌入资源和增加游戏元素(第二页,共四页)
GameObject.as
package
{
import flash.display.*;
import mx.collection.*;
import mx.core.*;
public class GameObjectManager
{
//double buffer
public var backBuffer:BitmapData;
//colour to use to clear backbuffer with
public var clearColor: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 avoid adding items
//a 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();
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();
new Bounce().startupBounce();
}
public function shutdown():void
{
shutdownAll();
}
public function enterFrame():void
{
//Calculate the time since the lastframe
var thisFrame:Date=new Date();
var seconds:Number=(thisFrame.getTime()-lastFrame.getTime())/1000.0;
lastFrame=thisFrame;
removeDeletedGameObjects();
insertNewGameObjects();
//now allow objects to update themselves
for each(var gameObject:GameObject in gameObjects)
{
if(gameObject.inuse)
gameObject.enterFrame(seconds);
}
drawObjects();
}
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):viod
{
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.removedAll();
}
protected function removedDeletedGameObjects():void
{
//insert the object acording 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.removedAll();
}
}
}
这里我们增加了三个新的变量:gameObjects,newGameObjects和removedGameObjects。gameObjects集合保存了在游戏中存在的所有游戏对象GameObjects(GameObjects用来代表在游戏中的任何元素,将在下面说明)。GameObjectManager将在这个集合的所有元素上循环来升级或者绘制游戏对象GameObjects。另外两个集合:newGameObjects和removedGameObjects保存在绘制循环中生成或者删除的游戏对象GameObjects。这么做的原因是当你在某个集合的元素的值上面循环时改变这个集合是不对的做法,下面的代码是一个你想要避免的例子。
for each(var gameObject:GameObject in gameObjects)
{
//this is a bad idea…
gameObjects.addItemAt(1,new GameObject());
gameObjects.addItemAt(2,new GameObject());
}
这不仅仅是限于ActionScript或者FLEX,许多编程语言特别地防止在某个集合上循环时改变它的元素的值。即使可能在某个循环时改变集合的值,这仍然是一个错误的做法,因为如果某个地方错了的话代码会变得非常难以调试。我们通过下面方式避免这个错误:把所有刚刚生成的游戏对象添加到newGameObjects集合(使用addGameObject函数)以及把所有被终止的游戏对象添加到removedGameObjects集合(使用removeGameObject函数)。这两个集合在我们进入循环之前通过insertNewGameObjects和DeleteRemovedGameObjects这两个函数与主要的gameObjects集合同步了。
我们给startup函数增加了一段代码来生成和初始化一个bounce对象。这个对象不是最终游戏的一部分,但是将作为一个示范来说明怎样来继承一个GameObject类来生成一个游戏的元素。Bounce类的代码将在下面详细说明。
我们的shutdown函数原来是一个空语句函数,现在调用了一个shutdownAll函数。shutdownAll函数在所有生成的游戏对象上依次调用shutdown函数。通过这种方法我们在离开游戏状态时(在我们的应用程序类里通过exitGame函数)通过能够只调用一次GameObjectManager的shutdown函数就可以清理整个GameObjects。
enterFrame函数升级后包含了调用insertNewGameObjects函数和removeDeletedGameObjects函数,这两个函数我们在前面已经提到,它们使得gameObjects集合反映了任何被开始或者被终结的GameObjects.我们也在gameObjects集合上循环,在所有的GameObjects上调用enterFrame函数。GameObject类(包括它被继承的类)在enterFrame函数这里升级它自身。例如一个敌人对象在调用enterFrame函数时将改变它在屏幕上的位置。最终我们调用drawObjects函数,它将在每个GameObject矩形化backBuffer然后调用copyToBackBuffer函数。正是通过copyToBackBuffer函数一个GameObject对象将自己绘制在屏幕上。现在我们已经知道GameObjectManager怎么管理一个GameObject的集合,现在让我们看看GameObject类。