I tillegg til evnen til å følge en bane, må et tegn (eller en gruppe av dem) også kunne følge en bestemt karakter (som en gruppeleder). Dette kan oppnås ved å bruke leder følger oppførsel, som jeg vil forklare i denne opplæringen.
Merk: Selv om denne opplæringen er skrevet med AS3 og Flash, bør du kunne bruke de samme teknikkene og konseptene i nesten hvilket som helst spillutviklingsmiljø. Du må ha en grunnleggende forståelse av matematiske vektorer.
Lederen som følger oppførsel er en sammensetning av andre styringskrefter, alle ordnet for å få en gruppe karakterer til å følge en bestemt karakter (lederen). En naiv tilnærming ville bruke søken eller jakten på å skape et følgemønster, men resultatet er ikke godt nok.
I søkegraden blir et tegn presset mot et mål, og til slutt opptar det samme sted som målet. Forfølgelsesadfærden skyver på den annen side et tegn mot et annet tegn, men tar sikte på å fange det (basert på spådommer) i stedet for bare å følge det.
I lederens oppførsel er målet å være nær nok til lederen, men litt bak den. Tegnet skal også bevege seg raskere mot lederen når de er fjernt, men skal sakte når avstanden er liten. Dette kan alle oppnås ved å kombinere tre styremønstre:
De neste avsnittene forklarer hvordan hver av disse oppføringene er kombinert for å skape lederens følgende mønster.
Et tegn bør forsøke å ligge litt bak lederen under den følgende prosessen, som en hær som holder seg bak sin kommandant. Poenget å følge (oppkalt bak
) kan enkelt beregnes basert på målets hastighet, siden det også representerer tegningsretningen. Sjekk pseudokoden:
tv = leader.velocity * -1; tv = normaliser (tv) * LEADER_BEHIND_DIST; bak = leder.posisjon + tv;
Hvis hastighetsvektoren blir multiplisert med -1
, Resultatet er omvendt av hastighetsvektoren. Den resulterende vektoren (kalt TV
) kan deretter normaliseres, skaleres tilsvarende, og legges til tegnets nåværende posisjon.
Her er en visuell fremstilling av prosessen:
Vector operasjoner involvert i å finne det rette stedet å følge.Det bedre LEADER_BEHIND_DIST
er jo større avstanden mellom lederen og bakpunktet er. Siden tegnene vil følge det punktet, jo mer fjernt er det fra lederen, desto lengre vil tegnene forbli fra lederen.
Det neste trinnet er å få et tegn følge lederens bak
punkt. På samme måte som alle andre oppføringer vil den følgende prosessen bli styrt av en kraft generert av followLeader ()
metode:
privat funksjon followLeader (leder: Boid): Vector3D var tv: Vector3D = leader.velocity.clone (); var kraft: Vector3D = ny Vector3D (); // Beregn bakpunktet tv.scaleBy (-1); tv.normalize (); tv.scaleBy (LEADER_BEHIND_DIST); bak = leader.position.clone (). add (tv); // Skaper en kraft for å komme fram til bakpunktet kraft = force.add (ankomme (bak)); tilbake kraft;
Metoden beregner bak
pek og skaper en kraft for å komme fram til det punktet. De followLeader
kraft kan da legges til karakterens styringskraft, akkurat som alle andre oppføringer:
styring = ingenting (); // null-vektoren, som betyr "nullstyrke" styring = styring + followLeader (); styring = trunkering (styring, maks_force) styring = styring / massehastighet = trunkering (hastighet + styring, maks_speed) posisjon = posisjon + hastighet
Resultatet av denne implementeringen er en gruppe tegn som kan komme til lederens bak
punkt:
Når tegn er svært nær hverandre mens du følger lederen, kan resultatet virke unaturlig. Siden alle tegnene vil bli påvirket av lignende krefter, har de en tendens til å bevege seg på samme måte som en "blob". Dette mønsteret kan løses ved hjelp av separasjon, en av reglene som styrer flockingens oppførsel.
Adskillelseskraften forhindrer at en gruppe tegn strekker seg, slik at de holder en viss avstand fra hverandre. Separasjonskraften kan beregnes som:
privat funksjonsseparering (): Vector3D var force: Vector3D = new Vector3D (); var naboCount: int = 0; for (var jeg: 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;
Separasjonskraften kan da legges til followLeader
tvinge, slik at den kan skyve tegnene vekk fra hverandre samtidig at de prøver å komme frem til lederen:
privat funksjon followLeader (leder: Boid): Vector3D var tv: Vector3D = leader.velocity.clone (); var kraft: Vector3D = ny Vector3D (); // Beregn bakpunktet tv.scaleBy (-1); tv.normalize (); tv.scaleBy (LEADER_BEHIND_DIST); bak = leader.position.clone (). add (tv); // Skaper en kraft for å komme fram til bakpunktet kraft = force.add (ankomme (bak)); // Legg til separasjonsstyrke kraft = force.add (separasjon ()); tilbake kraft;
Resultatet er et mye mer naturlig følgende mønster:
Tegn som følger lederen ved hjelp av separasjon. Flytt musepekeren for å lede lederen. Klikk for å vise styrker.Hvis lederen plutselig endrer den nåværende retningen, er det en sjanse for at tegnene vil ende opp med å komme i veien for lederen. Siden tegnene følger lederen, gir det ingen mening å tillate dem å holde seg foran lederen.
Hvis noen karakter kommer i veien for lederen, bør den straks bevege seg bort for å rydde ruten. Dette kan oppnås ved å bruke evadeatferd:
Unngår lederens ruteFor å sjekke om et tegn er i lederens syn, bruker vi et lignende konsept til hvordan vi oppdager hindringer i kollisionsvanskelighetsadferd: basert på lederens nåværende hastighet og retning, projiserer vi et punkt foran det (kalt fremover
); hvis avstanden mellom lederens fremover
pek og tegnet er mindre enn 30
, for eksempel, så er tegnet i lederens syn og skal flytte.
De fremover
punkt beregnes akkurat som bak
pek, med forskjellen at hastighetsvektoren ikke er invertert:
tv = leader.velocity; tv = normaliser (tv) * LEADER_BEHIND_DIST; fremover = leader.position + tv;
De followLeader ()
Metoden må oppdateres for å sjekke om tegnet er på lederens syn. Hvis det skjer, vil variabelen makt
(som representerer følgende kraft) legges ved retur av unndra (leder)
, som returnerer en kraft for å unngå lederens plassering:
privat funksjon followLeader (leder: Boid): Vector3D var tv: Vector3D = leader.velocity.clone (); var kraft: Vector3D = ny Vector3D (); // Beregn fremoverpunktet tv.normalize (); tv.scaleBy (LEADER_BEHIND_DIST); fremover = leader.position.clone (). add (tv); // Beregn bakpunktet tv.scaleBy (-1); bak = leader.position.clone (). add (tv); // Hvis tegnet er på lederens syn, legg til en kraft // for å unngå ruten umiddelbart. hvis (isOnLeaderSight (leder, fremover)) force = force.add (evade (leader)); // Skaper en kraft for å komme til bakpunktspunkten = force.add (ankomme (bak, 50)); // 50 er ankom radius // Legg til separasjonsstyrke kraft = force.add (separasjon ()); tilbake kraft; privat funksjon isOnLeaderSight (leder: Boid, leaderAhead: Vector3D): Boolsk returavstand (leaderAhead, dette) <= 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));
Et hvilket som helst tegn vil umiddelbart unnslippe sin nåværende posisjon hvis det er i lederens syn:
Tegn som følger lederen ved å bruke separasjon og unngår lederens syn. Flytt musepekeren for å lede lederen. Klikk for å vise styrker.Nedenfor er en demonstrasjon som viser lederens oppførsel. Den blå soldaten (lederen) kommer til musepekeren, mens de grønne soldatene følger lederen.
Når spilleren klikker hvor som helst på skjermen, vil alle soldater møte musepekeren og skyte. Monstrene kommer til tilfeldige steder, hvert par sekunder.
Flytt musepekeren for å lede lederen (soldatene følger). Klikk for å skyte monstrene.Lederen som følger oppførsel tillater en gruppe tegn å følge et bestemt mål, og holder seg litt bak den. Tegnene unngår også deres nåværende sted hvis de til slutt kommer i veien for lederen.
Det er viktig å merke seg at lederens oppførsel er en kombinasjon av flere andre oppføringer, som ankommer, unnviker og separerer. Det demonstrerer at enkle atferd kan kombineres for å skape ekstremt komplekse bevegelsesmønstre.
Takk for at du leste! Jeg håper du kan begynne å kombinere de tidligere forklarte oppføringene for å skape din egen komplekse oppførsel!