AS3仅渲染附近的对象

时间:2013-02-28 09:13:49

标签: algorithm actionscript-3 flash flex

我正在开发一款游戏,其中包括在一个大型世界中漫步,周围有随机物体,如树木,岩石等等。

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

所以我想我会问你们..你们将如何处理这项任务? 非常感谢代码示例 提前致谢

2 个答案:

答案 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)

如果您不需要对象在“视图”之外保持不变,则可以在玩家视图距离的外部范围内生成它们,这样您就只能循环遍历活动对象。当物体离玩家一定距离时,它们会被移除。 如果您希望对象持久化,可以使用某个系统来确定是否需要更新对象;例如,您可以为每个对象提供“区域”属性。播放器区域中和玩家区域附近区域中的对象会更新。那些不相邻的,不需要更新。