自动寻路(一)

最近找工作不顺,写了个demo,支持动态添加障碍物的自动寻路,大概就是这个样子


是不是如德芙般丝滑(哈哈

这个是基于A*算法实现的网格寻路(A*大家到知道吧,不知道的看下这个把,这个大佬讲的挺清楚的)

传统的A*寻路是这个样子的,这里推荐大家一个网站,能帮大家深入理解自动寻路:PathFinding.js

图1

如图1,可以看出传统A*是有局限性的:得到的路线太过生硬,而且也不是最优的路线

所以呢,我们就需要在原有的A*上面进行改进,怎么改进呢?原有的A*是遍布全图的格子,其实我们可以把它们看作是点(格子的中心),每个点的移动选择只有周围的点,以至于要想从A点移动到C点,只能先移动到B点,再一格一格往下移直到移动到C点,这不符合正常思维呀,在现实中我们想要从一个点走到另一个点,如果两点没有障碍物,那么肯定就径直走过去了,这样才是距离最短的。所以呢,如果我们在游戏中想要从一个点移动到另一个点,直接判断两者之间有没有障碍物,没有障碍物就直线移动过去。既然这样,图中的好多点就不需要了。可如果我们遇到障碍物该怎么办呢?我们只需要把点加在障碍物周围就可以了。

再来一张图

图2

如图2,我们要想从红点移动到蓝点,一眼就可以看出最短路径(红点→A点→B点→蓝点)

但是思路是什么呢,我们先回忆下A*,A*中的每个点是和周围的点有联系的,但我们图中的点是没有联系的,那我们就给它们加上联系,从红点可以直接到达AC点,我们给红点添加一个表,把AC两点记录到表中,从A点可以直接到达BC红三点,那么我们就把BC红三点加入到A的表中......按照这个规律,把图中6个点的联系都搞清楚(只要两点之间没有障碍物,那我们就给他们添加上联系)。

联系搞好时候我们再回忆A*,A*中判断取点是通过该点的g+h

g:从初始点到该点的实际距离

h:是从该点到终点的最佳路径的估计距离(说白了也就是该点和终点的直线距离)

我们先创建一个缓存表,用来存放可以选择的点,从红点出发,将红点设置为不可被加入缓存表,再将红点的表数据加入到缓存表中,然后从缓存表中选择一个g+h值最小的点,可以算出是A点,然后将A点设置为不可被加入缓存表,把红点设为A点的上一个点(即A.pre = 红点),然后再把A点的表数据加入到缓存表中......就按照这个过程一直循环下去,直到走到蓝点。最后得出的路径就是(蓝点→蓝点.pre→蓝点.pre.pre→......)

将代码装换成文字是一件痛苦的事情,不知道我有没有写明白,写的乱七八糟的(捂脸

其实上面的思路就是A*的实现过程,没有看明白的可以看上面的链接大佬讲的A*

接下来我们把上面的图转换成网格

图3

从图3可以看出,网格记录的就是障碍物的点的联系(两点直接没有障碍物就看做是有联系),因为起点和终点变化性大,所以不把它们加入到网格中,而是在游戏运行时动态设置它们的联系。来一张游戏中的网格效果图:

图4

就这样,点之间的联系就画好了,哈哈,还不错吧,然后我们通过这些点的联系,使用A*算法,就可以实现寻路啦!

可是呢,总感觉这线也太多了吧,才3个障碍物,16个点,就需要画这么多的线

......

感觉有的线好像并不需要啊,再来一张图:

图5

我们仔细看图5就会发现,A点虽然能直接到达F点,但是也不需要添加联系,因为不管我们如何设置起点和终点,得到的最短路径中都不会包含路径AF(除非起点和终点就是AF点),所以AF路径存在的意义也就没有了,它们也就不需要联系了,不仅如此,CD、CF、AD、AE、BE、BF这几个路径也统统不需要。

大家可以想想在程序中如何判断。

我想到方法是把这个路径延长拉伸一点,看它会不会和障碍物发生碰撞,如果发生碰撞就不需要该路径了(我觉得这个方法不太好,但暂时还没想出更合适的方法)

这样我们的图4就变成图6了,这下就干净多了

图6

好了,先写这么多,等这几天忙完有时间了,把支持动态添加障碍物写下

有什么问题欢迎在文章下评论或者私聊我

初次写技术博客,写的有点乱,欢迎大家指出我的不足,共同进步!

猜你喜欢

转载自blog.csdn.net/w_whenhao/article/details/80084930