hanxi / blog

涵曦的博客
https://blog.hanxi.cc
56 stars 5 forks source link

AOI (Area Of Interest)算法实现 #78

Open hanxi opened 3 years ago

hanxi commented 3 years ago

参考

1. 九宫格

绘制如下的 2D 的地图:

grid

计算九宫格:

{-1,-1}, {0,-1}, {1,-1}
{-1,0},  {0,0},  {1,0},
{-1,1},  {0,1},  {1,1},

用当前格子坐标加上上面的二维数组就能找出周围的九个格子(包括自己),当然处于边界的时候需要判断坐标的范围。

首先确定数据结构如下图:

grid_struct

数据结构的定义大概是下面这样的:

struct aoi_space {
    int w;
    int h;
    int nx;
    int ny;
    struct grid * grid_list;
};
struct grid {
    int gid;
    struct map * object_map;
};
struct object {
    int id;
    int position[2];
};

再定义操作接口:

// op: 'e' enter
// op: 'l' leave
// op: 'm' move
typedef void (AoiCallback)(int watcher, int marker, char op);

struct aoi_space * aoi_new(int w, int h, int nx, int ny, AoiCallback cb);
void aoi_delete(struct aoi_space * aoi);

void aoi_enter(struct aoi_space * aoi, int id, int x, int y);
void aoi_leave(struct aoi_space * aoi, int id);
void aoi_move(struct aoi_space * aoi, int id, int x, int y);

这里从接口可以看出:

方案实现规则引用 co lin 的描述:

  • 进入场景:进入一个格子,取出周围9格的对象,向它们发送Enter(我)事件,同时向我发送Enter(对象)事件。
  • 离开场景:取出周围9格的对象,向它们发送Leave(我)事件。
  • 移动:
    • 如果没跨格子,直接取9格的对象,向它们发送移动事件。
    • 如果跨过格子,计算{OldGrid-NewGrid},向它们发送Leave(我)事件,向我发送Leave(对象)事件;计算{NewGrid-OldGrid}集合,向它们发送Enter(我)事件,向我发送Enter(对象事件;计算{NewGrid*OldGrid}集合,向他们发送移动事件。

grid_move

为了简化代码实现,还是用 Lua 来实现示例。主要原因是如果实现 map 就觉得代码长了几行,如果是正式环境还是用 C 实现更高效。

Lua 代码实现在这里 https://github.com/hanxi/aoi

2. 十字链表

有空再研究。。。