¿Técnica para que los objetos se sigan en movimiento completo?

14

Me pregunto cómo se siguen los objetos entre sí donde se mueven sobre la posición anterior del objeto frente a ellos. Cuando el objeto principal se detiene, todo lo que sigue debe detenerse en su posición. Entonces, ¿cómo se logra esto?

Al igual que:

ingrese la descripción de la imagen aquí

Editar:
Lo que quiero lograr es que todos los siguientes objetos "caminen" por el camino que está tomando el objeto principal al frente. Todos los demás objetos simplemente se mueven a la velocidad del objeto principal (esto sería pasando el vector de velocidad a todos los siguientes objetos). Pero, ¿cómo dejo que todos los objetos se muevan / pausen sobre el camino mientras mantengo su distancia entre ellos también?

Sidar
fuente

Respuestas:

11

Use una Lista llamada "Ruta" para almacenar los puntos de ruta que describen su ruta, y una lista doblemente vinculada llamada "Serpiente" para almacenar los objetos en movimiento y la Ruta.

El objeto principal define nuevos puntos de referencia a medida que viaja. Los siguientes objetos se mueven a lo largo de la ruta tal como se define en estos puntos intermedios.

Cada objeto tiene una zona de seguridad definida por cierta distancia. Si el objeto principal se detiene, los siguientes objetos se mueven solo hasta que toquen la zona de seguridad de su predecesor.

Aquí hay un pseudocódigo de cómo se podrían implementar estas cosas. Tenga en cuenta que esta podría no ser la solución más elegante en términos de distribución de responsabilidades y encapsulación.

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 se hace más y más grande cuanto más tiempo transcurre el juego. Si su Snake existe desde hace bastante tiempo, debe eliminar el último WayPoint cada vez que el último elemento de la Snake haya pasado el penúltimo WayPoint of Path. Recuerde reducir también distanceFromEnd en todos los MovingObjects of Snake en consecuencia.

BerndBrot
fuente
Digamos que me gustaría arrastrar mi objeto principal con el mouse (no es lo que quiero, pero digamos que sí). ¿Cómo funcionaría eso con tu ejemplo?
Sidar
La lista de objetos podría moverse dejando primero que el primer elemento se mueva desde su posición actual en una dirección dada (con una velocidad dada), y luego dejando que todos los demás elementos se muevan desde sus posiciones actuales en una dirección especificada por su posición actual y $ this-> previousElement-> getPosition (). Si arrastra su primer elemento a algún lugar, solo tiene que llamar a su método setPosition (). Cuando se representa la lista, los otros objetos cambiarán su ruta para seguir a sus predecesores.
BerndBrot
Corrígeme si me equivoco, pero ¿eso no daría lugar a que los objetos sigan tomando atajos a medida que cambian de dirección? (como en la parte inferior de la imagen que he dado). Parece que no seguirían el camino del objeto por adelantado. En cambio, irían en la dirección del objeto principal delante de ellos tanto como sea posible. ¿Causando que los objetos se salgan del camino y tomen atajos?
Sidar
Sí, eso sucedería con esta implementación particular. Publiqué la respuesta antes de que
agregues
Bien. ¿Qué hay de esto?
BerndBrot
6

Esencialmente, necesitará dos estructuras de datos (lógico, intrusivo o real, dependiendo del resto de su código). El primero rastreará las cadenas de objetos, y el otro el camino.

Cadena Simplemente necesita saber qué objetos siguen a otros objetos. En el caso más simple, esto será simplemente A sigue a B, pero podría incluir más seguidores. Hay un líder designado en la cadena.

Ruta Para cada cadena necesitarás una ruta. Dependiendo de cómo funcione su juego, determinará cómo está estructurado. En la mayoría de los casos, será algún tipo de lista vinculada. Esto hará un seguimiento de las posiciones que todos en la cadena deben seguir.

Ahora, el líder de la cadena agregará elementos a la ruta . Cada vez que se mueve, agregará algo al encabezado de la lista. Cada objeto en la cadena recuerda en qué parte de la lista está. Cuando se trata de moverlo, simplemente se mueve al siguiente elemento de la lista (interpolado de manera apropiada si es necesario). A medida que el último elemento de la cadena se mueve más allá de un elemento de la lista, ese elemento se puede soltar (estará en la cola).

Metafóricamente, el líder deja un rastro de migas de pan para sus seguidores. El último seguidor de la lista consume la miga de pan.

Si su lista contiene puntos individuales, o solo los vértices de un camino, o algo más, está determinado completamente por su motor de juego. Pero, en cualquier caso, no veo que puedas evitar la lista en sí.

edA-qa mort-ora-y
fuente
Sí, me imaginé tal cosa. Es la implementación que generalmente implosiona mi mente. Gracias por la respuesta sin embargo. Respuesta aprobada de berndBrots pero votó por la suya.
Sidar
-3

Búsqueda A * pathfinding. Esta es una forma general y fácil de hacer que sus entidades / objetos del juego vayan / sigan una posición.

la mantequilla mortal
fuente
Sé lo que es A *, no lo que estoy buscando y es demasiado pesado para algo que parece bastante más simple.
Sidar
su respuesta ni siquiera se acerca a la respuesta correcta. A * es un algoritmo para encontrar una ruta. Si bien no quiere encontrar nada, solo quiere que el objeto se siga exactamente en cada posición en que se encontraba el último objeto.
Ali1S232
Cuando originalmente respondí la pregunta, no se solucionó para aclarar más / no había una imagen que mostrara lo que quería decir. Acabo de leer las primeras 2 oraciones y pensé que tenía múltiples entidades tratando de rastrear algo, no seguir un camino. Perdón por la mala respuesta, supongo
thedeadlybutter
Dije que se siguieran = P no se mueve a un punto.
Sidar
Lo sé, mis disculpas.
thedeadlybutter