Lenkverhalten verstehen Pfad folgt

Pfadverfolgung ist ein häufiges Problem bei der Spielentwicklung. Dieses Tutorial behandelt die Pfad folgt Lenkverhalten, mit dem Zeichen einem vordefinierten Pfad aus Punkten und Linien folgen können.

Hinweis: Obwohl dieses Tutorial mit AS3 und Flash geschrieben wurde, sollten Sie in der Lage sein, in fast jeder Spieleentwicklungsumgebung dieselben Techniken und Konzepte anzuwenden. Sie müssen ein grundlegendes Verständnis von mathematischen Vektoren haben.


Einführung

Ein Pfadfolgeverhalten kann auf verschiedene Arten implementiert werden. Die ursprüngliche Reynolds-Implementierung verwendet einen Pfad aus Linien, auf dem die Zeichen streng folgen, fast wie ein Zug auf Schienen.

Je nach Situation ist eine solche Genauigkeit möglicherweise nicht erforderlich. Ein Charakter kann sich entlang von Pfaden entlang von Linien bewegen, aber als Zeichen verwenden Referenz, anstatt als Schienen.

Die Implementierung des Pfadfolgeverhaltens in diesem Lernprogramm ist eine Vereinfachung des von Reynolds vorgeschlagenen ursprünglichen Verhaltens. Sie liefert immer noch gute Ergebnisse, ist jedoch nicht auf umfangreiche mathematische Berechnungen wie Vektorprojektionen angewiesen.


Pfad definieren

Ein Pfad kann als eine Gruppe von Punkten (Knoten) definiert werden, die durch Linien verbunden sind. Obwohl Kurven auch zur Beschreibung eines Pfads verwendet werden können, sind Punkte und Linien einfacher zu handhaben und erzeugen fast die gleichen Ergebnisse.

Wenn Sie Kurven verwenden müssen, können sie auf eine Reihe verbundener Punkte reduziert werden:


Kurven und Linien.

Die Klasse Pfad wird verwendet, um die Route zu beschreiben. Grundsätzlich verfügt die Klasse über einen Punktvektor und einige Methoden zum Verwalten dieser Liste:

 öffentliche Klasse Pfad private Var-Knoten: Vektor.; public function Path () this.nodes = neuer Vektor.();  public function addNode (node: Vector3D): void node.push (node);  public function getNodes (): Vektor. Rückkehrknoten; 

Jeder Punkt im Pfad ist ein Punkt Vector3D repräsentiert eine Position im Raum, genauso wie der Charakter Position Eigenschaft arbeitet.


Wechsel von Knoten zu Knoten

Um durch den Pfad zu navigieren, bewegt sich der Charakter von Knoten zu Knoten bis zum Ende der Route.

Jeder Punkt im Pfad kann als Ziel angesehen werden, sodass das Suchverhalten verwendet werden kann:

Suchen Sie einen Punkt nach dem anderen.

Der Charakter sucht den aktuellen Punkt bis zum Erreichen des Punktes, dann wird der nächste Punkt im Pfad zum aktuellen Punkt und so weiter. Wie bereits im Tutorial zur Kollisionsvermeidung beschrieben, werden die Kräfte jedes Verhaltens bei jedem Spielupdate neu berechnet, sodass der Übergang von einem Knoten zu einem anderen nahtlos und reibungslos erfolgt.

Die Klasse des Charakters benötigt zwei zusätzliche Eigenschaften, um den Navigationsprozess zu instrumentieren: den aktuellen Knoten (den, nach dem der Charakter sucht) und einen Verweis auf den Pfad, dem gefolgt wird. Die Klasse sieht wie folgt aus:

 öffentliche Klasse Boid public var path: Pfad; public var currentNode: int; (…) Private Funktion pathFollowing (): Vector3D var target: Vector3D = null; if (Pfad! = null) Var-Knoten: Vektor. = path.getNodes (); Ziel = Knoten [CurrentNode]; wenn (Entfernung (Position, Ziel) <= 10)  currentNode += 1; if (currentNode >= node.length) currentNode = node.length - 1;  NULL zurückgeben;  private Funktionsentfernung (a: Object, b: Object): Number return Math.sqrt ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));  (…)

Das pathFollowing () Die Methode ist diejenige, die für die Erzeugung der Pfadfolgekraft verantwortlich ist. Derzeit wird keine Kraft erzeugt, aber die Ziele werden richtig ausgewählt.

Das Pfad! = Null test prüft, ob das Zeichen einem Pfad folgt. Ist das der Fall? currentNode Diese Eigenschaft wird verwendet, um das aktuelle Ziel (das Ziel, das der Charakter suchen muss) in der Liste der Punkte nachzuschlagen.

Wenn der Abstand zwischen dem aktuellen Ziel und der Position des Charakters geringer ist als 10, Dies bedeutet, dass der Charakter den aktuellen Knoten erreicht hat. Falls das passiert, currentNode wird um eins erhöht, dh der Charakter sucht den nächsten Punkt im Pfad. Der Vorgang wird wiederholt, bis der Pfad keine Punkte mehr hat.


Kräfte berechnen und hinzufügen

Die Kraft, die verwendet wird, um den Charakter auf jeden Knoten im Pfad zu drücken, ist die Suchkraft. Das pathFollowing () Die Methode wählt bereits den entsprechenden Knoten aus. Jetzt muss eine Kraft zurückgegeben werden, die den Charakter in Richtung des Knotens schiebt:

 private Funktion pathFollowing (): Vector3D var target: Vector3D = null; if (Pfad! = null) Var-Knoten: Vektor. = path.getNodes (); Ziel = Knoten [CurrentNode]; wenn (Entfernung (Position, Ziel) <= 10)  currentNode += 1; if (currentNode >= node.length) currentNode = node.length - 1;  return target! = null? Suchen (Ziel): new Vector3D (); 

Nachdem die Pfadkraft berechnet wurde, muss sie wie üblich zum Geschwindigkeitsvektor des Charakters hinzugefügt werden:

 lenkung = nichts (); // der Nullvektor, was "Zero-Force-Betrag" bedeutet Lenkung = Lenkung + PfadFolgen (); Lenkung = verkürzt (Lenkung, max_force) Lenkung = Lenkung / Massengeschwindigkeit = verkürzt (Geschwindigkeit + Lenkung, max_speed) Position = Position + Geschwindigkeit

Der Pfad, der der Lenkkraft folgt, ist dem Verfolgungsverhalten sehr ähnlich, bei dem der Charakter ständig seine Richtung ändert, um das Ziel einzufangen. Der Unterschied besteht darin, wie der Charakter ein unbewegliches Ziel sucht, das zu Gunsten eines anderen ignoriert wird, sobald der Charakter zu nahe kommt.

Das Ergebnis ist folgendes:

Pfad folgt in Aktion. Klicken Sie, um Kräfte anzuzeigen.

Die Bewegung glätten

Die aktuelle Implementierung erfordert, dass alle Zeichen den aktuellen Punkt im Pfad "berühren", um das nächste Ziel auszuwählen. Infolgedessen führt ein Charakter möglicherweise unerwünschte Bewegungsmuster aus, z. B. indem er sich in Kreisen um einen Punkt bewegt, bis er erreicht wird.

In der Natur folgt jede Bewegung dem Prinzip der geringsten Anstrengung. Zum Beispiel kann eine Person nicht ständig in einem Korridor laufen; Wenn es eine Kurve gibt, geht die Person beim Wenden dicht an die Wände, um die Entfernung zu verkürzen.

Dieses Muster kann durch Hinzufügen eines Radius zum Pfad neu erstellt werden. Der Radius wird auf die Punkte angewendet und kann als Routenbreite angesehen werden. Es wird gesteuert, wie weit sich ein Charakter von den Punkten auf dem Weg entfernen kann:

Einfluss des Radius auf den Pfadverlauf.

Wenn der Abstand zwischen dem Zeichen und dem Punkt kleiner oder gleich dem Radius ist, wird der Punkt als erreicht betrachtet. Als Folge bewegen sich alle Charaktere unter Verwendung der Linien und Punkte als Führungen:

Pfad mit Radius folgen. Klicken Sie auf die Schaltfläche "Force", um die Kräfte anzuzeigen. Klicken Sie auf die Schaltflächen "+" und "-", um die Radiusgröße dynamisch anzupassen.

Je größer der Radius ist, desto breiter ist die Route und desto größer ist der Abstand, den die Charaktere beim Abbiegen von den Punkten halten. Der Wert des Radius kann angepasst werden, um verschiedene folgende Muster zu erzeugen.


Vor und zurück gehen

Manchmal ist es nützlich, dass sich ein Charakter weiter bewegt, nachdem er das Ende des Pfades erreicht hat. In einem Patrouillenmuster sollte der Charakter beispielsweise nach dem Erreichen des Endes an den Anfang der Route zurückkehren, und zwar an denselben Punkten.

Dies kann durch Hinzufügen von erreicht werden pathDir Eigenschaft für die Klasse des Charakters; Dies ist eine Ganzzahl, die die Richtung steuert, in die sich der Charakter entlang des Pfads bewegt. Ob pathDir ist 1, es bedeutet, dass sich der Charakter am Ende des Pfades bewegt; -1 bezeichnet eine Bewegung in Richtung Anfang.

Das pathFollowing () Methode kann geändert werden in:

 private Funktion pathFollowing (): Vector3D var target: Vector3D = null; if (Pfad! = null) Var-Knoten: Vektor. = path.getNodes (); Ziel = Knoten [CurrentNode]; wenn (Entfernung (Position, Ziel) <= path.radius)  currentNode += pathDir; if (currentNode >= Knoten.Länge || currentNode < 0)  pathDir *= -1; currentNode += pathDir;    return target != null ? seek(target) : new Vector3D(); 

Im Gegensatz zur älteren Version ist der Wert von pathDir wird jetzt der Eigenschaft hinzugefügt currentNode (statt einfach hinzuzufügen 1). Dadurch kann das Zeichen den nächsten Punkt im Pfad basierend auf der aktuellen Richtung auswählen.

Danach prüft ein Test, ob der Charakter das Ende der Route erreicht hat. Wenn das der Fall ist, pathDir wird mit multipliziert -1, Dadurch wird der Wert invertiert, wodurch der Charakter auch die Bewegungsrichtung invertiert.

Das Ergebnis ist ein Hin- und Herbewegungsmuster:

Pfad mit Radius und Hin und Her Muster. Klicken Sie auf die Schaltfläche "Force", um die Kräfte anzuzeigen. Klicken Sie auf die Schaltflächen "+" und "-", um die Radiusgröße dynamisch anzupassen.

Fazit

Das Pfadfolgeverhalten ermöglicht jedem Zeichen, sich auf einem vordefinierten Pfad zu bewegen. Die Route wird nach Punkten geführt und kann breiter oder schmaler eingestellt werden, wodurch sich Bewegungsmuster ergeben, die sich natürlicher anfühlen.

Die in diesem Tutorial behandelte Implementierung ist eine Vereinfachung des ursprünglichen Verhaltens, das von Reynolds vorgeschlagen wird, führt jedoch zu überzeugenden und ansprechenden Ergebnissen.