您的位置:首页 > 其它

AOI(Area of Interest) - 基于单元格的算法简析

2011-08-15 23:36 211 查看
AOI( Area Of Interest )是网游服务器中必不可少要考虑的一个问题,当前主流的AOI算法依然是

基于2D的格子的, 场景均分成为等大的格子,每个Entity都根据其位置放到所属格子的链表中.

关键问题是当Entity移动后:

一是要找到该Entity看到了哪些新的otherEntitys,

二是要找到哪些otherEntitys以前可以看到而现在看不到了,

三是要找到该Entity被哪些新的otherEntitys看到了,

四是要找出以前看得到自己现在看不到自己的otherEntitys.

1, 假定所有Entity的看到见的格子的数量都一样,为N*N,这意味着自己看得见的Entity也一定看得见自己,而

自己看不见的Entity也一定看不见自己.因此当Entity移动后:

<1>,找出Entity移动后新增的可见格子,将这些格子中的其它Entity加入自己的可见列表中(或者通知客户端有新的Entity可见).

<2>,找出Entity移动前可见而移动后不可见的格子,将这些格子中的其它Entity从自己的可见列表中移除(或者通知客户端这些Entity不可见).

<3>,找出Entity移动后新增的可见格子,将自已加入到这些格子中的其它Entity的可见列表中(或者通知其对应的客户端有新的Entity可见).

<4>,找出Entity移动前可见而移动后不可见的格子,将自己从这些格子中的其它Entity的可见列表中移除(或者通知其对应的客户端本Entity不可见).

2, 如果每个Entity的视野大小不等。每个格子增加一个observerGrids链表,保存所有"存在看得见该格子的对象"的格子。

当Entity移动后:

假定Entity移动前所在的gird命名为oldGrid, 移动后所在的grid命名为newGrid.

<1>,找到该Entity看到了哪些新的otherEntitys.

找出Entity移动后新增的可见格子, 记为newVisibleGrids.

算法如下:

foreach nGrid in newVisibleGrids

{

foreach nEntity in nGrid.entityList

{

将nEntity加入到thisEntity的可见列表中.(通知thisEntity对应的客户端nEntity可见).

}

将newGrid加入nGrid.observerGirds中.

}

<2>,找到哪些otherEntitys以前可以看到而现在看不到了.

找出Entity移动前可见而移动后不可见的格子,记为newHideGrids.

算法如下:

foreach nhGrid in newHideGrids

{

//找出以前看得到而移动后看不到的entity.

for nhEntity in nhGrid.entityList

{

把nhEntity从thisEntity的可见列表中移除(通知客户端nhEntity不可见).

}

如果oldGrid.entityList中的所有entity都看不见nhGrid,则将oldGrid从nhGrid.observerGrids中移除.

}

注:可以考虑在每个grid中记下所属entity的最大视野,最小视野,平均视野优化移除算法.

<3>,找到该Entity被哪些新的otherEntitys看到了.

foreach nGrid in newGrid.observerGrids

{

//优化:这里可以先排除掉同时存在于oldGrid.observerGrids中的nGrid?

foreach otherEntity in nGrid.entityList

{

oldDist = otherEntity.pos - thisEntity.oldPos;

//oldPos为entity移动前的位置.

newDist = otherEntity.pos - thisEntity.pos;

//检测对于otherEntity来说是否为新增的可见entity.

如果oldDist > otherEntity.viewDist 且 newDist <=

otherEntity.viewDist

将thisEntity加入到otherEntity的可见列表中(通知otherEntity对应的客户端thisEntity可见).

}

}

<4>,找出以前看得到自己现在看不到自己的otherEntitys.

foreach oGrid in oldGrid.observerGrids

{

//优化:这里可以先排除掉同时存在于newGird.observerGrids中的oGrid?

foreach otherEntity in oGrid.entityList

{

oldDist = otherEntity.pos - thisEntity.oldPos;

//oldPos为entity移动前的位置.

newDist = otherEntity.pos - thisEntity.pos;

//检测对于otherEntity来说是否为新增的不可见entity.

如果oldDist <= otherEntity.viewDist 且 newDist >

otherEntity.viewDist

将thisEntity从otherEntity的可见列表中移除(通知otherEntity对应的客户端thisEntity不可见).

}

}

3,考虑多重感知系统,如视觉,听觉,嗅觉并存时的情况.

比如:一个Entity隐身后无法被视觉感知,但可以被听觉和嗅觉感知.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: