我正在开发一款游戏,其中包括在一个大型世界中漫步,周围有随机物体,如树木,岩石等等。
现在我的目标不是让世界上的物体总量影响游戏的速度。 这就是为什么我认为我应该有一个对象数组, 每个对象都有自己的位置, 然后只需使用一个循环来检查哪些是近/远 然后分别使用addChild / removeChild 我仍然相信这种方法会成为一个问题,因为不断地通过一个包含大量物体的数组并不是那么好..
所以我想我会问你们..你们将如何处理这项任务? 非常感谢代码示例 提前致谢
答案 0 :(得分:3)
我希望您需要一些数据结构,例如octree/quadtree,取决于您的世界是2D还是3D,将在世界生成阶段使用所有静态对象填充。任何动态(怪物等)都会自己穿过这棵树的节点,对于显示器,你只需使用半径方法,只渲染(显示)与玩家相距某个树单元格的那些对象。使用这种方法,当玩家越过树状单元格之间的边界时,您只需要更改显示列表,对现在太远的单元格中的所有对象执行removeChild()
,并addChild()
开启现在处于显示范围内的那些。
编辑:更好的是,您可以拥有一个2D数组,其中包含您所在世界中的对象列表及其实际位置等,因此,除了可变粒度外,四叉树提供了一个统一的网格,其中每个单元都能够持有多个物体。这个网格比四叉树更容易穿越,因为它自然地保持了相邻元素的位置,当玩家连续穿过网格时,这是最需要的。一个例子,主要是伪代码,但可以给你一个关于实际网格的暗示的提示:
class World {
var GRID:Vector.<Vector.<Vector.<GameObject>>>; // the grid
const GRAN:int=100; // this many x this many is one GRID cell
var gridWidth:int;
var gridHeight:int;
public function World(w:int,h:int) { // size in pixels, for example. This depends on how you display objects
gridWidth=1+Math.floor(w/GRAN);
gridHeight=1+Math.floor(h/GRAN);
GRID=new Vector.<Vector.<Vector.<GameObject>>>(gridWidth,true); // fixed size, it optimizes performance
var i:int; var j:int;
for (i=0;i<gridWidth;i++) {
GRID[i]=new Vector.<Vector.<GameObject>>(gridHeight,true); // again fixed size
for (j=0;j<gridHeight;j++) GRID[i][j]=new Vector.<GameObject>();
// ^ variable size, as initially the world is empty, and it will get
//filled with stuff dynamically. But we need to allocate the data structure
}
}
public function PlaceObject(ob:GameObject):void {
// puts an object into grid and assigns it grid position to refer the grid
var gx:int=Math.floor(ob.x/GRAN);
var gy:int=Math.floor(ob.y/GRAN);
ob.gridX=gx;
ob.gridY=gy;
GRID[gx][gy].push(ob);
// error control is absent, but should be.
}
public function MoveObject(ob:GameObject):void {
// called if game engine moves an object. It has its X&Y changed, but grid position must be updated
var gx:int=Math.floor(ob.x/GRAN);
var gy:int=Math.floor(ob.y/GRAN);
if ((ob.gridX==gx)&&(ob.gridY==gy)) return; // this object didn't leave its grid node
GRID[ob.gridX][ob.gridY].splice(GRID[ob.gridX][ob.gridY].indexOf(ob),1);
// will break if the object is not in GRID, so integrity check is needed here
ob.gridX=gx;
ob.gridY=gy;
GRID[gx][gy].push(ob);
}
...
}
等。在这个类之外,你放置一个具有玩家GRID位置的渲染器,并从指定半径的GRID中抓取数据,并将对象放入显示列表。
答案 1 :(得分:0)
如果您不需要对象在“视图”之外保持不变,则可以在玩家视图距离的外部范围内生成它们,这样您就只能循环遍历活动对象。当物体离玩家一定距离时,它们会被移除。 如果您希望对象持久化,可以使用某个系统来确定是否需要更新对象;例如,您可以为每个对象提供“区域”属性。播放器区域中和玩家区域附近区域中的对象会更新。那些不相邻的,不需要更新。