战术RPG的A *算法?


15

我在用C ++编写一个非常糟糕的战术RPG搞乱了。到目前为止,我已经有了一个2D瓦片贴图,并且刚刚使Wikipedia中基于伪代码的A *算法起作用。

但是,真正的战术RPG不仅会在平坦的飞机上找到最佳路径,然后再向那里移动。它们通常具有有限的移动范围,并且必须向上或向下爬。如果您曾经玩过《最终幻想战术》,则这些内容会受到“移动”和“跳跃”统计数据的影响。这是我迷路的地方。如何更改A *算法,以便找到通往目标的最佳路径,但是路径只有这么多图块?我应该如何考虑身高差异并考虑统计数据?我如何实现跨越差距?

如果有帮助,现在我的地图将由Tile对象的Vector表示。每个图块都有指向北,南,东和西图块的指针,如果那里不存在图块,例如沿着地图的边缘或将图块设置为不可通过,则将它们设置为nullptr。


5
我不知道为什么移动范围是个问题。找到最短的路径,然后,沿着该路径移动“速度”平方。
Mooing Duck

Answers:


33

攀爬和缺口只是不同的成本函数。对于可以跳过间隙的单元,其正常成本为(?),对于非跳转单元,其成本为任意高。攀爬会产生额外的费用,困难的地形也是如此。A*算法能够很好地处理成本函数,因此,如果您的实现尚未执行此操作,则可以通过Google搜索如何使用成本函数实现A *。

话虽如此,但我认为A *对于战术RPG而言并不是特别好的方法。或更准确地说,这不是一个完整的故事。您不希望您的单位盲目地向他们的目标失误,而是希望他们在进行最终目标并试图向侧面攻击对手等过程中,利用掩护,制高点或其他优势来定位自己。因此,每一步的终点战术价值非常重要,而不仅仅是目标的接近程度。这不仅需要寻路,还需要更深入的问题解决。


10
关于“战术定位”的要点很好,但是这些决定可能会在高于基本寻路的水平上应用。另一方面,将成本应用到由某种战术分析器生成的寻路算法中的节点上可能是一个不错的选择。例如,如果敌人的视线跨过地形,则使该地形上的节点损失很高。
DrMcCleod

1
@DrMcCleod:确实,这就是我的意思,“或者更准确地说,这不是一个完整的故事”。您当然可以使用A *或其他算法来进行部分处理,但是我认为我会避免使用诸如通过移动成本来避免受监视节点之类的方法,因为跨区域移动可能会受到攻击的地形会得到更好的处理。风险/回报计算,IMO。
杰克·艾德利

13

当您需要一个单元所有可能的移动选项时,请使用Dijkstra的Algorithm

A *和Dijkstra之间的区别在于,Dijkstra为您提供了在给定成本下所有可能的最短路线,如果没有一条到达您的目的地,它将使成本增加一并继续。另一方面,A *更倾向于先计算那些有机会到达目的地的路线。

因此,当您只想从A点到B点的最短路径时,A *是一个不错的选择。但是,如果您需要所有可能的移动选项以及每个选项的最短路径,那么Dijkstra正是您想要的。

您需要做的就是在没有特定目标节点的情况下运行Dijksta算法,但是最大成本不得超过(设备的移动范围)。当旅行到一个节点将超过最大成本时,请勿访问它。当算法由于缺少未访问的边缘而终止时,访问集中的每个节点都是可能的目的地,并且节点的先前节点标记形成一个链表,该链表表示返回到初始节点的路径。

关于跳跃:在A *和Dijkstra中,这些都可以表示为另一个优势。它们的成本与遍历常规边缘的成本相同或不同。您还可以将“ jump_height”参数传递给算法,该参数告诉算法忽略超过给定高度的跳边。


9
在这里值得一提的A*是,这实际上只是Dijkstra的概括,因此,如果您理解其中一个,那么理解另一个就不难了。
立方

8
确实,如果您的启发式算法在A *算法中仅返回0,那么恭喜您!您刚刚编写了Dijkstra的算法。
Yann

9
“ Dijkstra以给定的成本为您提供了所有可能的最短路线,如果没有一条到达您的目的地,它将使成本增加一并继续。” -这既不是它的工作方式也不是它的输出。实际上,这只是广度优先搜索到加权图的概括。它找到一条最短的路径。A *只是它的概括,因为当您有距离启发式可用时。
BlueRaja-Danny Pflughoeft

1
不知道为什么会这样。从务实的角度来看,Dijkstra已过时。出于教育和历史原因,在CS中进行了授课。即使是A *,也无法进行认真的工作。Google Maps当然不使用它。您现在正在看的是ArcGraph变体。
MSalters

2
@MSalters Dijkstra和A *是用于简单问题(例如战术RPG)的完美算法。有效移动范围(平铺)非常狭窄,并且在所述图块上移动的方式非常有限(正交,有时是对角线),通常最大路径很短:SQRT(ArenaWidth²*ArenaHeight²)。从计算上看,在现代机器上,由于值可能很小,因此差异可以忽略不计,那么,当简单的实现足以满足此处概述的目的时,为什么还要为更复杂的实现而烦恼呢?
Valthek '19

2

其他答案都有一些很好的信息,因此请务必阅读它们。

但是,要回答您的问题:根据链接到的伪代码,您具有某种功能 heuristic_cost_estimate来计算从tileA到tileB的成本(假设它们是相邻的)。您不必对其进行平整(1)调整,而必须对其进行调整以包括平铺统计数据和单位统计数据,以及可能包括边缘统计数据。

例如:

if (edge == JUMP && !unit.canJump()) 
    return INF;
if (tile.Type == Forest && unit.moveType == HORSE) 
    return 2;
//Other cases here
//-----
else 
    return 1;

这将为您提供路径。然后,您只需在消耗移动点的同时沿其路径移动单元,并在其余点<edgeCost时停止它们。请注意,如果最终得到的剩余点数= 1,这可能不是最佳选择,但对于练习RPG来说已经足够了。实际上,正如Jack Aidley指出的那样,您需要更多战术!

挑战:
如果您想提高自己的水平,您可能想按照建议的方式使用Djikstras查找X距离内的所有空间,然后您要根据与目标的接近程度,防御力来评估该列表中的每个空间以获得“最佳”位置力量,是否可以从该位置受到攻击等。根据该信息,您将选择一个磁贴,然后按照您刚才使用Djikstras计算出的路径移动到该位置。


1

攀登和缝隙相当琐碎,因为它们只会改变成本。寻路(以及大多数战术AI)就是要汇总所有待访问节点的成本并将其最小化。不可逾越的悬崖将带来无限(非常高)的成本,斜坡的成本将比正常高,等等。

但是,这会找到不是最佳解决方案的全局最优路径,因为真正的对手通常不会找到最优路径。这是高度不现实的,有时甚至对玩家来说是显而易见的,并且很烦人(尤其是当AI本身也无可挑剔时,因为它也选择了最佳状态)。

故意进行良好的模拟找不到最佳路径。更好的算法可能是进行分层寻路-如果不做其他事情,通过在地图上画一条直线,并获取4-5个航点,然后从一个航点到下一个航点进行寻路,仅考虑到目前为止的节点权重已知,并将所有其他节点的权重设置为“无差异”。另外,您可以先在较粗的网格上运行A *,然后从一个大节点到另一个大节点进行寻路(但我猜想在地图上画一条线也很好)。

这要现实得多(并且由于图形小得多,因此还消耗了一部分处理能力)。是的,这可能意味着一个单位向悬崖移动只能发现它无法穿越。很好,它也发生在真正的对手身上。下次,它将不再发生(因为现在已经知道了无限成本)。


1
请注意,“简单的分层寻路”可能看起来很愚蠢。您会发现部队直奔山脊,却发现那里的道路被挡住了。然后,他们穿过山路到达下一个航点,然后从那里到达目的地-即使该后一个航点对他们而言偏离路线。预处理将确定山峰在前面并经过那里。但是,即使您不这样做,一旦您偏离计划的路线太远,也应该重新计划其余的路线。
MSalters

@MSalters:即使在第一次尝试之后,使用“画一条线”方法也可能发生这种情况。使用粗网格分层方法不太可能发生多次(例如,采用其中的节点的平均值,中位数,甚至最大成本值)。这几乎就是人类对手的游戏方式-避开您知道或可以从远处看到的巨大障碍物(如山链),否则要规划一条粗糙的,通常是笔直的路线,然后继续前进。除非您知道那里有一座山,否则您会径直走向它。
戴蒙
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.