JPS(jump point search)寻路算法

JPS(jump point search)跳跃点寻路算法是对AStar寻路算法的一个改进。

AStar 算法在扩展节点时会把所有相邻的节点考虑进去,当地图比较大时,openList 中的节点数量会很多,搜索效率较低。

在两点之间没有障碍物时,那么中间的节点对我们来说是没有用的,不希望添加到 openList
如下

可以看到JPS 算法不是每个节点都紧密连接的,而是跳跃性的或者说只有需要转弯的节点(也叫拐点)才会被考虑,所以叫跳跃点(Jump Point)。

在实现JPS前先了解它的规则
1.强迫邻居:节点X的邻居节点有障碍物,且X的父节点P经过X到达N的距离代价,比不经过X到大N的任一路径的距离代价都小,则称N是X的强迫邻居。
不知道说的什么意思,看下图

2.跳点(Jump Point):什么样的节点可以作为跳点
(1)节点 A 是起点、终点.
(2)节点A 至少有一个强迫邻居.
(3)父节点在斜方向(斜向搜索),节点A的水平或者垂直方向上有满足 (1)、(2) 的节点

(1)、(2)两条不需要解释,下面看下什么是斜向搜索,下面是一个方向为 (1, 1)斜向搜索
在搜索过程中它可以将水平和垂直方向两个分量,分解为一个方向为(1, 0)的水平搜索,一个方向为(0, 1)的垂直搜索
同理斜向有四种方向
左上 (-1, 1) ——>对应的水平 (-1, 0),垂直 ( 0, 1)
右上 ( 1, 1) ——>对应的水平 ( 1, 0),垂直 ( 0, 1)
右下 ( 1, -1) ——>对应的水平 ( 1, 0),垂直 ( 0, -1)
左下 (-1, -1) ——>对应的水平 (-1, 0),垂直 ( 0, -1)

如上所说(3)的情形即为如下

JSP寻路算法原理如下
JPS 算法和AStar算法非常相似,如果不了解AStar算法的可以先看下 AStar再看JPS会事半功倍。

一.定义开放列表 openList,将起点 S 加入到 openList
二.如果开放列表中节点数大于0个,则取出权值最低的节点 A,如果节点A 是终点则搜索成功返回。
先进行直线搜索 ( 上(0, 1)、下(0, -1)、 左(-1, 0)、右(1, 0))四个方向,根据情况判断需要搜索的方向放入dirList

dirList = {};
if(A没有父节点)
{dirList = {上(0, 1)、下(0, -1)、左(-1, 0)、右(1, 0)};
}
else
{父方向分解的水平 horizontalDir、垂直方向verticalDir // 如父节点P到节点A的方向 PA斜向右上(1, 1)则horizontalDir=(1, 0)、verticalDir=(0,1)// 如父节点P到节点A的方向 PA向右(1, 0)则horizontalDir=(1, 0)、verticalDir=(0,0)if(horizontalDir != (0, 0)){dirList.Add(horizontalDir);}if(verticalDir != (0, 0)){dirList.Add(verticalDir );}
}foreach (方向 dir in dirList)
{节点B = Awhile(true){B += dir //向前迈进一步if(B 是跳点){给B赋权值并且将跳点加入 openList break;}if(B是障碍物、地图边界){break;}}
}

然后搜索斜方向(左上(-1, 1)、右上( 1, 1)、右下 (1, -1)、左下 (-1, -1)) 四个方向,根据情况判断需要搜索的方向放入dirList

dirList = {}if(A没有父节点)
{dirList = {左上(-1, 1)、右上(1, 1)、右下(1, -1)、左下(-1, -1)};
}
else
{父节点为 PPA=(X,Y)if(X != 0 && Y != 0){//斜向 PA(X,Y)搜索dirList.Add(PA(X,Y));}foreach(Node N in A的所有强制邻居){// AN 一定是斜向的dirList.Add(AN);}
}foreach (方向 dir in dirList)
{dir 分解出来一个水平方向 horizontal、一个垂直方向vertical// 先水平方向搜索节点B = Awhile(true){B += horizontal //水平向前迈进一步if(B 是跳点){给B赋权值并且将跳点加入 openList break;}if(B是障碍物、地图边界){break;}}令 B = Awhile(true){B += vertical//垂直向前迈进一步if(B 是跳点){给B赋权值并且将跳点加入 openList break;}if(B是障碍物、地图边界){break;}}令 B = Awhile(true){B += dir //斜向迈进一步if(B 是跳点){给B赋权值并且将跳点加入 openList break;}if(B是障碍物、地图边界){break;}}
}

注意事项:
(1).如果节点A没有父方向P(起点)
则直线方向按照 (上下左右)四个方向, dirList = {上、下、左、右}
斜方向按照(左上、右上、右下、左下)四个方向搜索 dirList = {左上、右上、右下、左下}
(2).如果节点A有父方向P
则 PA=(X,Y)
将PA分解为水平 horizontalDir=(X,0),垂直 verticalDir=(0,Y)

还是先考虑水平和垂直的搜索方向,dirList = {}
如果 horizontalDir=(X,0) != (0, 0) 即 X != 0 则 将 horizontalDir 加入到 dirList
如果 verticalDir=(0,Y) !=(0, 0) 即 Y != 0 则 将 verticalDir 加入到 dirList
直线方向搜索 dirList 中的方向

然后是斜向 dirList = {}
如果 PA=(X,Y),X != 0 且 Y != 0, 则将 PA方向加入到 dirList
如果 A有强迫邻居 {N1, N2, N3…},则将 AN1,AN2,AN3,。。。都加入到 dirList

三.回到步骤二继续搜索

下面以一个例子演示JPS搜索的全过程
讲解在图下面,先看图,在看图下边的讲解

看上图,S为起点以绿色格子表示,E为终点以红色表示,棕色节点为障碍物不可通过
1.开始将 S加入到openList
2.从openList 中取出权值最小的节点,此时是S节点,S没有父方向,则开始搜索 (左、上、右、下)四个直线方向,左A1、上B1、下D1处遇到地图边界,C1处遇到障碍物。直线搜索结束

3.看上图
开始向S左上(-1, 1) SE1方向的斜向搜索
SE1(-1, 1)可以分解为水平向左 (-1, 0)和垂直向上(0, 1)两个方向
则SE1斜向搜索需要搜索 水平向左 (-1, 0)、垂直向上(0, 1)和斜向左上(-1, 1) 三个方向
E1向左搜索到达边界,向上搜索到达边界,E1不是跳点,斜向迈进一步到达E2
E2向左搜索到达边界,向上搜索到达边界,E2不是跳点,且已到达边界,结束

4.看上图
开始向S右上(1, 1) SF1方向斜向搜索
SF1(1, 1)可以分解为水平向右(1, 0)和垂直向上(0, 1)两个方向
则SF1斜向搜索需要搜索 水平向右(1, 0),垂直向上(0, 1)和 斜向右上(1, 1)三个方向
F1 向右搜索到障碍物,向上搜索到边界, F1不是跳点,斜向迈进一步到达F2
F2 向右搜索到障碍物,向上搜索到边界, F2不是跳点,斜向迈进一步到达F3
F3 向右搜索到障碍物,向上搜索到边界, F3不是跳点,斜向迈进一步到达F4
F4 向右发现节点M1 为 J2 的强迫邻居,则 F4为跳点,将 F4加入到 openList,将F4节点标记为蓝色,便于区分
由于 F4为 SF1发起的斜向搜索,所以是在 SF1斜向搜索的时候发现了跳点 F4,则不再向上搜索了,也不再继续斜向搜索,SF1斜向搜索停止
右上搜索结束

5.看上图
开始向S右下(1, -1) SG1 方向斜向搜索
SG1(1, -1)可以分解为 水平向右 (1, 0)和垂直向下(0, -1)
则SG1斜向搜索需要搜索 水平向右 (1, 0),垂直向下(0, -1)和斜向右下(1, -1)三个方向
G1 向右搜索到障碍物,向下搜索到边界, G1不是跳点,斜向迈进一步到达 G2
G2 向右搜索到障碍物, 向下搜索到边界, G2不是跳点,斜向迈进一步到达 G3
G3 向右发现节点J3 为 J1 的强迫邻居,则 G3 为跳点,将 G3加入到 openList,将G3节点标记为蓝色
由于G3为 SG1 发起的斜向搜索,所以是在 SG1斜向搜索的时候发现了跳点G3,则不再继续向下搜索了,也不在继续斜向搜索,SG1斜向搜索停止
右下搜索结束

6. 看上图
开始向S左下(-1, -1) SH1 方向斜向搜索
SH1(-1, -1)可以分解为 水平向左(-1, 0) 和 垂直向下(0, -1) 两个方向
则SH1斜向搜索需要搜搜 水平向左(-1, 0) ,垂直向下(0, -1)和斜向左下(-1, -1)三个方向
H1 向左搜索到障碍物,向下搜索到边界,H1不是跳点,斜向迈进一步到达 H2
H2 向左搜索到障碍物,向下搜索到边界,H2到达边界了结束
左下搜索结束
此时围绕 S节点的搜索结束,将S节点放入 closedList

7.看上图
取出 openList 中权值最小的节点此时openList ={G3, F4}, 且G3权值最小,则取出G3,将G3标记为绿色
G3的父方向时 S,则 SG3 方向为右下(1, -1)
SG3可以分解出水平向右 (1, 0),垂直向下 (0, -1) 两个方向
则SG3斜向搜索需要搜索 水平向右 (1, 0),垂直向下 (0, -1)和斜向右下(1, -1)三个方向

G3向右搜索发现节点J3是 J1 的强迫邻居,则J1是跳点,将节点J3加入到J1的强迫邻居列表中,将 J1添加到 openList,将 J1标记为蓝色
由于不是斜向搜索发现的跳点,则继续
G3向下搜索到边界,斜向迈进一步到达 G4
G4向右搜索到达边界,向下搜索到达边界,G4不是跳点,则斜向迈进一步到达G5
G5向右搜索到达边界,向下搜索到达边界,G5到达边界,则搜索结束。
将G3加入到 closedList 中

8看上图
取出openList 中权值最小的节点此时 openList ={F4, J1},F4权值最小,将F4取出,将F4标记为绿色
F4的父方向是S,则SF4方向为右上(1, 1)
SF4可以分解为 水平向右(1, 0)和垂直向上(0, 1)两个方向
则SF4斜向搜索需要搜索的方向为 水平向右(1, 0)、垂直向上(0, 1)和斜向右上(1, 1)三个方向

F4向右搜索发现 节点M1 是节点 J2的强迫邻居,则J2是跳点,将节点M1加入到J2的强迫邻居列表中,将 J2加入到 openList,并将 J2标记为蓝色
由于不是斜向搜索发现的跳点,则继续
F4向上搜索到达边界,斜向迈进一步到达F5
F5向右搜索到达边界,F5向上搜索到达边界,F5不是跳点,则斜向迈进一步到达F6
F6向右搜索发现节点O1是K1的强迫邻居,则F6是跳点,则将 F6加入到 openList,将F6标记为蓝色,
由于F6为 SF4 发起的斜向搜索,所以是在 SF4斜向搜索的时候发现了跳点F6,则不再继续向下搜索了,也不在继续斜向搜索,SF4斜向搜索停止
将F4加入到 closedList

9.看上图
取出openList 中权值最小的节点此时 openList={J1, J2,F6},节点 J1的权值最小,将 J1从openList取出,并标记为绿色
J1的父方向时 G3,则G3J1方向为向右(1, 0),
G3J1分解的水平方向(1, 0)和垂直反向(0,0),其中垂直方向(0,0)不满足垂直方向要求舍去
J1向右搜索到达边界

由于G3J1方向为水平方向,没有斜向,则不搜索斜向
但是J1有一个强迫邻居节点J3
则需要搜索斜向右上 J1J3=(1,1),发现节点P1是J3强迫邻居,则J3是跳点,将 P1加入到J3的强迫邻居中,将 J3加入到 openList并且标记为蓝色
将J3加入到 closedList
搜索结束

10看上图
从openList中取出权值最小的节点,此时 openList ={J3, F6, J2}, 节点F6权值最小,则取出F6,并将F6标记为绿色
F6父方向是 F4,则F4K6方向为斜向右上 (1, 1)
F4F6分解为水平向右(1, 0)和垂直向上(0, 1)两个方向
则F4F6斜向搜索需要搜索 水平向右(1, 0),垂直向上(0, 1)和斜向右上(1,1)三个方向
F6向右搜索发现节点O1为 K1 的强迫邻居,K1为跳点,将O1加入到K1的强迫邻居中,将 K1加入到openList,并将K1标记为蓝色
不是斜向搜索到的跳点,继续
F6向上搜索到达边界,斜向迈进一步到达F7
F7向右搜索到达障碍物,向上搜索到达边界,
将F6加入到 closedList
搜索结束

11看上图
从openList中取出权值最小的节点,此时 openList ={K1, J3, J2}, 节点K1权值最小,则取出K1,并将K1标记为绿色
K1父方向是 F6,则F6K1方向为水平向右(1, 0)
F6K1分解为水平向右(1, 0)和垂直(0, 0)两个方向,且垂直方向(0,0)不满足要求
K1向右搜索到边界

F6K1为水平向右,没有斜向,则不搜索斜向
但是 K1有一个强迫邻居O1,则搜索斜向右上 K1O1=(1,1)
K1O1分解为水平向右(1, 0)和垂直向上(0, 1)
O1向右搜索到边界,向上搜索到边界,O1不是跳点,则斜向迈进一步到达 O2
O2向右搜索到边界,向上搜索到边界,O2到达边界,
将K1加入到 closedList
搜索结束

12看上图
从openList中取出权值最小的节点,此时 openList ={ J2,J3}, 节点J2权值最小,则取出J2,并将J2标记为绿色
J2父方向是 F4,则F4J2方向为水平向右 (1, 0)
F4J2分解为水平向右(1, 0)和垂直(0, 0)两个方向,且垂直方向(0,0)不满足要求
J2向右搜索到边界

F4J2为水平向右,没有斜向,不需要斜向搜索
但是J2有一个强迫邻居M1,则想 J2M1斜向右下搜索
M1 向右搜索到达边界,向下搜索发现 J3,J3已经在 openList,更新J3的权值,返回
发现 R1为M1的强迫邻居,M1为跳点,将R1加入到 M1的强迫邻居,M1加入到openList,并将M1标记为蓝色
将J2加入到closedList
搜索结束


13看上图
从openList中取出权值最小的节点,此时 openList ={ J3,M1}, 节点J3权值最小,则取出J3,并将J3标记为绿色
J3父方向是 J1,则J1F3方向为斜向右上 (1, 1)
J1J3分解为水平向右(1, 0)和垂直(0, 1)两个方向
J3向右索索到边界,向上搜索到M1,M1已经在openList中,如果从J3到M1 的权值比 M1当前权值更小,则更新M1的权值,斜向迈进一步到达N1
N1向右搜索到边界,向上搜索到边界,斜向迈进一步到达N2
N2向右搜索到边界,向上搜索到边界,斜向迈进一步到达N3
。。。直到到达边界

J3还有一个强迫邻居P1,斜向左上J3P1=(-1,1)
J3P1 分解为水平向左(-1,0)和垂直向上(0, 1)
P1向左搜索到障碍物,向上搜索到障碍物,斜向迈进一步到达P2
P2向左搜索到 终点E,终点是跳点,则将 P2加入到openList中
将J3加入到closedList

到这里已经触摸到终点E了,接下来再将 P2取出来就能搜索到终点E 了,不再说明了,搜索成功结束

下面是一个Unity实现的搜索展示动画

刚开始加入到openList的节点显示蓝色小球,当从openList中取出来时显示绿色小球

此处是代码实现连接,Unity辅助展示,核心逻辑与引擎无关、与语言无关

下面是一个寻路搜索展示网页的搜索展示动画

网页链接

补充:
代码 JPSTool 判断强制邻居部分,的计算逻辑说明

判断水平、垂直方向(水平向右、水平向左、竖直向上、竖直向下)的强制邻居

CheckHVForceNeighbour

判断斜向(左上、左下、右上、右下)的强制邻居

CheckDiagonalForceNeighbour

先来看水平方向逻辑

先看前置接点P和当前节点X 处于横向水平关系时
从上图可看出从 PX水平方向X 的强制邻居有分别是 N1、N2
组成部分是:
(1)P、X、O1、N1
(2)P、X、O2、N2

已知:P、X 坐标
如何求得 O1、N1、O2、N2 的坐标?
P 指向 X 的方向 dir = (1, 0)
(1.1)公式1:
O1坐标 = X + (Abs(dir.Y) * 1, Abs(dir.X) * 1)
O1坐标 = X + (0, 1)

(1.2)公式2:
N1 坐标 = O1坐标 + dir
N1 坐标 = O1 坐标 + (1, 0)

(2.1)公式3:
O2 坐标 = X + (Abs(dir.Y) * -1, Abs(dir.X) * -1)
O2 坐标 = X + (0, -1)
(2.2)公式4:
N2 坐标 = O2 坐标 + dir
N2 坐标 = O2 坐标 + (1, 0)

同理水平向左、竖直向上、竖直向下 也都是使用 公式1、公式2、公式3、公式4
公式1公式3的区别在于
公式1 乘以 1 -> (Abs(dir.Y) * 1, Abs(dir.X) * 1)
公式3 乘以 -1 -> (Abs(dir.Y) * -1, Abs(dir.X) * -1)

公式2 和 公式4 相同

再来看斜向逻辑

先看前置接点P和当前节点X 处于斜向关系
从上图可看出从 PX斜向左上X 的强制邻居有分别是 N1、N2
组成部分是:
(1)P、X、O1、N1
(2)P、X、O2、N2

已知:P、X 坐标
如何求得 O1、N1、O2、N2 的坐标?
P 指向 X 的方向 dir = (-1, 1)
(1.1)公式1:
O1坐标 = X + (dir.X, 0)
O1坐标 = X + (-1, 0)

(1.2)公式2:
N1 坐标 = O1 坐标 + (dir.X, 0)
N1 坐标 = O1 坐标 + (-1, 0)

(2.1)公式3:
O2 坐标 = X + (0, dir.Y)
O2 坐标 = X + (0, 1)

(1.2)公式4:
N2 坐标 = O2 坐标 + (0, dir.Y)
N2 坐标 = O2 坐标 + (0, 1)

同理水平向左、竖直向上、竖直向下 也都是使用 公式1、公式2、公式3、公式4

如有错误之处请指出,感谢

JPS(jump point search)寻路算法相关推荐

  1. 「游戏」寻路算法之A Star算法原理及实现

    前言 自动寻路是在一些如MMORPG等类型游戏中常见的一种功能,其给了玩家良好的游戏体验,使得玩家在游戏过程中省去了大量游戏坐标点的记录以及长时间的键盘操作,不必记忆坐标,不必担心迷路,用最快捷的方法 ...

  2. 贪吃蛇AI算法中的A star寻路算法

    A*寻路算法 在之前的贪吃蛇游戏比赛里,计算蛇吃食物路径时要用到寻路算法,于是就去了解了一下,以下是我的算法演化过程. 1.简单寻路–按图索骥 我一开始想到的方法就是最简单的:目标在哪个方位就往哪个方 ...

  3. 最快速的寻路算法 Jump Point Search

    作者:runzhiwang,腾讯 TEG 后台开发工程师 本文介绍一种跳点搜索算法 JPS 以及其四个优化算法,其寻路速度最快可是 A*算法的 273 倍.文中的 JPS-Bit 和 JPS-BitP ...

  4. JPS寻路算法优化思路

    JPS寻路算法学习 A*算法 简介 A*算法的一些概念 算法流程 JPS 算法简介 JPS 算法的两条定义,三个规则 JPS 算法举例 JPS 五个优化算法 1.JPS-Bit:位运算优化 2.JPS ...

  5. SRPG游戏开发(二十三)第七章 寻路与地图对象 - 一 A*寻路算法(A* Search Algorithm)

    返回总目录 第七章 寻路与地图对象(Pathfinding and Map Object) 这一章主要进行寻路与地图对象的部分工作. 第七章 寻路与地图对象(Pathfinding and Map O ...

  6. A星寻路算法(A* Search Algorithm)

    你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...

  7. 游戏中常用的寻路算法(6):地图表示

    在本系列文档大部分内容中,我都假设A*用于某种网格上,其中的"节点"是一个个网格的位置,"边"是从某个网格位置出发的各个方向.然而,A*可用于任意图形,不仅仅是 ...

  8. [转]关于寻路算法的一些思考

    关于寻路算法的一些思考(1):A*算法介绍 物体的移动算法似乎显得很简单,然而寻路规划问题却十分复杂.考虑下面这个例子: 这个单位的初始位置在地图的下方,想要到达地图的顶部.如果物体所能侦测到的地方( ...

  9. 地图信息,障碍判断以及寻路算法(A星算法,B星算法和蚁群算法等)

    一.广度优先遍历和深度优先遍历 在学习寻路算法之前,我们先来了解一下广度优先遍历和深度优先遍历. 什么是广度优先遍历? 广度优先遍历(breadth first search)是一个万能的算法. 广度 ...

最新文章

  1. 藏在XP中的一个可以完整清除垃圾文件
  2. SAP 外币金额 汇率 转换
  3. ajax无刷新评论的思路,ajax学习——ajax版无刷新评论(数据库)
  4. mysql8 授权远程登录_MySQL8 远程授权访问
  5. 编写Java程序 堆栈的接口_java - 错误:调用实现接口的通用方法时,java.lang.AbstractMethodError - 堆栈内存溢出...
  6. Oracle导入TYPE对象报错ORA-02304
  7. JS正则验证邮箱的格式
  8. 输入URL经历的过程
  9. contiki makefile框架分析 contiki学习之一
  10. python 数据分析--2016美国竞选辩论可视化
  11. 循环神经网络 递归神经网络_递归神经网络-第3部分
  12. 利用哈希表设计快速电话号码查询系统
  13. Flash加速功能实现
  14. java 图片md5码_java 对图片进行MD5算法
  15. linux配额管理命令,Linux管理员配额管理
  16. 网卡和网卡的驱动程序
  17. 如何配置Binlog
  18. 升级iOS 16后续航时间变短了,如何提升续航?
  19. HDU 威威猫系列故事——篮球梦
  20. 显示器U2518怎么连服务器,【戴尔 U2518D 显示器使用感受】尺寸|分辨率|边框|底座|颜色_摘要频道_什么值得买...

热门文章

  1. 计算机科学与技术用AMD,为何选择 AMD 处理器 | AMD
  2. QQ邮箱中的WebQQ
  3. 求职者说:成功应聘华为后的总结
  4. 关于stm32f10xRB系列的PB5和PB12外设冲突问题
  5. vue 跳转打开新页面
  6. ctfshow单身杯(dsb)个人wp
  7. LaTeX中表格默认在页面中置顶怎么取消?
  8. matlab两点之间的所有路径,引用 在图中搜索两点间的所有路径matlab编程
  9. NODE.JS语言的短信接口好对接吗
  10. 血氧饱和度测量,pcb加原理图,