游戏开发:AOI的相关库

兴趣区域(AOI)是一种定位服务,当一个由(id, x, y)定义的单元进入或离开另一个单元的可见范围时,进入事件或离开事件就会触发,我们还可以使用 AOI 来查询一个单元附近的其他单元,所有这些过程都是高效的。本项目的目的是比较三种 AOI 模型的性能。它们分别是 Crosslink 模型、QuadTree 模型和 Tower 模型。

#include "crosslink_aoi/crosslink_aoi.h"
#include "quadtree_aoi/quadtree_aoi.h"
#include "tower_aoi/tower_aoi.h"

#include <chrono>

#define Log(fmt, ...)                  \
  do {                                 \
    fprintf(stderr, fmt, __VA_ARGS__); \
  } while (0)

const int kMapWidth = 1024;
const int kMapHeight = 1024;
const int kVisibleRange = 30;

void enter_callback(int me, int other) {
  Log("[unit(%d)] Say: unit(%d) Enter to my range\n", me, other);
}

void leave_callback(int me, int other) {
  Log("[unit(%d)] Say: unit(%d) Leave from my range\n", me, other);
}

template <class AOIImpl>
void AOIUsage() {
  AOIImpl aoi(kMapWidth, kMapHeight, kVisibleRange, enter_callback,
              leave_callback);
  aoi.AddUnit(1, 1, 1);
  aoi.AddUnit(2, 2, 2);
  aoi.AddUnit(3, 3, 3);
  aoi.UpdateUnit(1, 1000, 1000);
  aoi.UpdateUnit(1, 1, 1);
  aoi.RemoveUnit(1);
}

template <class AOIImpl>
void TestAOI(int max_units, float addSeq[], float updateSeq[]) {
  AOIImpl aoi(kMapWidth, kMapHeight, kVisibleRange, [](int, int) {},
              [](int, int) {});
  auto t1 = std::chrono::steady_clock::now();
  for (int i = 0; i < max_units; ++i) {
    aoi.AddUnit(i, addSeq[i], addSeq[i + 1]);
  }
  auto t2 = std::chrono::steady_clock::now();
  for (int i = 0; i < max_units; ++i) {
    aoi.UpdateUnit(i, updateSeq[i], updateSeq[i + 1]);
  }
  auto t3 = std::chrono::steady_clock::now();
  for (int i = 0; i < max_units; ++i) {
    aoi.RemoveUnit(i);
  }
  auto t4 = std::chrono::steady_clock::now();

  Log("[%s]:%d unit add,timespan=%ldms\n", typeid(aoi).name(), max_units,
      std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count());
  Log("[%s]:%d unit update,timespan=%ldms\n", typeid(aoi).name(), max_units,
      std::chrono::duration_cast<std::chrono::milliseconds>(t3 - t2).count());
  Log("[%s]:%d unit remove,timespan=%ldms\n", typeid(aoi).name(), max_units,
      std::chrono::duration_cast<std::chrono::milliseconds>(t4 - t3).count());
}

int main(int argc, char const* argv[]) {
  (void)argc;
  (void)argv;

  Log("%s", "CrosslinkAOI Usage:\n");
  AOIUsage<CrosslinkAOI>();
  Log("%s\n",
      "----------------------------------------------------------------------");
  Log("%s", "QuadTreeAOI Usage:\n");
  AOIUsage<QuadTreeAOI>();
  Log("%s\n",
      "----------------------------------------------------------------------");
  Log("%s", "TowerAOI Usage:\n");
  AOIUsage<TowerAOI>();
  Log("%s\n",
      "----------------------------------------------------------------------");

  Log("%s\n", "Benchmark:");
  for (int size = 1000; size <= 10000; size += 1000) {
    float addSeq[size * 2];
    float updateSeq[size * 2];
    for (int i = 0; i < size * 2; i += 2) {
      addSeq[i] = rand() % kMapWidth;
      addSeq[i + 1] = rand() % kMapHeight;
      updateSeq[i] = rand() % kMapWidth;
      updateSeq[i + 1] = rand() % kMapHeight;
    }

    TestAOI<CrosslinkAOI>(size, addSeq, updateSeq);
    Log("%s\n",
        "---------------------------------------------------------------------"
        "-");
    TestAOI<QuadTreeAOI>(size, addSeq, updateSeq);
    Log("%s\n",
        "---------------------------------------------------------------------"
        "-");
    TestAOI<TowerAOI>(size, addSeq, updateSeq);
    Log("%s\n",
        "---------------------------------------------------------------------"
        "-");
  }
  return 0;
}

Benchmark

上述数据在我的 i7-7700K CPU 上进行了测试。
我们在一张 1024*1024 的地图上模拟 N 个单位的 N 次随机移动,每个单位有 30 个可见范围。(1000<=N<=10000)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值