Förutom möjligheten att följa en väg måste en karaktär (eller en grupp av dem) också kunna följa ett visst tecken (som en truppledare). Detta kan uppnås med hjälp av ledare som följer beteende som jag förklarar i denna handledning.
Notera: Även om denna handledning skrivs med AS3 och Flash, borde du kunna använda samma tekniker och begrepp i nästan vilken spelutvecklingsmiljö som helst. Du måste ha en grundläggande förståelse för matematiska vektorer.
Ledaren som följer beteende är en sammansättning av andra styrkor, som alla är ordnade för att få en grupp karaktärer att följa en särskild karaktär (ledaren). Ett naivt förhållningssätt skulle använda sök eller strävan efter att skapa ett följdmönster, men resultatet är inte tillräckligt bra.
I sökbeteendet trycks en karaktär mot ett mål och upptar så småningom samma plats som det målet. Förföljandet beteende å andra sidan skjuter en karaktär mot ett annat tecken, men syftar till att fånga det (baserat på förutsägelser) istället för att bara följa det.
I ledaren följande beteende är målet att vara tillräckligt nära ledaren, men något bakom det. Karaktären ska också gå snabbare mot ledaren när de är avlägsna, men bör sakta ner när avståndet är litet. Detta kan alla uppnås genom att kombinera tre styrningsbeteenden:
I nästa avsnitt beskrivs hur varje av dessa beteenden kombineras för att skapa ledaren följande mönster.
Ett tecken ska försöka ligga något bakom ledaren under följande process, som en armé som ligger bakom befälhavaren. Poängen att följa (namngiven Bakom
) kan enkelt beräknas baserat på målets hastighet, eftersom det också representerar teckenriktningen. Kontrollera pseudokoden:
tv = leader.velocity * -1; tv = normalisera (tv) * LEADER_BEHIND_DIST; bakom = leader.position + tv;
Om hastighetsvektorn multipliceras med -1
, resultatet är omvänd av hastighetsvektorn. Den resulterande vektorn (kallad tv
) kan sedan normaliseras, skalas därefter och läggas till karaktärens nuvarande position.
Här är en visuell representation av processen:
Vektoroperationer som är inblandade i att hitta rätt ställe att följa.Ju större LEADER_BEHIND_DIST
desto större är avståndet mellan ledaren och den bakre punkten. Eftersom karaktärerna kommer att följa den punkten, desto mer avlägsen är det från ledaren, ju längre bort kommer karaktärerna att förbli från ledaren.
Nästa steg är att göra en karaktär följ ledarens Bakom
punkt. Precis som alla andra beteenden kommer följande process att styras av en kraft som genereras av followLeader ()
metod:
privat funktion followLeader (ledare: Boid): Vector3D var tv: Vector3D = leader.velocity.clone (); var kraft: Vector3D = ny Vector3D (); // Beräkna bakre punkten tv.scaleBy (-1); tv.normalize (); tv.scaleBy (LEADER_BEHIND_DIST); bakom = leader.position.clone (). add (tv); // Skapar en kraft för att komma fram till bakom punktstyrkan = force.add (anlända (bakom)); återvändande kraft;
Metoden beräknar Bakom
peka och skapar en kraft för att komma fram till den punkten. De followLeader
kraft kan sedan läggas till karaktärens styrkraft, precis som alla andra beteenden:
styrning = inget (); // null-vektorn, som betyder "nollstyrka" styrning = styrning + followLeader (); styrning = stympa (styrning, max_force) styrning = styrning / masshastighet = trunkera (hastighet + styrning, max_hastighet) position = läge + hastighet
Resultatet av detta genomförande är en grupp av tecken som kan komma fram till ledarens Bakom
punkt:
När tecken ligger väldigt nära varandra medan du följer ledaren kan resultatet tyckas onaturligt. Eftersom alla tecken kommer att påverkas av liknande krafter, tenderar de att flytta på samma sätt och bilda en "blob". Detta mönster kan fixas med hjälp av separation, en av de regler som styr flockningsbeteendet.
Separationskraften hindrar en grupp tecken från att tränga, så de håller ett visst avstånd från varandra. Separationskraften kan beräknas som:
privat funktionsseparation (): Vector3D var force: Vector3D = new Vector3D (); var neighborCount: int = 0; för (var i: int = 0; i < Game.instance.boids.length; i++) var b :Boid = Game.instance.boids[i]; if (b != this && distance(b, this) <= SEPARATION_RADIUS) force.x += b.position.x - this.position.x; force.y += b.position.y - this.position.y; neighborCount++; if (neighborCount != 0) force.x /= neighborCount; force.y /= neighborCount; force.scaleBy( -1); force.normalize(); force.scaleBy(MAX_SEPARATION); return force;
Separationskraften kan sedan läggas till followLeader
kraft, vilket gör det möjligt att skjuta tecknen bort från varandra på samma gång att de försöker komma fram till ledaren:
privat funktion followLeader (ledare: Boid): Vector3D var tv: Vector3D = leader.velocity.clone (); var kraft: Vector3D = ny Vector3D (); // Beräkna bakre punkten tv.scaleBy (-1); tv.normalize (); tv.scaleBy (LEADER_BEHIND_DIST); bakom = leader.position.clone (). add (tv); // Skapar en kraft för att komma fram till bakom punktstyrkan = force.add (anlända (bakom)); // Lägg till separationsstyrka kraft = force.add (separation ()); återvändande kraft;
Resultatet är ett mycket mer naturligt följande mönster:
Tecken som följer ledaren med separation. Flytta muspekaren för att styra ledaren. Klicka för att visa styrkor.Om ledaren plötsligt ändrar den aktuella riktningen finns det en chans att tecknen kommer att hamna i ledarens ledning. Eftersom karaktärerna följer ledaren, är det ingen mening att låta dem stanna framför ledaren.
Om någon karaktär kommer i ledaren, ska den omedelbart flytta bort för att rensa rutten. Detta kan uppnås med hjälp av evadebeteendet:
Undvik ledarens ruttFör att kontrollera om ett tecken ligger i ledarens syn använder vi ett liknande begrepp för hur vi upptäcker hinder i kollisionsundviklingsbeteendet: baserat på ledarens aktuella hastighet och riktning, projicerar vi en punkt framför den (kallad ett huvud
); om avståndet mellan ledarens ett huvud
peka och tecknet är mindre än 30
, till exempel då karaktären är i ledarens syn och bör flyttas.
De ett huvud
poäng beräknas exakt som Bakom
peka med skillnaden att hastighetsvektorn inte inverteras:
tv = leader.velocity; tv = normalisera (tv) * LEADER_BEHIND_DIST; framåt = ledareposition + tv;
De followLeader ()
Metoden måste uppdateras för att kontrollera om tecknet ligger på ledarens syn. Om det händer, variabeln tvinga
(som representerar följande kraft) läggs till genom retur av undgå (ledare)
, som återvänder en kraft för att undvika ledarens plats:
privat funktion followLeader (ledare: Boid): Vector3D var tv: Vector3D = leader.velocity.clone (); var kraft: Vector3D = ny Vector3D (); // Beräkna framåtpunkten tv.normalize (); tv.scaleBy (LEADER_BEHIND_DIST); framåt = leader.position.clone (). add (tv); // Beräkna bakre punkten tv.scaleBy (-1); bakom = leader.position.clone (). add (tv); // Om tecknet ligger på ledarens syn, lägg till en kraft // för att omedelbart undvika rutten. om (isOnLeaderSight (ledare, framåt)) force = force.add (evade (leader)); // Skapar en kraft för att komma fram till bakom punktstyrkan = force.add (ankomma (bakom, 50)); // 50 är ankommande radie // Lägg till separationsstyrka kraft = force.add (separation ()); återvändande kraft; privat funktion isOnLeaderSight (ledare: Boid, leaderAhead: Vector3D): Boolean (returavstånd (leaderAhead, this) <= LEADER_SIGHT_RADIUS || distance(leader.position, this) <= LEADER_SIGHT_RADIUS; private function distance(a :Object, b :Object) :Number return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
Alla tecken kommer omedelbart att undvika sin nuvarande position om det är ledarens syn:
Tecken som följer ledaren med hjälp av separation och undviker ledarens syn. Flytta muspekaren för att styra ledaren. Klicka för att visa styrkor.Nedan följer en demo som visar ledarens följande beteende. Den blå soldaten (ledaren) kommer fram till muspekaren medan de gröna soldaterna följer ledaren.
När spelaren klickar någonstans på skärmen kommer alla soldater att möta muspekaren och skjuta. Monstren kommer att komma till slumpmässiga platser, några sekunder.
Flytta muspekaren för att styra ledaren (soldaterna följer). Klicka för att skjuta monster.Ledaren som följer beteende tillåter en grupp av tecken att följa ett visst mål, som ligger något bakom det. Karaktärerna undviker också sin nuvarande plats om de så småningom kommer i ledningens ledning.
Det är viktigt att notera att ledaren som följer beteende är a kombination av flera andra beteenden, som anländer, undviker och skiljer sig åt. Det visar att enkla beteenden kan kombineras för att skapa extremt komplexa rörelsemönster.
Tack för att du läser! Jag hoppas att du kan börja kombinera de tidigare förklarade beteenden för att skapa ditt eget komplexa beteende!