A * Pathfinding for 2D Grid-Based Platformers Legge til One-Way Platforms

I denne korte opplæringen vil vi utvide vår plattformsporingsleder slik at den kan håndtere enveisplattformer: blokkerer at tegnet kan hoppe gjennom og også gå videre. (Teknisk er disse toveisplattformene, siden du kan hoppe gjennom dem fra begge retninger, men la oss ikke dele hår!)

Demo

Du kan spille Unity demo, eller WebGL-versjonen (100 MB +), for å se det endelige resultatet i aksjon. Bruk WASD å flytte tegnet, venstre klikk på et sted for å finne en sti du kan følge for å komme dit, Høyreklikk en celle for å skifte bakken på det punktet, og middle-klikk å plassere en enveis plattform.

Endre kartet for å imøtekomme One-Way-plattformer

For å håndtere enveisplatformene må vi legge til en ny flisertype på kartet:

public enum TileType Tom, Block, OneWay

Enveisplattformer har samme veibanevekt som tomme fliser, det vil si, 1. Det er fordi spilleren alltid kan gå gjennom dem når de hopper opp; de stopper ham bare når han faller, og det påvirker ikke på noen måte karakterens bevegelse.

Vi trenger også en funksjon som lar oss vite om flisen på en bestemt posisjon er spesielt en enveis plattform:

offentlig bool IsOneWayPlatform (int x, int y) if (x < 0 || x >= mWidth || y < 0 || y >= mHeight) returnere false; returnere (fliser [x, y] == TileType.OneWay); 

Endelig må vi endre Map.IsGround å returnere ekte hvis en flis er enten en solid blokk eller en enveis plattform:

offentlig bool IsGround (int x, int y) if (x < 0 || x >= mWidth || y < 0 || y >= mHeight) returnere false; returnere (fliser [x, y] == TileType.OneWay || fliser [x, y] == TileType.Block); 

Det er kartet delen av koden sortert; nå kan vi jobbe på banen selv.

Legge til nye nodefiltreringsbetingelser

Vi må også legge til to nye node filtreringsbetingelser til vår liste. Husk, listen vår ser for øyeblikket ut slik:

  1. Det er startnoden.
  2. Det er sluttkoden.
  3. Det er en hoppekode.
  4. Det er en første in-air node i et sidestopp (en node med hoppverdien er lik 3).
  5. Det er landingsknudepunktet (en knute som hadde en ikke-zeo hoppe verdi blir 0).
  6. Det er høydepunktet av hoppet (knuten mellom å flytte oppover og og falle nedover).
  7. Det er en knutepunkt som går rundt et hinder.

Vi vil legge til disse to forholdene:

  • Knutepunktet er på en enveis plattform.
  • Noden er på bakken og den forrige noden var på en enveis plattform (eller omvendt).

Inkludert noder som er One-Way Platforms

Det første punktet: Vi vil alltid inkludere en knutepunkt hvis den er på en enveis plattform:

hvis ((mClose.Count == 0) || (mMap.IsOneWayPlatform (fNode.x, fNode.y - 1)) ... mClose.Add (fNode);

Inkluder grunnnodes hvis tidligere node var en enveis plattform

Det andre punktet: Vi må inkludere en knute hvis den er på bakken, og den forrige noden er på en enveis plattform:

hvis ((mClose.Count == 0) || (mMap.IsOneWayPlatform (fNode.x, fNode.y - 1)) || (mGrid [fNode.x, fNode.y - 1] == 0 && mMap.IsOneWayPlatform (fPrevNode.x, fPrevNode.y - 1)) ... mClose.Add (fNode);

Alt sammen, så ...

Her er en oppdatert liste over node-filterbetingelser; algoritmen vil slippe gjennom en node som oppfyller noen av følgende krav:

  1. Det er startnoden.
  2. Det er sluttkoden.
  3. Knutepunktet er på en enveis plattform.
  4. Noden er på bakken og den forrige noden var på en enveis plattform (eller omvendt).
  5. Det er en hoppekode.
  6. Det er en første in-air node i et sidestopp (en node med hoppverdien er lik 3).
  7. Det er landingsknudepunktet (en knutepunkt som hadde en null-null-verdi blir 0).
  8. Det er høydepunktet av hoppet (knuten mellom å flytte oppover og og falle nedover).
  9. Det er en knutepunkt som går rundt et hinder.

Og her er koden som sjekker alle disse forholdene:

hvis ((mClose.Count == 0) || (mMap.IsOneWayPlatform (fNode.x, fNode.y - 1)) || (mGrid [fNode.x, fNode.y - 1] == 0 && mMap.IsOneWayPlatform (fPrevNode.x, fPrevNode.y - 1)) || (fNodeTmp.JumpLength == 3) || (fNextNodeTmp.JumpLength! = 0 && fNodeTmp.JumpLength == 0) // mark hopp starter || (fNodeTmp.JumpLength == 0 && fPrevNodeTmp.JumpLength! = 0) // mark landinger || (fNode.y> mClose [mClose.Count - 1] .y && fNode.y> fNodeTmp.PY) || (fNode.y < mClose[mClose.Count - 1].y && fNode.y < fNodeTmp.PY) || ((mMap.IsGround(fNode.x - 1, fNode.y) || mMap.IsGround(fNode.x + 1, fNode.y)) && fNode.y != mClose[mClose.Count - 1].y && fNode.x != mClose[mClose.Count - 1].x)) mClose.Add(fNode);

Hvordan filtrering ser ut med One-Way Platforms

Til slutt, her er et eksempel på filtrering med enveisplattformer.

Konklusjon

Det er alt der er til det! Det er et enkelt tillegg, egentlig. I den neste opplæringen i denne serien legger vi til en litt mer komplisert (men likevel ganske enkel) utvidelse, noe som gjør det mulig å finne algoritmen for å finne tegn som er større enn 1x1 blokker.