Java 游戏中没有寻路的移动
Movement in Java games without pathfinding
假设我想让一个物体在整个游戏过程中沿着 A、B 和 C 点之间的设定路径重复移动,基于它应该 at/moving 朝向的变量。现在,我可以使用完整的 A* 寻路进行编程,但这会花费很多时间,并且需要大量代码才能真正发挥其全部价值。有没有更有效的方法来做到这一点?目前,我唯一的想法是让对象在一个方向上移动一定数量的像素,然后是另一个方向,然后是另一个方向,但是对象很容易在一段时间后移动几个像素。我应该补充一点,none 个点在彼此的视线范围内,因此物体必须绕着墙壁移动。感谢任何帮助,因为我觉得我在这里遗漏了一些非常明显的东西。
我应该澄清一下,墙壁不会改变位置。他们将在整个游戏中保持原样。
我只会进行一次完整的 A* 路径查找并存储结果对象移动。如果任何其他对象可能会更改路径,则可以再次触发路径查找。
定义点序列 p
使得:
任意两个连续点p[i]
和p[i + 1]
之间没有障碍物。
沿着点的顺序旅行会带你从A到B然后到C。
换句话说,您要走一条从 A 到 B 再到 C 的路径,并将其分成直线段。这些点是固定的,所以你不会因为浮点精度而偏离路径。
现在您可以通过在序列 p
中逐点移动对象来完成您的 objective。要反向移动,向后迭代 p
。
根据您的评论 "it would be very easy for the object to get several pixels off after a while",我假设您的关键问题是如何定期更新对象的位置,使其沿着两点之间的路径移动。如果你只是每次更新相同的数量,那么,正如你所说,它不太可能在终点结束。
执行此操作的最简单方法是使用一个变量来表示到目前为止对象沿着路径走了多远。该算法可以非常快速地重新计算出正确的位置。
例如:
class Position {
private final int x;
private final int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public static Position interpolatedPosition(Position from, Position to, float progress) {
return new Position(
from.x + Math.round(progress * (to.x - from.x)),
from.y + Math.round(progress * (to.y - from.y)));
}
}
您可以相当轻松地扩展它,通过将 progress
除以通话中的距离来实现恒定速度。或者,您可以通过创建一个包含位置列表和存储进度的 class 来支持沿路径的移动。
class Path {
private final List<Position> positions = new ArrayList<>();
private int currentPosition = 0;
private float progress = 0.0f;
private float speed = 0.1f;
public void addPosition(Position position) {
positions.add(position);
}
public void update() {
progress += speed;
while (progress > 1.0f) {
currentPosition = nextPosition();
progress -= 1.0f;
}
}
public Position getCurrentPosition() {
return Position.interpolatedPosition(positions.get(currentPosition), positions.get(nextPosition()), progress);
}
private int nextPosition() {
return (currentPosition + 1) % positions.size();
}
}
你问题的第二部分是如何提前确定这条绕过障碍物的路径。这个问题的答案取决于很多因素——特别是您希望解决方案达到多优以及搜索算法需要多高效。然而,没有任何简单的捷径 - 通用路径查找不是一个简单的领域。根据您的应用程序,如果您已经知道地图的布局,最简单的解决方案可能是自己定义路径。
假设我想让一个物体在整个游戏过程中沿着 A、B 和 C 点之间的设定路径重复移动,基于它应该 at/moving 朝向的变量。现在,我可以使用完整的 A* 寻路进行编程,但这会花费很多时间,并且需要大量代码才能真正发挥其全部价值。有没有更有效的方法来做到这一点?目前,我唯一的想法是让对象在一个方向上移动一定数量的像素,然后是另一个方向,然后是另一个方向,但是对象很容易在一段时间后移动几个像素。我应该补充一点,none 个点在彼此的视线范围内,因此物体必须绕着墙壁移动。感谢任何帮助,因为我觉得我在这里遗漏了一些非常明显的东西。
我应该澄清一下,墙壁不会改变位置。他们将在整个游戏中保持原样。
我只会进行一次完整的 A* 路径查找并存储结果对象移动。如果任何其他对象可能会更改路径,则可以再次触发路径查找。
定义点序列 p
使得:
任意两个连续点
p[i]
和p[i + 1]
之间没有障碍物。沿着点的顺序旅行会带你从A到B然后到C。
换句话说,您要走一条从 A 到 B 再到 C 的路径,并将其分成直线段。这些点是固定的,所以你不会因为浮点精度而偏离路径。
现在您可以通过在序列 p
中逐点移动对象来完成您的 objective。要反向移动,向后迭代 p
。
根据您的评论 "it would be very easy for the object to get several pixels off after a while",我假设您的关键问题是如何定期更新对象的位置,使其沿着两点之间的路径移动。如果你只是每次更新相同的数量,那么,正如你所说,它不太可能在终点结束。
执行此操作的最简单方法是使用一个变量来表示到目前为止对象沿着路径走了多远。该算法可以非常快速地重新计算出正确的位置。
例如:
class Position {
private final int x;
private final int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public static Position interpolatedPosition(Position from, Position to, float progress) {
return new Position(
from.x + Math.round(progress * (to.x - from.x)),
from.y + Math.round(progress * (to.y - from.y)));
}
}
您可以相当轻松地扩展它,通过将 progress
除以通话中的距离来实现恒定速度。或者,您可以通过创建一个包含位置列表和存储进度的 class 来支持沿路径的移动。
class Path {
private final List<Position> positions = new ArrayList<>();
private int currentPosition = 0;
private float progress = 0.0f;
private float speed = 0.1f;
public void addPosition(Position position) {
positions.add(position);
}
public void update() {
progress += speed;
while (progress > 1.0f) {
currentPosition = nextPosition();
progress -= 1.0f;
}
}
public Position getCurrentPosition() {
return Position.interpolatedPosition(positions.get(currentPosition), positions.get(nextPosition()), progress);
}
private int nextPosition() {
return (currentPosition + 1) % positions.size();
}
}
你问题的第二部分是如何提前确定这条绕过障碍物的路径。这个问题的答案取决于很多因素——特别是您希望解决方案达到多优以及搜索算法需要多高效。然而,没有任何简单的捷径 - 通用路径查找不是一个简单的领域。根据您的应用程序,如果您已经知道地图的布局,最简单的解决方案可能是自己定义路径。