Pad volgen is een veel voorkomend probleem bij de ontwikkeling van games. Deze tutorial behandelt de pad volgt stuurgedrag, waarmee tekens een vooraf gedefinieerd pad van punten en lijnen kunnen volgen.
Notitie: Hoewel deze tutorial geschreven is met behulp van AS3 en Flash, zou je in bijna elke game-ontwikkelomgeving dezelfde technieken en concepten moeten kunnen gebruiken. Je moet een basiskennis hebben van wiskundige vectoren.
Een padvolgend gedrag kan op verschillende manieren worden geïmplementeerd. De originele Reynolds-implementatie maakt gebruik van een pad gemaakt van lijnen, waar personages hen strikt volgen, bijna als een trein op rails.
Afhankelijk van de situatie is een dergelijke nauwkeurigheid wellicht niet vereist. Een personage kan langs een pad langs lijnen lopen, maar ze gebruiken als een referentie, in plaats van als rails.
De implementatie van padvolggedrag in deze zelfstudie is een vereenvoudiging van het oorspronkelijke door Reynolds voorgestelde. Het levert nog steeds goede resultaten op, maar het is niet afhankelijk van zware wiskundige berekeningen zoals vectorprojecties.
Een pad kan worden gedefinieerd als een reeks punten (knooppunten) verbonden door lijnen. Hoewel krommen ook kunnen worden gebruikt om een pad te beschrijven, zijn punten en lijnen gemakkelijker te hanteren en produceren bijna dezelfde resultaten.
Als u curves moet gebruiken, kunnen deze worden teruggebracht tot een reeks verbonden punten:
De klas Pad
wordt gebruikt om de route te beschrijven. In principe heeft de klasse een vector van punten en een paar methoden om die lijst te beheren:
public class Path private var nodes: Vector.; public function Path () this.nodes = new Vector. (); public function addNode (node: Vector3D): void nodes.push (node); openbare functie getNodes (): Vector. return nodes;
Elk punt op het pad is een Vector3D
een positie in de ruimte vertegenwoordigen, op dezelfde manier als die van het personage positie
eigendom werkt.
Om het pad naar het pad te navigeren, verplaatst het teken zich van het knooppunt naar het knooppunt totdat het het einde van de route bereikt.
Elk punt in het pad kan worden gezien als een doelwit, dus het zoekgedrag kan worden gebruikt:
Zoek het ene punt na het andere.Het personage zoekt het huidige punt totdat het wordt bereikt, waarna het volgende punt in het pad het huidige punt wordt enzovoort. Zoals eerder beschreven in de zelfstudie over het vermijden van botsingen, worden de krachten van elk gedrag opnieuw berekend bij elke spelupdate, dus de overgang van het ene knooppunt naar het andere is naadloos en soepel.
De klasse van het personage heeft twee extra eigenschappen nodig om het navigatieproces te instrumenteren: het huidige knooppunt (het teken dat het personage zoekt) en een verwijzing naar het pad dat wordt gevolgd. De klas ziet er als volgt uit:
openbare klasse Boid public var path: Path; public var currentNode: int; (...) private functie pathFollowing (): Vector3D var target: Vector3D = null; if (path! = null) var nodes: Vector.= path.getNodes (); target = nodes [currentNode]; if (afstand (positie, doel) <= 10) currentNode += 1; if (currentNode >= nodes.length) currentNode = nodes.length - 1; return null; persoonlijke functie afstand (a: Object, b: Object): Number return Math.sqrt ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); (...)
De pathFollowing ()
methode is degene die verantwoordelijk is voor het genereren van het pad na kracht. Momenteel produceert het geen kracht, maar het selecteert de doelen juist.
De pad! = null
test controleert of het teken een willekeurig pad volgt. Als dat het geval is de currentNode
eigenschap wordt gebruikt om het huidige doel (dat het personage moet zoeken) op te zoeken in de lijst met punten.
Als de afstand tussen het huidige doel en de positie van het personage kleiner is dan 10
, het betekent dat het karakter het huidige knooppunt heeft bereikt. Als dat gebeurt, currentNode
wordt met één opgehoogd, wat betekent dat het personage het volgende punt in het pad zoekt. Het proces wordt herhaald totdat het pad geen punten meer heeft.
De kracht die wordt gebruikt om het personage naar elk knooppunt in het pad te duwen, is de zoekkracht. De pathFollowing ()
methode kiest al het juiste knooppunt, dus nu moet het een kracht teruggeven die het personage naar dat knooppunt drijft:
private function pathFollowing (): Vector3D var target: Vector3D = null; if (path! = null) var nodes: Vector.= path.getNodes (); target = nodes [currentNode]; if (afstand (positie, doel) <= 10) currentNode += 1; if (currentNode >= nodes.length) currentNode = nodes.length - 1; return target! = null? seek (target): new Vector3D ();
Nadat het pad dat volgt op kracht wordt berekend, moet het zoals gewoonlijk aan de snelheidsvector van het personage worden toegevoegd:
besturing = niets (); // de nulvector, wat betekent "nulkrachtmagnitude" besturing = sturen + pad Volgend (); sturen = afbreken (sturen, max_kracht) sturen = sturen / massasnelheid = afbreken (snelheid + sturen, max_snelheid) positie = positie + snelheid
De padvolgende stuurkracht lijkt erg op het achtervolgingsgedrag, waarbij het personage voortdurend zijn richting aanpast om het doelwit te vangen. Het verschil ligt in hoe het personage een onbeweeglijk doelwit zoekt, dat genegeerd wordt ten gunste van een ander zodra het personage te dichtbij komt.
Het resultaat is het volgende:
Pad volgt in actie. Klik om krachten te tonen.De huidige implementatie vereist dat alle karakters het huidige punt in het pad "aanraken" om het volgende doel te selecteren. Als gevolg hiervan kan een personage ongewenste bewegingspatronen uitvoeren, zoals cirkels rond een punt verplaatsen totdat het is bereikt.
In de natuur volgt elke beweging het principe van de minste inspanning. Een persoon zal bijvoorbeeld niet altijd in het midden van een gang lopen; als er een bocht is, loopt de persoon tijdens het draaien nauw in de richting van de muren om de afstand in te korten.
Dat patroon kan opnieuw worden gemaakt door een radius aan het pad toe te voegen. De straal wordt toegepast op de punten en deze kan worden gezien als de route "breedte". Het bepaalt hoe ver een personage zich van de punten langs de weg kan verplaatsen:
Invloed van radius op pad volgen.Als de afstand tussen het teken en het punt kleiner is dan of gelijk is aan de straal, wordt het punt als bereikt beschouwd. Als gevolg hiervan zullen alle personages met de lijnen en punten verplaatsen als gidsen:
Pad volgt met straal. Klik op de knop "Force" om krachten weer te geven. Klik op de knoppen "+" en "-" om de radiusgrootte dynamisch aan te passen.Hoe groter de straal, hoe breder de route en hoe groter de afstand die de personages tijdens het draaien van de punten behouden. De waarde van de straal kan worden aangepast om verschillende volgende patronen te produceren.
Soms is het nuttig dat een personage blijft bewegen nadat het het einde van het pad heeft bereikt. In een patrouillepatroon bijvoorbeeld, moet het personage terugkeren naar het begin van de route nadat het het einde heeft bereikt, en dezelfde punten volgen.
Dit kan worden bereikt door het toevoegen van de pathDir
eigendom van de klasse van het personage; dit is een geheel getal dat de richting regelt waarin het personage zich langs het pad beweegt. Als pathDir
is 1
, het betekent dat het personage naar het einde van het pad beweegt; -1
geeft een beweging naar het begin aan.
De pathFollowing ()
methode kan worden gewijzigd in:
private function pathFollowing (): Vector3D var target: Vector3D = null; if (path! = null) var nodes: Vector.= path.getNodes (); target = nodes [currentNode]; if (afstand (positie, doel) <= path.radius) currentNode += pathDir; if (currentNode >= nodes.length || currentNode < 0) pathDir *= -1; currentNode += pathDir; return target != null ? seek(target) : new Vector3D();
In tegenstelling tot de oudere versie, is de waarde van pathDir
is nu toegevoegd aan de eigenschap currentNode
(in plaats van gewoon toevoegen 1
). Hierdoor kan het teken het volgende punt in het pad selecteren op basis van de huidige richting.
Daarna controleert een test of het karakter het einde van de route heeft bereikt. Als dat het geval is, pathDir
wordt vermenigvuldigd met -1
, die zijn waarde inverteert, waardoor het karakter ook de bewegingsrichting omkeert.
Het resultaat is een heen-en-weer bewegingspatroon:
Pad volgt met straal en heen-en-weer patroon. Klik op de knop "Force" om krachten weer te geven. Klik op de knoppen "+" en "-" om de radiusgrootte dynamisch aan te passen.Met het padvolggedrag kan elk teken langs een vooraf gedefinieerd pad bewegen. De route wordt geleid door punten en kan worden aangepast om breder of smaller te zijn, waardoor bewegingspatronen ontstaan die natuurlijker aanvoelen.
De implementatie die in deze zelfstudie wordt behandeld, is een vereenvoudiging van het oorspronkelijke pad dat volgt op het gedrag dat Reynolds voorstelt, maar het levert nog steeds overtuigende en aansprekende resultaten op.