塔防游戏的动态路径算法


16

我正在做塔防,我需要一个好的路径算法。

我曾经考虑过Dijkstra,但我需要一个可以动态发展的人。删除或添加一条边而无需完全重新计算时,它必须能够自我更新。

如果有帮助,我正在C#中进行编码。

Answers:


8

通常,您将要使用A *,除非您正在寻找重要不同的东西。


如果我对A *不太熟悉,该如何解决动态变化的环境?重新计算每一帧?发生碰撞时?
贾斯汀·L.2010年

1
通常,您会在像这样的简单游戏中重新确定每个帧的路径。地图网格可能会非常小,最多只能有数百个代理。如果它最终成为一个巨大的性能问题,那么您可以稍后通过不重建树(除非需要时)来优化它。
coderanger 2010年

6
如果反应迟钝,我的建议是:不要计算每个生物的路径。他们都有可能走同一条路。我只重新计算新塔的位置,并且塔在当前路径中。即使这样,也只能对方块正方形之前路径上的点处的怪物进行重新计算,而不对经过它的小生物进行重新计算,因此不在乎。然后,为了使寻路更短,您可以限制它以找到被遮挡的正方形之后的正方形,因为您已经知道了从那里开始的路径。
seanmonstar

4
实际上,“暴民”是“移动对象”的行业用语(和MMO / MUD播放器)。

3
无论如何,它是长期存在的,可以追溯到MUD1,并且足够标准以使其出现在许多出版物中。zh.wikipedia.org/wiki/Mob_%28computer_gaming%29

19

我需要解决一个类似的问题:在一个大型迷宫状的网格上寻找路径,不断变化的“成本”和障碍。

问题是,在塔防游戏中,需要为其求解路径的实体数通常比图中的节点数大得多。A * 不是最合适的算法,因为每次更改时您都需要重新解决它。好吧,如果您只需要找到一条路径,那是合适的,但是在我的情况下,我需要能够处理可能出现在不同位置且每个实体都有自己路径的实体。

弗洛伊德-沃肖尔算法是更为合适的,但对于我来说,我写了一个自定义算法,每当一个节点发生变化时,重新计算成本,从所有邻居节点,然后如果邻居已经改变了它被调用递归地对待他们。

因此,在游戏开始时,我只是在所有“目标”节点上启动了该算法。然后,每当一个节点发生更改(例如,变得不可通过)时,我都会在该节点上启动它,并将更改传播到将受影响的所有节点,然后停止。因此,无需进行全局重新计算,并且该算法完全独立于需要寻路的实体数量。

我的算法基本上类似于(伪代码):

update_node method in Node class:
    $old <- $my_score
    find $neighbor node among all neighbors such that
        $neighbor.score + distance_to($neighbor) is minimal
    $my_score <- $neighbor.score + distance_to($neighbor)
    $next_node <- $neighbor
    if ($my_score != $old)
        for each $neighbor
            $neighbor.update_node()

初始分数取决于节点是目标还是某种障碍。


1
随着CPU负载的变化,也很容易在帧上动态扩展它。
tenpn

+1表示A *不是正确的算法。
Ricket 2010年

5

由于我在游戏中拥有的实体数量,我在TD上使用的路由算法比正常的A *路径落后。我没有从目标路由到坏人,而是从目标路由到了板上的每个空白方块。

这并不需要很长时间,您只需不断迭代电路板,直到找到您的“成本”,并且它为被阻塞的路由提供了很好的反馈(如果您正在执行这些操作)。与A *相比,使用Floyd算法是快速且缓存友好的,因为它不进行依赖数据的查找,它只是在流中加载数据并对其进行操作。

首先将您的面板设置为无限成本,然后将目标平方设置为零成本,然后在面板上进行迭代以检查相邻单元的成本是否小于当前成本加上差旅成本。旅行费用是您进行启发式分析的地方(在我的情况下,对角旅行的成本是无限的,但是穿过塔楼的成本很高,因此允许他们穿过塔楼进餐,但除非没有选择)

一旦获得了成本网格,就可以通过测试单元上最陡峭的成本梯度来快速构建一个“流”网格。这对于大量的坏人确实非常有效,因为他们中的任何一个都不必寻找路径,他们只是遵循虚拟路标。

另一个好处是,通过这种方式,您只需在每次调整障碍物时(或在我的游戏中,当小兵吞噬其中一个塔楼时)就运行此任务。并非每次都有小兵/暴民进入该领域(每秒成千上万的暴民和数十个暴民会令人头疼)。


4

寻路速度很快,并且在某种正常的塔防游戏大小的情况下,只要情况发生变化,您就可以毫无困难地运行完整的A *或Dijkstra传球。一毫秒之内,我们正在谈论一个完整的刷新。任何一种自适应寻路最终都会变得极其复杂。除非您要制作世界上最大的塔防网格,否则只需简单的方法即可。


1
值得注意的是,塔防技术在手机上很流行,而寻路并不很快。特别是在稍旧的设备(例如Sidekick或Android 1.6设备)上。
seanmonstar

1
数十年来,开发人员一直在功能不那么强大的硬件上使用A *和Dijkstra之类的寻路算法(想想Game Boy)。只要实现起来相当有效,任何足够新的屏幕都足以适合游戏的手机都不会出现问题。这里讨论了一些不错的
Mike Strobel,2010年

+1。当我开发自己的DTD克隆时,我得出了相同的结论。我尝试逐步更新路径,但是算法变得过于复杂。花了一天的时间之后,我对每次更改都进行了完整的重新计算。那行得通,并且通过一些调整,我就能够使其足够快。
finnw 2011年


2

对于您的解决方案来说,这可能是过高的选择,但是请考虑向后路由而不是向前路由。

在TD游戏中,敌人通常试图达到特定目标。从该目标向后路由至第一个敌人,然后缓存该路径。在为后续敌人生成路径时,请使用第一条路径作为起点,依此类推。如果您有多个敌人进入点或多个目标,则应从一系列预先缓存的路径开始。


1

航路点寻路可能是td游戏的最佳选择,因为通常基于ai遵循直接路径的级别。基本上,您可以设置节点或航路点,然后将“ ai”点指向路标并走到它,一旦距该路标足够近,就可以到达下一个路标,面向它并朝它前进。


这仅适用于只能将炮塔放置在路径一侧的那些TD游戏-不适用于允许将棋塔放置在棋盘上任何位置的游戏。
伊恩

是的,起初作者没有指定他想要哪种类型,所以我认为它是非动态的。
罗塔克(Loktar)2010年

1

有人问过,您可以通过在玩家每次放置或卸下塔楼时重新计算路径来应对动态变化的环境,而您只是将该路径存储在内存中。环境不会在每一帧上都改变。

请注意,某些TD游戏具有设定的路径,并且不允许您在其上放置塔楼,因此它们可以通过简单的方法解决寻路:通过对路径进行硬编码而不是阻止路径:)


1

一个简单的解决方案是作弊。

事先设计地图,以确保没有死角。然后在每个路口,添加一个触发器,使角色选择路线(例如:始终向左转,始终向右转或随机)。


1
大概他在谈论诸如Desktop TD之类的事情,用户正在动态创建地图。仍然对于“哑巴”敌人来说可能是一个不错的解决方案,因此您可以使AI更好的敌人有点困难。
coderanger
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.