[game] 十字链表的AOI算法实现

转载:https://www.cnblogs.com/rond/p/6114919.html

AOI主要有九宫格、灯塔和十字链表的算法实现。本文阐述十字链表的实现和尝试。

  1. 基本原理
    根据二维地图,将其分成x轴和y轴两个链表。如果是三维地图,则还需要维护多一个z轴的链表。将对象的坐标值按照大小相应的排列在相应的坐标轴上面。

  2. 基本接口
    对对象的操作主要有以下三个接口:

add:对象进入地图;
leave:对象离开地图;
move:对象在地图内移动。
2. 算法实现
既然是链表,很自然地想到用线性表来实现。因为存在向前和向后找的情况,所以使用双链表实现。其实实现也是非常简单,就是两个双链表(这里以二维地图举例)。那么我们的节点需要四个指针,分布为x轴的前后指针,y轴的前后指针。

// 双链表(对象)

class DoubleNode
{
public:DoubleNode(string key, int x, int y){this->key = key;this->x = x;this->y = y;xPrev = xNext = NULL;};DoubleNode * xPrev;DoubleNode * xNext;DoubleNode * yPrev;DoubleNode * yNext;string key;  // 只是一个关键字int x; // 位置(x坐标)int y; // 位置(y坐标)private:};

下面是地图场景信息和接口。这里的实现比较粗略,是带头尾的的双链表,暂时不考虑空间占用的问题。类Scene有分别有一个头尾指针,初始化的时候会为其赋值,主要用DoubleNode类的指针来存储x轴和y轴的头尾。初始化的时候,将_head的next指针指向尾_tail;将_tail的prev指针指向_head。

// 地图/场景

class Scene
{
public:Scene(){this->_head = new DoubleNode("[head]", 0, 0); // 带头尾的双链表(可优化去掉头尾)this->_tail = new DoubleNode("[tail]", 0, 0);_head->xNext = _tail;_head->yNext = _tail;_tail->xPrev = _head;_tail->yPrev = _head;};// 对象加入(新增)DoubleNode * Add(string name, int x, int y);// 对象离开(删除)void Leave(DoubleNode * node);// 对象移动void Move(DoubleNode * node, int x, int y);// 获取范围内的AOI (参数为查找范围)void PrintAOI(DoubleNode * node, int xAreaLen, int yAreaLen);private:DoubleNode * _head;DoubleNode * _tail;
};

2.1. add(进入地图)
将DoubleNode对象插入到十字链表中。x轴和y轴分别处理,处理方法基本一致。其实就是双链表的数据插入操作,需要从头开始遍历线性表,对比相应轴上的值的大小,插入到合适的位置。

void _add(DoubleNode * node)
{// x轴处理DoubleNode * cur = _head->xNext;while(cur != NULL){if((cur->x > node->x) || cur==_tail) // 插入数据{node->xNext = cur;node->xPrev = cur->xPrev;cur->xPrev->xNext = node;cur->xPrev = node;break;}cur = cur->xNext;}// y轴处理cur = _head->yNext;while(cur != NULL){if((cur->y > node->y) || cur==_tail) // 插入数据{node->yNext = cur;node->yPrev = cur->yPrev;cur->yPrev->yNext = node;cur->yPrev = node;break;}cur = cur->yNext;}
}

假设可视范围为x轴2以内,y轴2以内,则运行:

分别插入以下数据a(1,5)、f(6,6)、c(3,1)、b(2,2)、e(5,3),然后插入d(3,3),按照x轴和y轴打印其双链表结果;
插入d(3,3)数据,求其可视AOI范围(如图,除了f(6,6),其它对象都在d的可视范围内)。
控制台结果(前8行):

步骤1结果图示:

步骤2结果图示:


2.2. leave(离开地图)和move(移动)
其实都是双链表的基本操作,断掉其相应的指针就好了。按理,是需要

move和leave操作如图,move是将d(3,3)移动到(4,4),然后再打印其AOI范围。

控制台结果:

移动后AOI范围图示:

  1. 完整代码实例
#include "stdafx.h"#include "stdio.h"#include <iostream>#include <string>using namespace std;// 双链表(对象)class DoubleNode{public:DoubleNode(string key, int x, int y){this->key = key;this->x = x;this->y = y;xPrev = xNext = NULL;};DoubleNode * xPrev;DoubleNode * xNext;DoubleNode * yPrev;DoubleNode * yNext;string key;int x; // 位置(x坐标)int y; // 位置(y坐标)private:};// 地图/场景class Scene{public:Scene(){this->_head = new DoubleNode("[head]", 0, 0); // 带头尾的双链表(可优化去掉头尾)this->_tail = new DoubleNode("[tail]", 0, 0);_head->xNext = _tail;_head->yNext = _tail;_tail->xPrev = _head;_tail->yPrev = _head;};// 对象加入(新增)DoubleNode * Add(string name, int x, int y){DoubleNode * node = new DoubleNode(name, x, y);_add(node);return node;};// 对象离开(删除)void Leave(DoubleNode * node){node->xPrev->xNext = node->xNext;node->xNext->xPrev = node->xPrev;node->yPrev->yNext = node->yNext;node->yNext->yPrev = node->yPrev;node->xPrev = NULL;node->xNext = NULL;node->yPrev = NULL;node->yNext = NULL;};// 对象移动void Move(DoubleNode * node, int x, int y){Leave(node);node->x = x;node->y = y;_add(node);};// 获取范围内的AOI (参数为查找范围)void PrintAOI(DoubleNode * node, int xAreaLen, int yAreaLen){cout << "Cur is: " << node->key  << "(" << node ->x << "," << node ->y << ")" << endl;cout << "Print AOI:" << endl;// 往后找DoubleNode * cur = node->xNext;while(cur!=_tail){if((cur->x - node->x) > xAreaLen){break;}else{int inteval = 0;inteval = node->y - cur->y;if(inteval >= -yAreaLen && inteval <= yAreaLen){cout << "\t" << cur->key  << "(" << cur ->x << "," << cur ->y << ")" << endl;}}cur = cur->xNext;}// 往前找cur = node->xPrev;while(cur!=_head){if((node->x - cur->x) > xAreaLen){break;}else{int inteval = 0;inteval = node->y - cur->y;if(inteval >= -yAreaLen && inteval <= yAreaLen){cout << "\t" << cur->key  << "(" << cur ->x << "," << cur ->y << ")" << endl;}}cur = cur->xPrev;}};// 调试代码void PrintLink()  // 打印链表(从头开始){// 打印x轴链表DoubleNode * cur = _head->xNext;while (cur != _tail){cout << (cur->key) << "(" << (cur->x) <<"," << (cur->y) << ") -> " ;cur = cur->xNext;}cout << "end" << endl;// 打印y轴链表cur = _head->yNext;while (cur != _tail){cout << (cur->key) << "(" << (cur->x) <<"," << (cur->y) << ") -> " ;cur = cur->yNext;}cout << "end" << endl;};private:DoubleNode * _head;DoubleNode * _tail;void _add(DoubleNode * node){// x轴处理DoubleNode * cur = _head->xNext;while(cur != NULL){if((cur->x > node->x) || cur==_tail) // 插入数据{node->xNext = cur;node->xPrev = cur->xPrev;cur->xPrev->xNext = node;cur->xPrev = node;break;}cur = cur->xNext;}// y轴处理cur = _head->yNext;while(cur != NULL){if((cur->y > node->y) || cur==_tail) // 插入数据{node->yNext = cur;node->yPrev = cur->yPrev;cur->yPrev->yNext = node;cur->yPrev = node;break;}cur = cur->yNext;}}};// --------------------------------------------void main(){Scene scene = Scene();// 增加scene.Add("a", 1, 5);scene.Add("f", 6, 6);scene.Add("c", 3, 1);scene.Add("b", 2, 2);scene.Add("e", 5, 3);DoubleNode * node = scene.Add("d", 3, 3);scene.PrintLink();scene.PrintAOI(node, 2, 2);// 移动cout << endl << "[MOVE]" << endl;scene.Move(node, 4, 4);scene.PrintLink();scene.PrintAOI(node, 2, 2);// 删除cout << endl << "[LEAVE]" << endl;scene.Leave(node);scene.PrintLink();}

十字链表的AOI算法实现相关推荐

  1. noj数据结构稀疏矩阵的加法十字链表_一个算法毁了一款好游戏?算法和数据结构到底有多重要?...

    来源 | 异步 | 文末赠书 前段时间大火的国产游戏--<太吾绘卷>,由于创新的玩法和精良的制作一度广受好评,然而随着玩家游戏的深入和时长的积累,发现该游戏在玩的过程中游戏外的问题很多很多 ...

  2. c语言建立并存储树,利用十字链表存储树结构(便于同时求出某一点的入度与出度)------C语言实现...

    #include #include #include /* 利用十字链表存储有向图,可用于同时查找某个顶点的出度与入度: */ typedef struct edge {//顶点表 int headv ...

  3. 算法:游戏内AOI视野算法(十字链表)

    为什么要有这个算法? 对于一个游戏场景内的实体来说,当战斗频繁的时候,可能存在上千实体的数据同步,例如上千实体移动时的坐标同步,大型战斗场景时全场景实体的属性的同步等等,这样就会造成一个问题,同步数据 ...

  4. 游戏算法-AOI十字链表入门简单版python

    AOI十字链表python简单实现,仅用作学习,理解基本原理 AOI一般是C++去实现,本文章python写仅用来入门了解 场景内维护两个实体链表 list_x和list_y 所有实体根据x坐标大小排 ...

  5. 稀疏矩阵的十字链表存储表示和实现(第五章 P104 算法5.4)

    稀疏矩阵的十字链表存储 当矩阵的非零元个数和位置在操作过程中变化较大时,就不宜采用顺序存储结构来表示三元组的线性表.对这种类型的矩阵,采用链式存储结构表示三元组的线性表更为恰当. 在链表中,每个非零元 ...

  6. 图十字链表并求度c语言,第5章_西安电子科技大学出版社:算法与数据结构-C语言描述(樊希平)_doc_大学课件预览_高等教育资讯网...

    第5章 数组和广义表要点: 1.掌握数组元素存储位置的换算: 2.了解特殊矩阵地存储方法和元素存储位置计算: 3.了解广义表的长度.深度.head.tail等概念和操作和存储结构. 教材习题解答: 5 ...

  7. 经典算法题每日演练——第二十一题 十字链表

    上一篇我们看了矩阵的顺序存储,这篇我们再看看一种链式存储方法"十字链表",当然目的都是一样,压缩空间. 一:概念 既然要用链表节点来模拟矩阵中的非零元素,肯定需要如下5个元素(ro ...

  8. 十字链表计算矩阵乘积 c语言,求用十字链表实现矩阵相加算法(C语言)急!!!...

    匿名用户 1级 2010-02-09 回答 我有一个可以用的.怎么给你?百度hi我吧. 算了,我贴上来吧,由电脑编程网整理: #include #include #define smax 45 typ ...

  9. 游戏开发中AOI算法总结

    定义 在MMO游戏中,在一些多人玩法中,通常出现很多玩家在同一张地图上移动的情况,假如一个玩家发生了移动,释放技能,更换装扮-这时就需要通知其他玩家,而如果通知整张地图上的所有玩家的话,显然是不现实的 ...

最新文章

  1. JSIS3D:具有多任务点向网络和多值条件随机场的3D点云联合语义-实例分割
  2. C++中有string类,string是一个类不是一种类型,c语言中没有
  3. 鸿蒙是安卓换皮UI,鸿蒙2.0是安卓换皮?还真不是
  4. “融合、智能、绿色”施耐德电气线上工博以全生命周期解决方案助推数字化
  5. 按用户设置计算机权限,巧妙设置用户权限 管理学生机房计算机
  6. Spring boot(8)---手动构建maven项目springboot
  7. 风控趋势|隐私计算几大落地场景与三方数据市场
  8. centos 6.4 更新源地址
  9. OpenCV-理想高通低通滤波器(C++)
  10. 算法笔记-----归并排序
  11. 安装Anaconda3 5.2.0后只有Anaconda Prompt,没有spyder等
  12. java extjs 教程_EXTJS入门教程及其框架搭建
  13. acm题库及答案 java_ACM试题及答案.docx
  14. Oracle 对 JDK收费和.NET Core 给我们的机遇
  15. 对计算机病毒的防治也,对计算机病毒及防范对策研究.doc
  16. C函数的参数中有取地址符
  17. 数据挖掘基础学习笔记
  18. SIGMOD 2021 论文简析:当公交网络连接满足通勤需求时的公共交通规划 Public Transport Planning
  19. 网红湾湾否认与李易峰恋情,网友:其实两人很般配!
  20. AP侧,BP侧如何理解?

热门文章

  1. 如何实现HMI触摸屏远程上下载程序?
  2. c#配置安装IIS管理器
  3. 六自由度机器人牛顿-欧拉法动力学建模(自己学习用)
  4. 解决读入数据集乱码问题
  5. 在线考试系统设计时必须考虑的问题之二------------人性化问题
  6. 游戏设计参考:魔兽世界WOW角色的基本属性及其作用
  7. 北京购车摇号满两年送车牌
  8. C#读写注册表及 WOW6432Node 问题
  9. asp.net奶茶店进销存系统
  10. 视频游戏产业因区块链而被限制的 3 个原因