当前位置:嗨网首页>书籍在线阅读

06-用对象池管理对象实例

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

9.1.4 用对象池管理对象实例

读者已经学习了与声音相关的对象池,但是未曾将这个概念应用到游戏对象。由于对象池这种技术的设计初衷是为了节省处理时间,因此它非常适合于街机游戏,例如本章正在创建的游戏。有时,创建对象实例是一项比较耗费处理器的任务,使用对象池管理对象实例,可以避免在游戏运行期间执行类似的任务。特别是创建爆炸碎片时,会在1帧中创建多个对象。在一个处理能力比较弱的平台上(例如手持设备),对象池技术可以提高帧率。

1.在Geo Blaster扩展版中使用对象池

在本章的游戏中,将把对象池的概念应用到爆炸碎片上。当然,也可以把这个概念应用到陨石、导弹、飞碟以及其他需要多次创建的对象上。但本例仅关注爆炸碎片。读者将会看到,在JavaScript中添加对象池是一个相对简单但却非常强大的技术。

2.在游戏中添加对象池变量

为了创建爆炸碎片的对象池,需要在有的应用程序作用域范围内添加以下4个变量。

var particlePool = [];
var maxParticles = 200;
var newParticle;
var tempParticle;

particlePool数组用于保存碎片对象实例的列表,在后面将用到这些对象。当createExplode()函数需要使用碎片时,程序将首先检查数组中是否有可用对象。如果有可用对象,函数将从particlePool栈中的顶端“弹出”该对象,并将它赋值给应用程序作用域的变量newParticle。该变量将引用一个池中的对象。createExplode()函数会设置newParticle对象的属性,然后将其放入已经存在的particles数组的底部。

一旦碎片的生命耗尽,updateParticles()函数会将该碎片从particles数组中剥离,然后放入particlePool数组的底部。创建一个名为tempParticle的变量,在updateParticles()函数中将使用该变量在每一帧中引用新创建的对象实例。

在一个名为createObjectPools()的新函数中使用maxParticles变量的值。在创建声音和图片表的加载事件之前,应先在gameStateInit()函数中调用此函数。

下面所示为createObjectPools()函数。

function createObjectPools(){
  for (var ctr=0;ctr<maxParticles;ctr++){
   var newParticle = {};
   particlePool.push(newParticle)
  }
  console.log("particlePool=" + particlePool.length)
}

该函数从0循环到maxParticles的值减1,然后在对象中每个元素中放置一个通用对象。当需要一个碎片时,createExplode()函数将检查particlePool.length是否大于0。如果找到一个可用碎片,就会在设置碎片属性后将该碎片添加到particles数组中。如果没有可用碎片,则不会使用任何对象。

提示

用户可以对这个功能进行扩展。例如,当没有可用对象时,为其添加一个碎片。虽然本例没有添加该功能,但这却是一个常见的对象池算法。

以下是修改之后的createExplode()函数的全部代码。

function createExplode(x,y,num,type){
  playSound(SOUND_EXPLODE,.5);
  for (var partCtr=0;partCtr<num;partCtr++){
   if (particlePool.length > 0){
   newParticle = particlePool.pop();
   newParticle.dx = Math.random()*3;
   if (Math.random()<.5){
     newParticle.dx* = -1;
   }
   newParticle.dy = Math.random()*3;
   if (Math.random()<.5){
   newParticle.dy* = -1;
   }
   newParticle.life = Math.floor(Math.random()*30+30);
   newParticle.lifeCtr = 0;
   newParticle.x = x;
   newParticle.width = 2;
   newParticle.height = 2;
   newParticle.y = y;
   newParticle.type = type;
   //ConsoleLog.log("newParticle.life=" + newParticle.life);
   particles.push(newParticle);
   }
  }
}

updateParticles()函数将遍历particles数组中的实例,更新每个实例的属性,然后检查每个碎片的生命是否已经耗尽。如果是,函数将把该碎片放回到对象池中。为了将碎片重新放入池中,将以下代码添加到updateParticles()函数中。

if (remove){
  particlePool.push(tempParticle)
  particles.splice(particleCtr,1)
}