等轴测图的精确 A* 搜索启发式?
我已经编写了 A* 搜索算法的实现。 问题是我目前使用的启发式方法仅适用于方形网格。 由于我的地图是等轴测图,启发式方法并未考虑地图的实际布局以及单元格之间的距离。
更新:经过广泛的记录和分析(理解为花费大量时间试图找出平庸),我得出的结论是我当前的启发式效果非常好,有一点例外:真实直线和对角线运动的最终结果是相反的。
inline int Pathfinder::calculateDistanceEstimate(const CellCoord& coord) const
{
int diagonal = std::min(abs(coord.x-goal->position.x), abs(coord.y-goal->position.y));
int straight = (abs(coord.x-goal->position.x) + abs(coord.y-goal->position.y));
return 14 * diagonal + 10 * (straight - 2 * diagonal);
}
这意味着,在等距地图上,直线移动的成本实际上是对角线移动的 sqrt(2)
倍,计算结果是对角线移动的成本。 问题是:如何修改当前的启发式,以便为等距布局生成正确的结果? 简单地用straight
替换diagonal
,反之亦然将不起作用。
I have written an implementation of the A* search algorithm. The problem is that the heuristic I'm currently using only works accurately on square grids. As my map is isometric, the heuristic doesn't take into account actual the layout of the map and thus, the distance between cells.
Update: After extensive logging and analysis (read as spending lots of time trying to figure out a banality), I have come to the conclusion that my current heuristic works quite well, with one little exception: the end result is reversed for real straight and diagonal movement.
inline int Pathfinder::calculateDistanceEstimate(const CellCoord& coord) const
{
int diagonal = std::min(abs(coord.x-goal->position.x), abs(coord.y-goal->position.y));
int straight = (abs(coord.x-goal->position.x) + abs(coord.y-goal->position.y));
return 14 * diagonal + 10 * (straight - 2 * diagonal);
}
This means that a straight move, which really costs sqrt(2)
times more than a diagonal move on an isometric map, is calculated to be the that of a diagonal one. The question is: how can I modify my current heuristic so it will produce correct results for an isometric layout? Simply replacing diagonal
with straight
and vice versa will not work.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
要尝试的一件事是将所有计算从等距坐标转换为方形网格坐标集。
假设 0,0 仍然是地图的根。 0,1 保持不变,1,2 变为 0,2; 1,3 变为 0,3; 2,3 变为 1,4; 3,3 变为 2,5; 0,2 变为-1,1; 等等。这会让你回到方形网格,这样坐标和启发式应该再次起作用。
Y 坐标变为 Y+sourceX 偏移量(3,3 位于 x=2 处;因此变为 2,5); 事实证明,以数学方式找到 sourceX 本身更加困难。
[意识流; 忽略] Y=0 处的等距坐标对于源 X 来说是准确的。因此,要计算源 X,您需要“向左/向上移动 Y 次”,这应该会产生 Y/2 的变化; 向下舍入,在 X 坐标中......粗略地表明方形坐标为:
其中 sourceX 和 sourceY 是普通方形网格中的坐标; Y/2 是整数算术/向下舍入。
因此,从理论上讲,这将变为:
基于新的问题进行更新:
假设您正在尝试获得距离(3,2; 3,3) < (距离(2,3;3,3)=距离(3,1;3,3)); 以下内容应该有效:(从 C# 翻译;不保证不存在拼写错误)
编辑:再次修复了可怕的拼写错误。
One thing to try would be converting from isometric coordinates to a square grid coordinate set for all calculations.
Say that 0,0 stays the root of the map. 0,1 stays the same, 1,2 becomes 0,2; 1,3 becomes 0,3; 2,3 becomes 1,4; 3,3 becomes 2,5; 0,2 becomes -1,1; etc. This puts you back into a square grid such that the coordinates and heuristics should work again.
Y coordinate becomes Y+sourceX offset (3,3 is at x=2; so becomes 2,5); finding sourceX mathmatically is proving itself more difficult.
[Stream of consciousness; ignore] Isometric coordinates at Y=0 are accurate for source X. So, to calculate source X you need to 'move left/up Y times' which should net a change of Y/2; rounded down, in the X coordinate.... roughly suggesting that the square coordinates would be:
Where sourceX and sourceY are the coordinates in a normal square grid; and Y/2 is integer arithmetic/rounded down.
So, in theory, this becomes:
Update based on new bits of question:
Assuming that you are trying to get distance(3,2; 3,3) < (distance(2,3; 3,3) = distance(3,1; 3,3)); the following should work: (translated from C#; typos not guaranteed to be non present)
EDIT: Fixed horrible typo.... again.
Amit 此处计算“六边形的曼哈顿距离”。 它是 C++ 代码,我不能保证它,但 Amit 是我以前听说过的游戏开发名字。
六边形的曼哈顿距离应该适合适当的启发式。
编辑:反转超链接的语法,哎呀。
Amit here computes the "manhattan distances for hexagons". Its C++ code, and I can't vouch for it, but Amit is a name I've heard before for game development.
The manhattan distance for hexagons should be suitable for a proper heuristic.
Edit: reversed the syntax for hyperlinking, whoops.