A*寻路算法入门(一)

时间:2021-11-02 04:24:27

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 
如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;)


免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流之用,请勿进行商业用途。同时,转载时不要移除本申明。如产生任何纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作!

该篇博客由iOS课程团队的Johann Fradj发布,他现在是一个全职开发ios的开发者.他是Hot Apps Factory(其是App Cooker的创造者)的共同创建者.

A*寻路算法入门(一)

学习A*寻路算法是如何实现的!

你是否在你的游戏中想要怪物或者玩家移动到特定的地点,同时避免墙和障碍物?

如果是,读一读这篇课程,它将向你展示你能用A*寻路算法做些什么!

在网上已经有一些关于A*寻路算法的文章,不过几乎所有的都是面向已经知道基础的有经验的开发者.

本课程将从基本开始将你渐渐带入门径.我们将一步步讨论A*算法是如何工作的,并且包括了大量的图片和例子去示意整个过程.

不管你使用神马编程语言或平台,你都会发现本课程解释的算法对于任何语言来说都是有帮助的.稍后,我们将在课程之后展示一个用Cocos2D实现的iPhone game的例子.

现在泡上一杯香浓可口的咖啡再配上一些美味的零食,让我们开始旅程吧! :]



一只寻路的猫咪(本猫猪也是路痴,猫猪注.)

让我们想象我们有一个游戏,游戏中一只猫咪想要找到得到骨头的路径.

“为毛一只在世界上的猫咪想要一根骨头呢?!”你可能会这样想.好吧,在我们的游戏中,这是一只狡猾的猫咪,它想将骨头交给狗狗们,所以狗狗们不会咬它啦! :]

所以想象下图中的猫咪想要找到到达骨头的最短路径:

A*寻路算法入门(一)

不幸的是,这只猫咪不能直接从当前位置到达骨头,因为途中有坚固的墙壁,因为它在游戏中不是幽灵猫咪!

而且这只猫咪非常的懒,它总是像找到最短的路径,以便还有劲回家去找它的母猫缠绵 ;-)

但是我们如何写一个算法来使猫咪得偿所愿呢?救世主A*算法来啦!

简化搜索区域

在寻路中的第一步是使得整个搜索区域简化的可被简单操作.

这将取决于具体的游戏.举个栗子,我们可以按像素来划分搜索区域,但是它对于我们基于瓦块地图的游戏来说的粒度太高(而且毫无必要).

作为替代,我们将使用瓦块(一个正方形)作为寻路算法的基本单元.用其他形状也是可以的(比如三角形或者六边形),但是正方形在这里对于我们的需求来说最适合并且也最简单.


像那样划分,我们的搜索区域可以简单的描述成地图瓦片的2维数组.所以如果关卡的地图是25*25块瓦片,则我们的搜索区域将为一个包括625个正方形的数组.如果我们将地图按像素划分,则搜索区域将是一个包含640,000个正方形的数组(每个瓦片是32*32个像素)!

所以让我们根据屏幕截图开始将搜索区域按瓦片划分为数组表示(在我们这个简单的例子中,地图的瓦片尺寸为 7x6 = 42块)”

A*寻路算法入门(一)

开放和闭合列表

现在我们已经创建了一个简单的搜索区域,让我们讨论一下A*算法是如何工作的.

除了懒以外,我们的猫咪的记性也不太好,所以它需要2张表:

  1. 一张记录所有在寻找最短路径中被考虑到的正方形(称之为开放列表 open list)
  2. 另一张记录那些不需要再次考虑的正方形(称之为闭合列表 closed list)

猫咪从添加自己的当前位置(我们将这个开始位置称之为点A)到闭合列表中开始.然后,它添加所有当前位置相邻的可达瓦片到开放列表中.

这里有一个在空白区域如何添加例子的示意图(绿色表示在开放列表中):

A*寻路算法入门(一)

现在这只猫咪需要确定这些选择中的哪一个是最短路径,但是如何选择呢?

在A*寻路算法中,这通过给每一个正方形一个分值来确定,这称之为路径评分.让我们在下一篇中看一下它是如何工作的!




路径评分

我们将给每一个正方形一个分值 G + H :

  • G是从开始点A到当前方块的移动花费.所以对于一个开始A点的邻居方块来说,值为1,但是离开开始点越远它的值会越大.
  • H是当前方块到目的方块(我们称该点为有骨头的点B!)的估计移动花费,这通常称之为启发式的算法,因为我们并不真的清楚花费是多少 — 它仅是一个估计值.

你可能会奇怪”移动花费”的意思.在这个游戏中它十分的简单 — 就是(途经)方块的数量.

不管如何,记住你可以将我们的游戏变得不一样.比如说:

  • 如果你允许对角线移动,你可能会将对角线移动的花费设置的高一点.
  • 如果你有不同的地形,你可能将通过它们的花费设置的不一样 — 举个栗子:沼泽,水或者是猫女的海报 ;-)

这就是大体上的想法 — 现在我们进一步研究如何去计算G和H的值.

更多的关于G

回忆一下,G是从开始点A到当前方块的移动花费(在这个游戏中就是经过方块的数量).

为了计算G,我们需要将其父方块(该方块表示我们从哪来)的G取出然后加1.因此,每个方块的G值将表示从点A到自身方块一般路径总的花费.

举个栗子,以下图片展示了到达2个不同骨头的2个不同路径,每个方块的G值都列在方块中:

A*寻路算法入门(一)

更多的关于H

回忆以下,H是当前方块到目的地估计的移动花费(在我们的游戏中也就是途经方块的数量).

估计移动花费越接近于实际的花费,则最终路径将会更准确.如果估计发生了偏差,可能产生的路径将不是最短的(但可能还是会很接近).这个主题有点复杂,所以在该系列课程中我们不会详述,但是我会在文章结尾提供一个链接文章,它解释的非常好.

简单来说,我们将使用”曼哈顿距离方法”(同样称之为”曼哈顿长度”或者是”街区距离”),它仅仅计算到达B点水平和垂直的方块数量,但并不考虑任何障碍物或不同的地形.

举个栗子,这里有一张图展示了使用”街区距离”去估计从不同的起始位置到目的位置的H值(显示在空白处):

A*寻路算法入门(一)