Java游戏中的无寻路运动

Java游戏中的无寻路运动,java,algorithm,path-finding,2d-games,Java,Algorithm,Path Finding,2d Games,假设我想让一个对象在整个游戏中沿着设定的路径在a点、B点和C点之间反复移动,这取决于它应该位于/朝哪个点移动的变量。现在,我可以编写一个完整的A*寻路程序,但这需要花费大量的时间,需要大量的代码来完成一些无法充分发挥其价值的事情。有没有更有效的方法?目前,我唯一的想法是让物体在一个方向上移动一定数量的像素,然后在另一个方向上,然后在另一个方向上移动,但是物体很容易在一段时间后移动几个像素。我应该补充一点,没有一个点是彼此的视线范围内的,所以物体必须绕着墙移动。非常感谢您的帮助,因为我觉得我错过了

假设我想让一个对象在整个游戏中沿着设定的路径在a点、B点和C点之间反复移动,这取决于它应该位于/朝哪个点移动的变量。现在,我可以编写一个完整的A*寻路程序,但这需要花费大量的时间,需要大量的代码来完成一些无法充分发挥其价值的事情。有没有更有效的方法?目前,我唯一的想法是让物体在一个方向上移动一定数量的像素,然后在另一个方向上,然后在另一个方向上移动,但是物体很容易在一段时间后移动几个像素。我应该补充一点,没有一个点是彼此的视线范围内的,所以物体必须绕着墙移动。非常感谢您的帮助,因为我觉得我错过了一些非常明显的东西


我应该澄清,这些墙不会改变位置。在整个游戏中,它们将保持在原来的位置。

我只会执行一次完整的a*路径查找,并存储结果对象移动。如果任何其他对象可能会更改路径,则可以再次触发路径查找。

我只会执行一次完整的a*路径查找,并存储结果对象移动。如果任何其他对象可能更改路径,则可以再次触发路径查找。

定义一系列点
p
,以便:

  • 任何两个连续点
    p[i]
    p[i+1]
    之间都没有障碍物

  • 沿着点的顺序移动将把你从A带到B,然后带到C

换句话说,你从a到B再到C,然后把它分成直线段。这些点是固定的,因此不会因为浮点精度而偏离路径


现在,您可以通过在序列
p
中逐点移动对象来实现目标。要反向移动,请向后迭代
p

定义一系列点
p
,以便:

  • 任何两个连续点
    p[i]
    p[i+1]
    之间都没有障碍物

  • 沿着点的顺序移动将把你从A带到B,然后带到C

换句话说,你从a到B再到C,然后把它分成直线段。这些点是固定的,因此不会因为浮点精度而偏离路径


现在,您可以通过在序列
p
中逐点移动对象来实现目标。要反向移动,请在
p
上反向迭代。

我从您的评论中假设“对象很容易在一段时间后去掉几个像素”,您面临的关键问题是如何定期更新对象的位置,使其沿着两点之间的路径移动。如果你每次只更新相同的数量,那么,正如你所说,它不太可能在终点结束

最简单的方法是使用一个变量,该变量表示对象已沿路径移动了多远。该算法可以非常快速地重新计算正确的位置

例如:

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)));
    }
}
通过在通话中用距离除以
进度
,您可以很容易地扩展此功能以实现恒定速度。或者,您可以通过创建一个包含位置列表和存储进度的类来支持沿路径移动

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();
    }

}
类路径{
私有最终列表位置=新ArrayList();
私有int currentPosition=0;
私人浮动进度=0.0f;
私人浮动速度=0.1f;
公共职位(职位){
职位。添加(职位);
}
公共无效更新(){
进步+=速度;
而(进度>1.0f){
currentPosition=nextPosition();
进度-=1.0f;
}
}
公共位置getCurrentPosition(){
返回Position.interpolatedPosition(positions.get(currentPosition)),positions.get(nextPosition()),progress;
}
private int nextPosition(){
返回(currentPosition+1)%positions.size();
}
}

你问题的第二部分是如何在遇到一系列障碍之前确定这条道路。这个问题的答案取决于很多因素——特别是你希望解决方案的最优程度和搜索算法的效率。然而,没有任何简单的捷径-通用路径查找不是一个简单的领域。根据您的应用程序,最简单的解决方案可能是,如果您已经知道地图的布局,您可以自己定义路径。

我从您的评论中假设“对象很容易在一段时间后去掉几个像素”关键问题是如何定期更新对象的位置,使其遵循两点之间的路径。如果你每次只更新相同的数量,那么,正如你所说,它不太可能在终点结束

最简单的方法是使用一个变量,该变量表示对象已沿路径移动了多远。该算法可以非常快速地重新计算正确的位置

例如:

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)));
    }
}
通过在通话中用距离除以
进度
,您可以很容易地扩展此功能以实现恒定速度。或者,您可以通过创建一个包含位置列表和存储进度的类来支持沿路径移动

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();
    }

}
类路径{
私有最终列表位置=新ArrayList();
私有int currentPosition=0;
私人浮动进度=0.0f;
私人浮动速度=0.1f;
公共职位(职位){
职位。添加(职位);
}
公共无效更新(){
进步+=速度;
而(进度>1.0f){
currentPosition=nextPosition();
进度-=1.0f;
}
}
公共位置getCurrentPosition(){
返回位置。插值位置(位置g