Technique pour des objets qui se succèdent en mouvement complet?

14

Je me demande comment les objets se suivent lorsqu'ils se déplacent sur la position précédente de l'objet devant eux. Lorsque l'objet principal s'arrête, tout ce qui suit doit s'arrêter à sa position. Alors, comment est-ce possible?

Ainsi:

entrez la description de l'image ici

Edit:
Ce que je veux réaliser, c'est que tous les objets suivants "parcourent" le chemin que prend l'objet devant. Tous les autres objets se déplacent simplement à la vitesse de l'objet principal (ce serait en passant le vecteur vitesse à tous les objets suivants). Mais comment laisser tous les objets se déplacer / faire une pause sur le chemin tout en maintenant leur distance les uns par rapport aux autres.

Sidar
la source

Réponses:

11

Utilisez une liste appelée "Chemin" pour stocker les points de cheminement qui décrivent votre chemin, et une liste à double lien appelée "Serpent" pour stocker les objets en mouvement et le Chemin.

L'objet principal définit de nouveaux points de cheminement lors de son déplacement. Les objets suivants se déplacent le long du chemin défini par ces points de cheminement.

Chaque objet a une zone de sécurité définie par une certaine distance. Si l'objet principal s'arrête, les objets suivants se déplacent uniquement jusqu'à ce qu'ils touchent la zone de sécurité de leur prédécesseur.

Voici un pseudo-code pour savoir comment ces choses pourraient être implémentées. Sachez que ce n'est peut-être pas la solution la plus élégante en termes de répartition des responsabilités et d'encapsulation.

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 devient de plus en plus grand plus le jeu se poursuit. Si votre serpent existe depuis un certain temps, vous devez supprimer le dernier WayPoint chaque fois que le dernier élément du serpent a passé l'avant-dernier WayPoint du chemin. N'oubliez pas de réduire également distanceFromEnd dans tous les MovingObjects of Snake en conséquence.

BerndBrot
la source
Disons que je voudrais faire glisser mon objet principal avec ma souris (pas ce que je veux, mais disons que je le fais). Comment cela fonctionnerait-il avec votre exemple?
Sidar
La liste d'objets pourrait se déplacer en laissant d'abord le premier élément se déplacer de sa position actuelle dans une direction donnée (avec une vitesse donnée), puis en laissant tous les autres éléments se déplacer de leurs positions actuelles dans une direction spécifiée par leur position actuelle et $ this-> previousElement-> getPosition (). Si vous faites glisser votre premier élément quelque part, il vous suffit d'appeler sa méthode setPosition (). Lorsque la liste est rendue, les autres objets changeront de chemin pour suivre leurs prédécesseurs.
BerndBrot
Corrigez-moi si je me trompe, mais cela n'entraînerait-il pas également que les objets suivent des raccourcis lorsqu'ils changent de direction? (comme dans la partie inférieure de l'image que j'ai donnée). On dirait qu'ils ne suivraient pas le chemin de l'objet à l'avant. Au lieu de cela, ils iraient dans la direction de l'objet principal devant eux autant que possible. Causer des objets qui se détournent et prendre des raccourcis?
Sidar
Oui, cela se produirait en effet avec cette mise en œuvre particulière. J'ai posté la réponse avant d'ajouter vos photos, alors
réessayons
Bien. Et ça?
BerndBrot
6

Essentiellement, vous aurez besoin de deux structures de données (logique, intrusive ou réelle, selon le reste de votre code). Le premier suivra les chaînes d'objets et l'autre le chemin.

Chaîne Il vous suffit de savoir quels objets suivent d'autres objets. Dans le cas le plus simple, ce sera simplement A suit B, mais pourrait inclure plus de followers. Il y a un leader désigné dans la chaîne.

Chemin Pour chaque chaîne, vous aurez besoin d'un chemin. En fonction de la façon dont votre jeu fonctionne, cela déterminera la façon dont cela sera structuré. Dans la plupart des cas, il s'agira d'une sorte de liste chaînée. Cela permettra de suivre les positions que tout le monde dans la chaîne doit suivre.

Maintenant, le leader de la chaîne ajoutera des éléments au chemin . Chaque fois qu'il se déplace, il ajoute quelque chose en tête de liste. Chaque objet de la chaîne se souvient où il se trouve sur la liste. Lorsqu'il s'agit de se déplacer, il passe simplement à l'élément suivant de la liste (interpolé de manière appropriée si nécessaire). Lorsque le dernier élément de la chaîne passe devant un élément de la liste, cet élément peut être supprimé (ce sera à la queue).

Métaphoriquement, le leader laisse un fil d'Ariane à ses partisans. Le dernier suiveur de la liste consomme le fil d'Ariane.

Que votre liste contienne des points individuels, ou simplement les sommets d'un chemin, ou autre chose, est entièrement déterminé par votre moteur de jeu. Mais en tout cas, je ne vois pas que vous pourrez éviter la liste elle-même.

edA-qa mort-ora-y
la source
Ouais j'ai pensé une telle chose. C'est l'implémentation qui implose généralement mon esprit. Merci pour la réponse. Réponse de berndBrots approuvée mais votée par vous.
Sidar
-3

Recherche A * pathfinding. C'est un moyen général et facile pour que vos entités / objets de jeu se rendent / suivent une position.

le beurre
la source
Je sais ce qu'est A *, pas ce que je recherche et beaucoup trop lourd pour quelque chose qui semble beaucoup plus simple.
Sidar
votre réponse n'est même pas proche de la bonne réponse. Un * est un algorithme pour trouver un chemin. Bien qu'il ne veuille rien trouver, il veut juste que l'objet se suive exactement dans chaque position du dernier objet.
Ali1S232
Lorsque j'ai répondu à l'origine à la question, ce n'était pas fixe pour clarifier davantage / il n'y avait pas d'image pour montrer ce qu'il voulait dire. Je viens de lire les 2 premières phrases et j'ai pensé qu'il avait plusieurs entités essayant de suivre quelque chose, pas de suivre un chemin. Désolé pour la mauvaise réponse, je suppose
thedeadlybutter
J'ai dit de se suivre = P ne pas aller jusqu'à un point.
Sidar
Je sais, mes excuses.
thedeadlybutter