语境
老卢卡斯艺术公司(ScummVM时代)使用预先计算的寻路来点击图形冒险游戏。这是该技术的粗略概述。
第1步
每个房间的地板都被划分为所谓的“步行箱”,它们几乎等同于导航网格中的节点,但仅限于梯形形状。例如:
______ _____ _________ _____
\ A | B | C | D \
\_____| | |_______\
|_____| |
|_________|
第2步
离线算法(例如Dijkstra或A *)将计算每对节点之间的最短路径,并将路径的第一步存储在2D矩阵中,并在每个维度中由使用的起始节点和结束节点进行索引。例如,使用上面的步行框:
___ ___ ___ ___
| A | B | C | D | <- Start Node
___|___|___|___|___|
| A | A | A | B | C | ---
|___|___|___|___|___| |
| B | B | B | B | C | |
|___|___|___|___|___| |-- Next node in shortest path
| C | B | C | C | C | | from Start to End
|___|___|___|___|___| |
| D | B | C | D | D | ---
|___|___|___|___|___|
^
|
End Node
您可能会猜到,内存需求随着节点数量的增加而迅速增加(N ^ 2)。由于short通常足够大以将每个条目存储在矩阵中,因此具有300个节点的复杂映射会导致额外存储:
300^2 * sizeof(short) = 176 kilobytes
第三步
另一方面,计算两个节点之间的最短路径非常快捷且琐碎,只需对矩阵进行一系列查找即可。就像是:
// Find shortest path from Start to End
Path = {Start}
Current = Start
WHILE Current != End
Current = LookUp[Current, End]
Path.Add(Current)
ENDWHILE
应用此简单算法以查找从C到A的最短路径将返回:
1) Path = { C }, Current = C
2) Path = { C, B }, Current = B
3) Path = { C, B, A }, Current = A, Exit
题
我怀疑,借助当今功能强大的硬件,再加上对每个级别执行此操作所需要的内存,现在仅通过在运行时执行A *就能抵消这项技术曾经带来的任何好处。
我还听说如今的内存查找甚至可能比常规计算要慢,这就是为什么创建正弦和余弦查找表不再流行的原因。
但是我必须承认,尽管我对低级硬件效率的问题还不是很了解,所以我借此机会向更熟悉该主题的人提出意见。
在我的引擎上,我还需要能够在运行时动态地向图中添加和删除节点(请参见参考资料),因此预先计算的路由只会使事情变得更加复杂,因此我将其报废(更不用说我的运行时A *解决方案已经在完美运行)。尽管如此,我还是想知道...
归根结底,这种技术在当今任何情况下仍然有用吗?