2

我正在开发一款游戏,其中包括在一个大世界中行走,周围有树木、岩石等随机物体

现在我的目标是不让世界上的物体总量影响游戏的速度。这就是为什么我想也许我应该有一个物体数组,每个物体都有自己的位置,然后就用一个循环检查哪些是近/远然后分别使用 addChild/removeChild 我仍然相信这种方法将是一个问题,因为不断通过一个包含大量对象的数组并不是那么好..

所以我想我会问你们……你们将如何处理这项任务?代码示例将不胜感激 在此先感谢

4

2 回答 2

3

我希望您需要一些数据结构,例如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 抓取数据,并将对象放入显示列表中。

于 2013-02-28T09:26:25.157 回答
0

如果您不需要您的对象在“视野”之外时保持不变,您可以在玩家视野距离的外部范围内生成它们,这样您就只会循环通过活动对象。当物体离玩家一定距离时,它们会被移除。如果您希望您的对象持久存在,您可以使用一些系统来确定是否需要更新对象;例如,您可以给每个对象一个“区域”属性。玩家区域和与玩家区域相邻的区域中的对象得到更新。那些不相邻的,不需要更新。

于 2013-02-28T09:56:58.413 回答