Техника для объектов, следующих друг за другом в полном движении?

14

Мне интересно, как объекты следуют друг за другом, когда они перемещаются по предыдущей позиции объекта перед ними. Когда ведущий объект останавливается, все, что следует, должно остановиться на своей позиции. Итак, как это достигается?

Вот так:

введите описание изображения здесь

Изменить: то,
что я хочу достичь, это то, что все следующие объекты «идут» по пути, по которому идет ведущий объект впереди. Все остальные объекты просто движутся со скоростью ведущего объекта (это было бы путем передачи вектора скорости всем следующим объектам). Но как я могу позволить всем объектам двигаться / останавливаться на пути, сохраняя при этом их расстояние друг от друга.

Sidar
источник

Ответы:

11

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

Ведущий объект определяет новые путевые точки во время движения. Следующие объекты движутся по пути, как определено этими путевыми точками.

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

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

class Position {
    property x;
    property y;
}
class WayPoint extends ListNode {
    property position;
}
class Path extends List { 
    property WayPoints = array();

    // Find out the x, y coordinates given the distance traveled on the path
    function getPositionFromDistanceFromEnd(distance) {
        currentWayPoint = this->first();
        while(distance > 0) {
            distanceBetweenWayPoints = this->getDistance(currentWayPoint, currentWayPoint->next());
            if(distanceBetweenWayPoints > distance) {
                position = ... // travel remaining distance between currentWayPoint and currentWayPoint->next();
                return position;
            } else {
                distance -= distanceBetweenWayPoints;
                currentWayPoint = currentWayPoint->next();
            }
        }
    }
    function addWayPoint(position) {
        // Vector describing the current and new direction of movement
        currentDirection = this->first() - this->second();
        newDirection = position - this->first();
        // If the direction has not changed, there is no need to add a new WayPoint
        if( this->sameDirection(currentDirection, newDirection) {
            this->first->setPosition(position);
        } else {
            this->add(position);
        }
    }
}
class Snake extends DoublyLinkedList {
    property Path;
    property MovingObjects = array();
}
abstract class MovingObject extends DoublyLinkedListNode {
    property Snake; // shared among all moving objects of the same snake
    property position;
    const securityDistance = 10;
    abstract function move() { }
}
class MovingObjectLeader extends MovingObject {
    property direction;
    function move() {
        this->position += this->direction * this->Snake->speed;
        this->Snake->Path->addWayPoint(this->position);
        if(this->hasFollower()) {
            this->follower->move();
        }
    }
}
class MovingObjectFollower extends MovingObject {
    property distanceFromEnd;
    function move() {
        this->distanceFromEnd += this->Snake->speed;

        // If too close to leader: stop in order to respect security distance
        if(this->distanceFromEnd > this->leader()->distanceFromEnd - this->securityDistance) {
            this->distanceFromEnd = this->leader()->distanceFromEnd - this->securityDistance;
        }

        this->position = this->Snake->getPositionFromDistanceFromEnd(this->distanceFromEnd);

        if(this->hasFollower()) {
            this->follower->move();
        }
    }
}

Path-> WayPoints становится больше и больше, чем дольше продолжается игра. Если ваша Змея существует в течение достаточно долгого времени, вам нужно удалять последнюю точку маршрута всякий раз, когда последний элемент змеи передал второй до последнего путь точки пути. Не забудьте также уменьшить distanceFromEnd во всех MovingObjects of Snake соответственно.

BerndBrot
источник
Допустим, я бы хотел перетащить свой ведущий объект с помощью мыши (не то, что я хочу, но скажем, что я делаю). Как это будет работать с вашим примером?
Сидар
Список объектов может перемещаться, сначала позволяя первому элементу перемещаться из его текущей позиции в заданном направлении (с заданной скоростью), а затем позволяя всем другим элементам перемещаться из их текущих позиций в направлении, определяемом их текущей позицией и $ this-> previousElement-> GetPosition (). Если вы перетащите свой первый элемент куда-нибудь, вам просто нужно вызвать его метод setPosition (). Когда список отображается, другие объекты изменят свой путь, чтобы следовать их предшественникам.
BerndBrot
Поправьте меня, если я ошибаюсь, но не приведет ли это к тому, что объекты будут следовать по ярлыкам, когда они меняют направление? (как в нижней части изображения, которое я дал). Похоже, они не будут следовать по пути объекта впереди. Вместо этого они пойдут в направлении ведущего объекта как можно дальше от них. Причинение объектам сойти с пути и ярлыки?
Сидар
Да, это действительно произошло бы с этой конкретной реализацией. Я опубликовал ответ, прежде чем вы добавили свои фотографии, поэтому давайте попробуем еще раз ...
BerndBrot
Хорошо. Что насчет этого?
BerndBrot
6

По сути, вам понадобятся две структуры данных (логическая, навязчивая или реальная, в зависимости от остальной части вашего кода). Первый будет отслеживать цепочки объектов, а другой путь.

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

Путь Для каждой цепочки вам понадобится путь. В зависимости от того, как ваша игра работает, будет зависеть, как она будет структурирована. В большинстве случаев это будет какой-то связанный список. Это позволит отслеживать позиции, которым должны следовать все в цепочке.

Теперь лидер в цепочке будет добавлять предметы на путь . Каждый раз, когда он перемещается, он добавляет что-то в начало списка. Каждый объект в цепочке запоминает, где он находится в списке. Когда дело доходит до перемещения, он просто перемещается к следующему элементу в списке (при необходимости интерполируется соответствующим образом). Когда последний элемент в цепочке проходит мимо элемента в списке, этот элемент можно отбросить (он будет в хвосте).

Метафорически лидер оставляет след своих последователей. Последний последователь в списке потребляет хлебную крошку.

Содержит ли ваш список отдельные точки, или только вершины пути, или что-то еще, полностью определяется вашим игровым движком. Но в любом случае я не вижу, что вы сможете избежать самого списка.

эд-ка морт-ора-й
источник
Да, я понял такую ​​вещь. Это реализация, которая обычно взрывает мой разум. Спасибо за ответ, хотя. Одобрено BerndBrots ответить, но проголосовал ваш.
Сидар
-3

Найти A * поиск пути. Это общий и простой способ заставить ваши игровые объекты / объекты переходить / следовать за позицией.

thedeadlybutter
источник
Я знаю, что такое A *, а не то, что я ищу, и слишком тяжелый для чего-то, что кажется гораздо более простым.
Сидар
Ваш ответ даже близко не соответствует правильному ответу. A * - это алгоритм поиска пути. Хотя он не хочет ничего искать, он просто хочет, чтобы объект точно следовал друг за другом в каждой позиции, в которой находился последний объект.
Ali1S232
Когда я первоначально ответил на вопрос, это не было исправлено, чтобы уточнить больше / не было изображения, чтобы показать, что он имел в виду. Я только что прочитал первые 2 предложения и понял, что у него несколько сущностей, пытающихся что-то отследить, а не следовать по пути. Извините за плохой ответ, я думаю
thedeadlybutter
Я сказал, следуй друг за другом = P не двигаться в точку.
Сидар
Я знаю, мои извинения.
Thedeadlybutter