3 enkle regler for flocking Behaviors Justering, Samhold og Separasjon

I den naturlige verden utviser organismer visse oppførsel når de reiser i grupper. Dette fenomenet, også kjent som flokker, forekommer ved både mikroskopiske skalaer (bakterier) og makroskopiske skalaer (fisk). Ved hjelp av datamaskiner kan disse mønstrene simuleres ved å lage enkle regler og kombinere dem. Dette er kjent som fremvoksende oppførsel, og kan brukes i spill for å simulere kaotisk eller livlig gruppebevegelse.

Merk: Selv om denne opplæringen er skrevet med Flash og AS3, bør du kunne bruke de samme teknikkene og konseptene i nesten hvilket som helst spillutviklingsmiljø.


Introduksjon

I denne veiledningen vil jeg dekke de tre hovedreglene som brukes til å simulere flokkning og forklare hvordan man implementerer hver enkelt. Før vi begynner, her er noen terminologi jeg skal bruke:

  • Middel: En enkelt enhet eller karakter.
  • Hastighetsvektor: En agentens nåværende hastighet.
  • Nabolag: Et bestemt område rundt agenten, pleide å lete etter andre agenter.
  • resulterende: Vektoren oppnådd fra regningens beregninger.

Denne demonstrasjonen viser effektene av de tre flokkene som jeg skal forklare i denne opplæringen: Justering, samhold, og atskillelse.

Full kildekode for denne demoen kan lastes ned her, så denne artikkelen vil bare markere de viktigste aspektene av implementeringen. Du er velkommen til å laste ned kilden hvis du vil lære mer.


Justering


Bilde tilpasset Craig Reynolds artikkel

Justering er en oppførsel som får en bestemt agent til å rette opp med agenter i nærheten.

Først skal vi lage en funksjon som tar en agent og returnerer en hastighetsvektor.

offentlig funksjon computeAlignment (myAgent: Agent): Point 

Vi trenger to variabler: en for lagring av vektoren vi skal beregne, og en annen for å holde oversikt over antall naboer til agenten.

var v: Punkt = nytt punkt (); var naboCount = 0;

Med våre variabler initialisert, vi nå iterate gjennom alle agenter og finne de i nabo radius - det vil si de som er nær nok til å bli ansett naboer av den angitte agenten. Hvis en agent er funnet innenfor radiusen, blir dens hastighet lagt til beregningsvektoren, og nabotellingen økes.

for hver (var agent: Agent i agentArray) hvis (agent! = myAgent) hvis (myAgent.distanceFrom (agent) < 300)  v.x += agent.velocity.x; v.y += agent.velocity.y; neighborCount++;   

Hvis ingen naboer ble funnet, returnerer vi bare null vektoren (standardverdien til beregningsvektoren).

hvis (neighborCount == 0) returnere v;

Til slutt deler vi beregningsvektoren ved nabotellingen og normaliserer den (divider den med lengden for å få en lengdevektor 1), oppnå den endelige resulterende vektor.

v.x / = neighborCount; v.y / = neighborCount; v.normalize (1); returnere v;

Cohesion


Bilde tilpasset Craig Reynolds artikkel

Samholdskraft er en oppførsel som gjør at agenter styrer mot "massesenteret" - det vil si den gjennomsnittlige plasseringen av agenter innenfor en viss radius.

Gjennomføringen er nesten identisk med justeringens oppførsel, men det er noen viktige forskjeller. Først, i stedet for å legge til hastighet til beregningsvektoren, den stilling er lagt til i stedet.

v.x + = agent.x; v.y + = agent.y;

Som før blir delingsvektoren delt av nabotellingen, noe som resulterer i posisjonen som tilsvarer massesenteret. Men vi vil ikke ha sentrum av massen selv, vi vil ha retningen mot massesenteret, så vi beregner vektoren som avstanden fra agenten til massesenteret. Endelig normaliseres denne verdien og returneres.

v.x / = neighborCount; v.y / = neighborCount; v = nytt punkt (v.x - myAgent.x, v.y - myAgent.y); v.normalize (1); returnere v;

Atskillelse


Bilde tilpasset Craig Reynolds artikkel

Separasjon er oppførselen som får en agent til å styre vekk fra alle naboene.

Gjennomføringen av adskillelse ligner meget på linje og sammenheng, så jeg bare peker på hva som er annerledes. Når en nærliggende agent er funnet, blir avstanden fra agenten til naboen lagt til beregningsvektoren.

v.x + = agent.x - myAgent.x; v.y + = agent.y - myAgent.y

Beregningsvektoren er delt med tilsvarende nabotelling, men før normalisering er det et enda viktigere trinn involvert. Den beregnede vektoren må bli negert for at agenten skal styre vekk fra naboene sine på riktig måte.

v.x * = -1; v.y * = -1;

Sette alt sammen

Når disse tre reglene er implementert, må de komme sammen. Den enkleste måten å gjøre dette på er som følger:

varjustering = beregnejustering (agent); Var kohesjon = ComputeChesion (agent); var separasjon = beregne separasjon (agent); agent.velocity.x + = alignment.x + cohesion.x + separation.x; agent.velocity.y + = alignment.y + cohesion.y + separation.y; agent.velocity.normalize (AGENT_SPEED);

Her beregner jeg bare de tre reglene for en bestemt agent, og legger dem til hastigheten. Jeg normaliserer deretter hastigheten og multipliserer med noen konstant som representerer standardhastigheten for en agent. Det er mulig å forbedre dette ytterligere ved å legge til vekter for hver regel for å finjustere atferdene:

agent.velocity.x + = alignment.x * alignmentWeight + cohesion.x * cohesionWeight + separation.x * separasjonsvekt; agent.velocity.y + = alignment.y * alignmentWeight + cohesion.y * cohesionWeight + separation.y * separasjonsvekt;

Endring av disse vekter vil forandre måten agenter flokker. Pass på å eksperimentere med tallene til du finner noe du liker.

Her er demoen igjen, så du kan prøve den ut:


Konklusjon

Flocking er enkel å implementere, men det har noen kraftige resultater. Hvis du lager et spill med AI, spesielt store grupper av AI som samhandler med hverandre, kan flokkning komme til nytte. Bruk det godt.