基于三角网格的寻路算法(一)—— 综述

这篇文章是2010年我在人人游戏实习时写下的。当时是使用AS3作为开发语言,所以实现也是用的AS3。正文如下:

不久前学习了A*寻路算法,并用AS3进行了实现,但是总觉得A*算法不容易找出一个径直抵达的路径,总是需要拐弯,尽管没有任何障碍。上上周末参加了RIA天地会北京行的大会,介绍了一种比较先进的算法,可以基本保证找到最近的路径,也就是直线抵达,这是一种基于三角网格的寻路算法。

这种寻路算法需要将地图进行预处理,即将由地图边界拐点和障碍物外围拐点所形成的离散点的集合转换成为一个全部由三角型组成的网络,这种处理叫做“三角剖分”,其中最著名的应该就是Delaunay三角剖分了。Delaunay三角剖分示例如图1-1所示:

图1-1 Delaunay三角剖分

将离散点组织成为三角网络以后,去掉那些无法到达的三角形,即障碍物内部的三角形,剩下的就是覆盖了所有可到达地点的三角网络,如图1-2所示:



图1-2 擦除三角网络中不可到达的三角形

图1-2模拟了某些游戏中的场景,假设场景是一个矩形区域,但是上方和左下方的一小部分被建筑物占据因此无法到达,中间是一个喷泉因此也无法到达,于是左边图经过删除不可到达三角形后就形成了右边的图。

接下来假设我们的人物在点A处,我们用鼠标点击了B点,这时我们希望将人物从点A移动到点B,于是我们首先用A*算法查找一条最近的网格路径,在A*寻路过程中人物在三角形中的位置我们默认是三角形的重心,即三角形三边中线的交点,因为这一点必然在三角形内部,且基本为三角形比较中间的位置。于是我们找到了如图1-3所示的一条三角形路径:


图1-3 使用A*算法找到的路径以及所经过的三角网格

其中黑色线条表示A*寻径算法计算出来的初始路径,首先从A点出发走到A点所在三角形的重心,然后依次移动到下一个三角形的重心,最后移动到B点。不难发现这种移动远没有达到我们预期的结果,所以最后还需要一步平滑的过程。如图1-4所示的过程:

图1-4 平滑处理过程

图1-4表示了最后一步平滑处理的过程。黑色线条中间夹着的范围类似于动物和人的“视野”;蓝色线条表示一次“远望”,可以看到针对左边视野边界的第一次远望的目标点在原视野范围内,因此不做移动,只将左边视野范围调整到这次远望的目标点处;接下来的两次远望同第一次一样在视野范围内,因此只调整视野范围而不做移动;接着再针对右边视野进行一次远望,这次发现目标点不在原视野范围内了,因此需要将人物从A点移动到C点才可以看到该点。黄线表示人物移动的路线。然后再从C点确定新的视野范围,以此类推,可到达B点的路线用黄颜色的折线连接而成,最后通过回溯找到这条路径完整的过程,这样就完成了我们的寻路,可以看到使用基于网格的寻路算法找到的路径基本上就是最近的路线了。

实际上三角剖分为我们A*寻路和最后的平滑处理过程提供了很大的帮助,尤其是平滑过程,使用三角形来处理“视野”和“远望”是一个很好的做法,因为三角形只有三个角,因而可以很容易找到下一次远望的目标点——只需要将某一边的视野沿着外侧的边移动到下一个三角形唯一没有被使用过的点上即可,至于到底移动哪一边视野,需要保证移动后两边视野的落脚点之间有边连接。

这种寻路算法相对于A*有很明显的优势:

1. 能够找出真正最近的路径;

2. Delaunay三角剖分的结果比按照矩形或者六边形等固定形状进行拆分的结果更能够描述复杂的地形;

3. Delaunay三角剖分出来的网格数量比按照固定形状拆分出来的格子数量少,减少了寻路开销。

当然缺点也是很明显的:

1. 三角网格寻路增加了地图的复杂度,不利于策划进行配置,而如果是固定形状拆分的话,策划可以很轻松地按照某个坐标值进行配置,表示该块范围是草地或是河流;

2. 三角网格寻路很难对地形有变化的地图进行剖分,因为如果某个范围内是河流,而士兵在河流中行进的速度比平原中要慢一半的话,三角网格中的A*寻路就要比固定形状的A*寻路要困难得多,它不容易估计从当前三角形到达下一个三角形所要消耗的代价值。

因此我对基于三角网格的寻路算法和固定形状的A*算法做了一个应用范围的假设,如果不对欢迎大家指摘和批评:

1. 战棋类游戏使用固定形状的A*寻路;

2. 行进途中根据地形而影响角色行进状况的游戏使用固定形状的A*寻路;

地形对角色无影响且没有固定约束建筑物或障碍物形状的游戏,比如多数MMORPG游戏,都可以采用基于三角网格的寻路算法。

编辑于 2017-01-20