Verwenden Sie eine Liste mit dem Namen "Pfad", um die Wegpunkte zu speichern, die Ihren Pfad beschreiben, und eine doppelt verknüpfte Liste mit dem Namen "Schlange", um die sich bewegenden Objekte und den Pfad zu speichern.
Das Leitobjekt definiert auf seiner Reise neue Wegpunkte. Die folgenden Objekte bewegen sich entlang des Pfades, wie durch diese Wegpunkte definiert.
Jedes Objekt hat eine Sicherheitszone, die durch einen gewissen Abstand definiert ist. Wenn das führende Objekt angehalten wird, werden die folgenden Objekte nur so lange weiterbewegt, bis sie die Sicherheitszone ihres Vorgängers berühren.
Hier ist ein Pseudocode, wie diese Dinge implementiert werden könnten. Beachten Sie, dass dies möglicherweise nicht die eleganteste Lösung in Bezug auf die Verteilung von Verantwortlichkeiten und die Kapselung ist.
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();
}
}
}
Pfad-> Wegpunkte werden immer größer, je länger das Spiel dauert. Wenn Ihre Schlange schon länger existiert, müssen Sie den letzten Wegpunkt löschen, wenn das letzte Element der Schlange den vorletzten Wegpunkt des Pfads passiert hat. Denken Sie daran, auch distanceFromEnd in allen MovingObjects of Snake entsprechend zu reduzieren.
Im Wesentlichen benötigen Sie zwei Datenstrukturen (logisch, aufdringlich oder real, abhängig vom Rest Ihres Codes). Die erste verfolgt die Objektketten und die andere den Pfad.
Kette Sie müssen lediglich wissen, welche Objekte anderen Objekten folgen. Im einfachsten Fall ist dies einfach A folgt B, könnte aber mehr Anhänger enthalten. Es gibt einen bestimmten Anführer in der Kette.
Pfad Für jede Kette benötigen Sie einen Pfad. Abhängig davon, wie Ihr Spiel funktioniert, wird bestimmt, wie dies strukturiert ist. In den meisten Fällen handelt es sich um eine Art verknüpfte Liste. Dies wird die Positionen verfolgen, denen jeder in der Kette folgen muss.
Jetzt fügt der Anführer der Kette dem Pfad Elemente hinzu . Jedes Mal, wenn es sich bewegt, wird etwas zum Kopf der Liste hinzugefügt. Jedes Objekt in der Kette merkt sich, wo es sich auf der Liste befindet. Beim Verschieben wird einfach zum nächsten Element in der Liste gewechselt (bei Bedarf entsprechend interpoliert). Wenn der letzte Gegenstand in der Kette an einem Gegenstand in der Liste vorbeigeht, kann dieser Gegenstand fallengelassen werden (er befindet sich am Ende).
Metaphorisch hinterlässt der Anführer seinen Anhängern eine Paniermehlspur. Der letzte Follower in der Liste verbraucht den Breadcrumb.
Ob Ihre Liste einzelne Punkte oder nur die Eckpunkte eines Pfades oder etwas anderes enthält, hängt ausschließlich von Ihrer Spiel-Engine ab. Aber ich sehe auf keinen Fall, dass Sie die Liste selbst umgehen können.
quelle
A * -Pfadfindung nachschlagen. Dies ist ein allgemeiner und einfacher Weg, um Ihre Spielobjekte zu einer Position zu bewegen.
quelle