我正在开发一款游戏,其中包括在一个大世界中行走,周围有树木、岩石等随机物体
现在我的目标是不让世界上的物体总量影响游戏的速度。这就是为什么我想也许我应该有一个物体数组,每个物体都有自己的位置,然后就用一个循环检查哪些是近/远然后分别使用 addChild/removeChild 我仍然相信这种方法将是一个问题,因为不断通过一个包含大量对象的数组并不是那么好..
所以我想我会问你们……你们将如何处理这项任务?代码示例将不胜感激 在此先感谢
我正在开发一款游戏,其中包括在一个大世界中行走,周围有树木、岩石等随机物体
现在我的目标是不让世界上的物体总量影响游戏的速度。这就是为什么我想也许我应该有一个物体数组,每个物体都有自己的位置,然后就用一个循环检查哪些是近/远然后分别使用 addChild/removeChild 我仍然相信这种方法将是一个问题,因为不断通过一个包含大量对象的数组并不是那么好..
所以我想我会问你们……你们将如何处理这项任务?代码示例将不胜感激 在此先感谢
我希望您需要一些数据结构,例如octree/quadtree,这取决于您的世界是 2D 还是 3D,它们将在世界生成阶段用您的所有静态对象填充。任何动态的东西(怪物等)都会自行移动通过这棵树的节点,并且对于显示,您只需使用半径方法,仅渲染(显示)那些与玩家处于特定树单元距离内的对象。使用这种方法,您只需要在您的玩家越过树单元格之间的边界时更改显示列表,您removeChild()
对所有那些现在太远的单元格中的对象以及addChild()
现在在显示范围内的对象执行一个操作。
编辑:更好的是,您可以拥有一个二维数组,其中包含您世界中的对象列表,以及它们的实际位置等,因此四叉树提供的不是可变粒度,您将拥有一个统一的网格,其中每个单元格能够容纳更多而不是单个对象。这个网格比四叉树更容易遍历,因为它自然地保持相邻元素的位置,当你的玩家连续移动通过网格时,这是最需要的。一个例子,主要是伪代码,但可以给你一个关于实际网格是什么样子的提示:
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 抓取数据,并将对象放入显示列表中。
如果您不需要您的对象在“视野”之外时保持不变,您可以在玩家视野距离的外部范围内生成它们,这样您就只会循环通过活动对象。当物体离玩家一定距离时,它们会被移除。如果您希望您的对象持久存在,您可以使用一些系统来确定是否需要更新对象;例如,您可以给每个对象一个“区域”属性。玩家区域和与玩家区域相邻的区域中的对象得到更新。那些不相邻的,不需要更新。