96 lines
4.4 KiB
Markdown
96 lines
4.4 KiB
Markdown
![]() |
导航地图NavMap,会把之前的逻辑串联起来,有关键字[[partial分部类和方法]],声明了,各个寻路顶点的数据容器,寻路区域的数组;
|
|||
|
还有边界字典borderDic和areaIDDic,用来处理,可用的区域边界;
|
|||
|
另外还有3个Action委托函数,用来处理,Scene场景,配合NavView相关逻辑,绘制寻路结果;
|
|||
|
|
|||
|
![[Pasted image 20240408145744.png]]
|
|||
|
|
|||
|
GetBorderLstByAreaID函数接口,通过区域id,从边界字典borderDic,拿到对应的边界队列容器
|
|||
|
|
|||
|
![[Pasted image 20240408155423.png]]
|
|||
|
|
|||
|
设置基础节点数据,是遍历所有的,节点,根据索引大小,设置key关联字符
|
|||
|
|
|||
|
![[Pasted image 20240408153356.png]]
|
|||
|
|
|||
|
继续,如果borderDic边界字典容器,包含上述key索引,就会调用边界的areaID1和areaID2,两个区域ID,完成新key构建,放到areaIDDic边界字典容器;而且这个不是单独的边界,isShared布尔,会设置为true;
|
|||
|
|
|||
|
一开始的时候,是没有对应key的,就往边界字典borderDic里面,构建NavBorder边界体,加到容器即可;
|
|||
|
|
|||
|
![[Pasted image 20240408153547.png]]
|
|||
|
|
|||
|
这是单独边界
|
|||
|
|
|||
|
![[Pasted image 20240408155849.png]]
|
|||
|
|
|||
|
这些是isShared为true的共享边界
|
|||
|
|
|||
|
![[Pasted image 20240408160015.png]]
|
|||
|
|
|||
|
继续,通过边界的isShared布尔变量,加到singleLst队列容器,再从边界字典borderDic中移除它们;
|
|||
|
使用,上述解析的GetBorderLstByAreaID函数,通过区域id索引areaID,对区域的边界队列borderLst完成赋值;
|
|||
|
|
|||
|
![[Pasted image 20240408155535.png]]
|
|||
|
|
|||
|
GetBorderByAreaIDKey接口,通过key在区域字典areaIDDic中,拿到它的边界
|
|||
|
|
|||
|
![[Pasted image 20240408160642.png]]
|
|||
|
|
|||
|
OnXZSegment接口,判断叉乘是否为0,也就是面积为0,点乘为负数,也就是方向相反,判断落点是否在线条上;
|
|||
|
这个接口,后续是用于,判断落点是否在,寻路的检测区域内,如果在线上,那就肯定在区域内了,所以直接返回true即可,参考[[向量Dot点乘与Cross叉乘的概念及几何意义]];
|
|||
|
|
|||
|
![[Pasted image 20240408160737.png]]
|
|||
|
|
|||
|
通过[[PNPoly算法]],配合OnXZSegment接口,判断向量点,是否在检测区域内
|
|||
|
|
|||
|
![[Pasted image 20240408161029.png]]
|
|||
|
|
|||
|
算法对应的C语言公式:
|
|||
|
|
|||
|
``` c
|
|||
|
int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
|
|||
|
{
|
|||
|
int i, j, c = 0;
|
|||
|
for (i = 0, j = nvert-1; i < nvert; j = i++) {
|
|||
|
if ( ((verty[i]>testy) != (verty[j]>testy)) &&
|
|||
|
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
|
|||
|
c = !c;
|
|||
|
}
|
|||
|
return c;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
调用,上述检测区域接口,判断传参坐标pos,是否在检测区域,然后返回,对应的检测区域id即可
|
|||
|
|
|||
|
![[Pasted image 20240408161401.png]]
|
|||
|
|
|||
|
这是一个自定义堆队列类PEQue,也是继承自[[IComparable接口]],具体逻辑解析,参考[[基于堆实现优先级队列]]即可
|
|||
|
|
|||
|
![[Pasted image 20240408165629.png]]
|
|||
|
|
|||
|
导航地图NavMap的分部类,对应的脚本位置
|
|||
|
|
|||
|
![[Pasted image 20240408165744.png]]
|
|||
|
|
|||
|
它的结构,是由两个region组成,分别是A星算法和漏斗算法
|
|||
|
|
|||
|
![[Pasted image 20240408165934.png]]
|
|||
|
|
|||
|
A星算法,主要是用于,检测开始点,和结束点,它们之间的寻路路径,所路过的NavArea寻路区域;
|
|||
|
声明开始点、结束点,所在对应的区域m_startArea和m_endArea;
|
|||
|
而检测队列m_detectQue会使用,上述优先级队列相关逻辑;
|
|||
|
另外还有两个队列容器,分别是已完成检测的m_finishLst,和最终返回得到的,所路过的m_pathLst区域队列容器;
|
|||
|
|
|||
|
![[Pasted image 20240408170017.png]]
|
|||
|
|
|||
|
检测周边区域的核心逻辑;
|
|||
|
完成邻近区域的,前一个区域preArea字段,和总距离sumDistance字段赋值;
|
|||
|
通过一系列布尔判断后,放到已检测队列容器m_detectQue,参考[[IsPositiveInfinity]];
|
|||
|
通过寻路区域的,CalcNavAreaDis接口,拿到跟最终位置区域的距离,加上当前寻路总距离sumDistance,作为priority优先级赋值,具体逻辑解析, [[A星寻路算法]]即可;
|
|||
|
|
|||
|
![[Pasted image 20240408170541.png]]
|
|||
|
|
|||
|
跟A星算法相关逻辑一样,倒着获取,寻路的前一个节点preArea;
|
|||
|
从最终寻路的结束点end,通过while死循环函数,倒着找,前一个节点preArea,直到它是null空值为止;
|
|||
|
然后,使用分部类NavMap中GetBorderByAreaIDKey接口,通过key,在区域字典areaIDDic中,拿到对应的边界即可
|
|||
|
|
|||
|
![[Pasted image 20240408171039.png]]
|