本文由 伯乐在线 - 唯一小时 翻译,黄利民 校稿。未经许可,禁止转载!
英文出处:theory.stanford.edu。欢迎加入翻译组。
本系列:
- 关于寻路算法的一些思考(1):A* 算法介绍
- 关于寻路算法的一些思考(2):Heuristics 函数
- 关于寻路算法的一些思考(3):A* 算法的实现
- 关于寻路算法的一些思考(4):A* 算法的变体
- 关于寻路算法的一些思考(5):处理移动中的障碍物
- 关于寻路算法的一些思考(6):预先计算好的路径的所用空间
- 关于寻路算法的一些思考(7):地图表示
- 关于寻路算法的一些思考(8):长期和短期目标
- 关于寻路算法的一些思考(9):寻路者的移动成本
- 关于寻路算法的一些思考(10):最短路径的用户体验
- 关于寻路算法的一些思考(11):寻路算法的其他应用
- 关于寻路算法的一些思考(12):AI 技术
我已经集中讲过了从一个地方到另一个地方寻找路径的任务。然而,一个与之同等重要的问题是:一旦我有一个路径,我该怎样沿着它移动?最明显的答案是从一个位置到另一个的位置的直线移动。然而,你可能想在曲线上移动,或者多次的移动。你可能想把位置偏离成为低优先级的目标。一个更高层次的问题是:你要去哪里?除非你先回答的是高层次的问题,路径规划不是很有用。当然,目标设定的一个形式就是让用户点击目的地。不过,你可能已经自动执行了任务——探索,间谍活动,攻击和建设都是常见的方式。
单元移动
我已经集中讲解了在寻路问题,它减少了从一个位置移动到另一个位置中的问题,也减少了从一个空间到相邻空间的许多小问题。
你可以从一个位置到另一个位置的直线上移动,但有很多可选方案。考虑一下这幅图上的四个移动路径:
红色路径是标准方法:从一个正方形的中心移动到另一个正方形的中心移动。绿色路径比较好些:代替了在瓷砖的中心,而在瓷砖边沿之间的直线上移动。你也可以尝试在瓷砖的对角的连线上移动。蓝色的路径使用样条曲线,深蓝色的是低阶样条曲线,浅蓝色是高阶样条曲线(这需要花更长时间来计算)。
对角线和瓷砖边沿之间的连线是最短的解决方案。但是,曲线能使你的单元格看起来少了些机械化,多了些“活力”。这是一个低级的把戏,但不是最好的。
如果您的单位不能轻易转向,你可能在绘制运动路径时,要考虑到这一点。克雷格·雷诺兹有一个关于转向的网页,其中有一页是关于转向和用Java小程序来演示各种各样的行为。如果你有不止一个的单元沿着路径移动时,你可能还需要研究群集。克雷格建议,你应该将路径当做一个指导路线,它反应出了你偏离了条件要求,而不是作为你的单元必须要访问的位置清单。
如果你正在使用网格寻路,你的单位是不受约束的网格,这和移动成本是一致的, 当两点没有障碍物的时候,你可能希望把路径伸直,然后在两点之间的直线上运动就可以遥遥领先。如果你使用的导航网格,去看看漏斗算法。
行为标志或堆栈
你的单位也许有一个以上的目标。例如,你可能有一个像“间谍活动”的总体目标,但也可能是一个更直接的目标,像“去敌人司令部”。此外,还有可能是暂时的目标,如“避开巡逻卫士”。下面是一些目标的说明:
- 停止:留在当前位置
- 停留:停留在一个区域
- 逃跑:移动到安全区域
- 撤退:移动到安全区域,同时击退敌方单位
- 探索:查找并了解了这一点信息是已知的领域
- 游荡:漫无目的的四处移动
- 搜索:寻找一个特定的对象
- 间谍:靠近一个对象或单位来更多地了解它,而不被发现
- 巡逻:反复走过某个区域,以确保没有敌方单位通过它
- 保卫:停留在一些对象或单位附近,使敌方单位离开
- 警卫:入口附近保持在一定区域,以保持敌军单位出
- 攻击:移动到一些对象或单位,以捕获或消灭它
- 环绕:与其他单位一起,尽量包围一个敌方单位或对象
- 回避:从某些对象或单元移开 避免:与任何其他单位烤翅距离
- 跟随:保持近一些单位,因为它到处移动
- 群组:寻求和形成群组单位
- 工作:执行一些任务,如采矿,耕种,或搜集
对于每一个单位,你可以用一个标志来表明该行为是执行。用多个层次来保持一个行为堆栈。该堆栈的顶部是最直接的目标,堆栈的底部将是总体目标。当你需要做一些新的东西,但后来想回去你过去正在做的东西,那就压入栈中一个新的行为。如果你需要做一些新的东西,但不想再回到老的行为,那就清除栈。一旦你的完成了某些目标,把它从栈中弹出,并开始执行堆栈中的下一个行为。
等待移动
运动算法会碰上那些曾被认为不会出现在寻路过程中的障碍,这是不可避免的。一个容易实施的技术是基于其他障碍物会首先移动的假设。当障碍物是一个友好的单位时,这是特别有用的。当一个障碍挡住了去路,并且它只是等待一段时间后才移动。如果那段时间之后它还是没有移动,就要重新计算它周围或到目的地的路径。如果提前检测障碍物,你的单位只需简单地走慢一点来给其他单位更多时间离开挡你的道路。
两个单元会互相碰撞,并且每个将等待另一个继续行进,这种情况是非常有可能的。在这种情况下,优先级方案可以派上用场:分配给每个单元一个唯一的编号,然后使编号较低的单元等待更高编号的单元。如果两者都在等待,这将迫使其中一个单元继续前行。当提前检测到障碍物,编号较低的单元应该到达碰撞的预期点之前减速。
协调移动
当单位试图要穿越一条狭窄的通道时,上面所描述的技术将不起作用。如果一个单位静止不动,而其他单位试图绕过去,通道不能同时使用这两个单位。一个单位将阻塞住它,而另一个将花费一段漫长的道路。
第二个单元与第一个单元进行通信,并要求其退回来,这种情况应该是可能的。一旦通道畅通无阻,第二单元就可以穿过,然后第一单元就可以通过。这可能是复杂的实现,除非你能事先能确定这些通道。对于随机生成的地图,通道在哪里和在多远的地方第一个单位需要退回来,这将是非常难以确定的。