Движение в Java-играх без поиска пути

Допустим, я хочу, чтобы объект перемещался по заданному пути между точками A, B и C неоднократно на протяжении всей игры, в зависимости от переменной, в которой он должен находиться/двигаться. Теперь я мог бы запрограммировать полный поиск пути A*, но это заняло бы много времени и потребовало бы много кода для чего-то, что на самом деле не использовалось бы в полной мере. Есть ли более эффективный способ сделать это? На данный момент единственная идея, которая у меня есть, состоит в том, чтобы объект перемещался на заданное количество пикселей в одном направлении, затем в другом, затем в другом, но через некоторое время объекту было бы очень легко сместиться на несколько пикселей. Добавлю, что ни одна из точек не находится в пределах прямой видимости друг от друга, поэтому объекту придется двигаться вокруг стен. Любая помощь приветствуется, так как я чувствую, что здесь не хватает чего-то очень очевидного.

Я должен уточнить, что стены не будут менять положение. Они останутся на месте на протяжении всей игры.


person senox13    schedule 17.08.2015    source источник
comment
Я думаю, вам нужно объяснить проблему немного больше. Я так понимаю, вы хотите разработать заданный путь между точками, который включает в себя обход препятствий, но вы не хотите использовать алгоритм поиска пути. Это правильно?   -  person sprinter    schedule 17.08.2015
comment
По сути, да. В частности, как я могу определить набор точек для перемещения между ними?   -  person senox13    schedule 17.08.2015
comment
@user2925591 user2925591 Не могли бы вы поддержать мой ответ?   -  person Michael Laszlo    schedule 17.08.2015


Ответы (3)


Из вашего комментария я предполагаю, что «объекту будет очень легко сбросить несколько пикселей через некоторое время», что ключевой вопрос, который у вас есть, заключается в том, как регулярно обновлять положение объекта, чтобы он следовал по пути между двумя точками. Если вы просто обновляете его каждый раз на одну и ту же сумму, то, как вы говорите, он вряд ли окажется в конечной точке.

Самый простой способ сделать это — использовать переменную, которая представляет, как далеко по пути прошел объект. Алгоритм может очень быстро пересчитать правильное положение.

Например:

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

}

Вторая часть вашего вопроса заключается в том, как заранее определить этот путь, обходя множество препятствий. Ответ на этот вопрос зависит от множества факторов, в частности от того, насколько оптимальным должно быть решение и насколько эффективным должен быть алгоритм поиска. Однако простых путей не существует — общий поиск пути — непростая область. В зависимости от вашего приложения самым простым решением может быть простое определение путей самостоятельно, если вы уже знаете макет карты.

person sprinter    schedule 17.08.2015
comment
Опять же, алгоритма поиска не будет. Просто ряд точек и движение между ними. Решение Майкла Ласло является лучшим здесь, поскольку оно указало на очень очевидную вещь, которую мне не хватало. Просто определение точек и перемещение между ними. - person senox13; 17.08.2015

Я бы выполнил полный поиск пути A * только один раз и сохранил движение объекта результата. Поиск пути может быть запущен снова, если какой-либо другой объект потенциально может изменить путь.

person Zaki Anwar Hamdani    schedule 17.08.2015
comment
Вопрос заключался в том, как определить пути без реализации полного поиска пути. У меня нет времени программировать то, что по сути не используется. - person senox13; 17.08.2015

Определите последовательность точек p так, чтобы:

  • Между любыми двумя последовательными точками p[i] и p[i + 1] нет препятствий.

  • Путешествие по последовательности точек приведет вас от A к B, а затем к C.

Другими словами, вы выбираете путь от A до B и C и разбиваете его на прямые сегменты. Точки фиксированы, поэтому вы не будете отклоняться от пути из-за точности с плавающей запятой.

Теперь вы можете выполнить свою задачу, перемещая объект из точки в точку в последовательности p. Чтобы двигаться в обратном направлении, повторите p назад.

person Michael Laszlo    schedule 17.08.2015
comment
из любопытства: определение последовательности точек... разве это не похоже на поиск пути? (вы делаете это вручную, но, в конце концов, это то же самое)... - person Martin Frank; 17.08.2015