A *路径跟随某个步长与网格大小不同

时间:2017-08-08 21:26:49

标签: java a-star

我有这个方法:

public boolean moveTowardsPoint(Point p, double stepSize, double minDistance, ArrayList<GameBodyObject> objects,  boolean shouldStepInto, AStar astar) {

    ArrayList<GameBodyObject> others = (ArrayList<GameBodyObject>) objects.clone();
    others.remove(this);

    if(aStarPath == null || lastPointToMove == null || !lastPointToMove.isAlmostTheSame(p, 0.01)) {
        try {
            astar.getGrid().unsetObstacleForObject(this);
            aStarPath = astar.process(this, p, objects);
            Collections.reverse(aStarPath);
            currentIndex = 0;
            current = null;
            astar.getGrid().reset();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    lastPointToMove = p.clone();

    double dx = p.getX() - getPosition().getX();
    double dy = p.getY() - getPosition().getY();

    Point lastPosition = getPosition().clone();

    boolean isClose = false;
    double dist = Math.sqrt(dx * dx + dy * dy);

    if (dist < Math.max(minDistance, stepSize)) {
        isClose = true;
    } else {
        if(aStarPath.indexOf(current) >= aStarPath.size() - 1) {

            if(shouldStepInto && dist <= stepSize) {
                setPosition(p.clone());
            }

        } else if(aStarPath != null && aStarPath.size() > 0) {
            if (current == null) {
                currentIndex = 0;
                current = aStarPath.get((int)currentIndex);
            }
            double mss = stepSize / current.getWidth();
            Spot p2 = aStarPath.get(Math.min((int)Math.ceil(currentIndex + mss), aStarPath.size() - 1));
            Spot p1 = current;
            if(!p1.equals(p2)) {
                Vector v = new Vector(p2.getX() - p1.getX(), p2.getY() - p1.getY()).normalize();
                getPosition().moveByVector(v.mult(stepSize));
                setRotation(v.getAngle());
            }
            currentIndex = Math.min(currentIndex + mss, aStarPath.size() - 1);
            current = aStarPath.get((int)currentIndex);
        }
    }
    return isClose;
}

这是GameBodyObject的方法。

它应该计算A *路径并向该路径上的某个点移动,但它的移动速度比currentcurrentIndex)向前移动通过路径要慢。我在开始时有一些距离检查,但这并不重要。我将currentIndex移动stepSize除以grid cell size。就我而言,它是0.6。然后我有一个moveByVector方法,它只是通过向量移动Point

如何使其同步,使其移动速度与currentcurrentIndex)一样快?它甚至可能吗?

修改

以下是我的变量定义:

private List<Spot> aStarPath = null;
private Spot current = null;
private double currentIndex = -1;
private Point lastPointToMove;

1 个答案:

答案 0 :(得分:0)

该解决方案中存在一个错误。在对角线上currentIndex比玩家移动的速度快。因此,您必须考虑玩家沿着该路径移动的角度。具体地说:

  double coef = Math.max(Math.abs(Math.cos(angle)),Math.abs(Math.sin(angle)));
  double mss = stepSize / (current.getWidth() / coef);

完整的方法现在看起来像这样,就像一个魅力:

public boolean moveTowardsPoint(Point p, double stepSize, double minDistance, ArrayList<GameBodyObject> objects,  boolean shouldStepInto, AStar astar) {

    ArrayList<GameBodyObject> others = (ArrayList<GameBodyObject>) objects.clone();
    others.remove(this);

    if(aStarPath == null || lastPointToMove == null || !lastPointToMove.isAlmostTheSame(p, 0.01)) {
        try {
            astar.getGrid().unsetObstacleForObject(this);
            aStarPath = astar.process(this, p, objects);
            Collections.reverse(aStarPath);
            currentIndex = 0;
            current = null;
            astar.getGrid().reset();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    lastPointToMove = p.clone();

    double dx = p.getX() - getPosition().getX();
    double dy = p.getY() - getPosition().getY();

    Point lastPosition = getPosition().clone();

    boolean isClose = false;
    double dist = Math.sqrt(dx * dx + dy * dy);

    if (dist < Math.max(minDistance, stepSize)) {
        isClose = true;
    } else {
        if(aStarPath.indexOf(current) >= aStarPath.size() - 1) {

            if(shouldStepInto && dist <= stepSize) {
                setPosition(p.clone());
            }

        } else if(aStarPath != null && aStarPath.size() > 0) {
            if (current == null) {
                currentIndex = 0;
                current = aStarPath.get((int)currentIndex);
            }
            Spot c1 = aStarPath.get((int)currentIndex);
            Spot c2 = aStarPath.get(Math.min((int)currentIndex + 1, aStarPath.size() - 1));
            double angle = new Vector(c2.getX() - c1.getX(),c2.getY() - c1.getY()).getAngle();
            double coef = Math.max(Math.abs(Math.cos(angle)),Math.abs(Math.sin(angle)));
            double mss = stepSize / (current.getWidth() / coef);
            Spot p2 = aStarPath.get(Math.min((int)Math.ceil(currentIndex + mss), aStarPath.size() - 1));
            Spot p1 = current;
            if(!p1.equals(p2)) {
                Vector v = new Vector(p2.getX() - p1.getX(), p2.getY() - p1.getY()).normalize();
                getPosition().moveByVector(v.mult(stepSize));
                setRotation(v.getAngle());
            }
            currentIndex = Math.min(currentIndex + mss, aStarPath.size() - 1);
            current = aStarPath.get((int)currentIndex);
        }
    }

    return isClose;
}