In questo breve tutorial, estenderemo il nostro pathfinder platform in modo che possa gestire piattaforme a senso unico: blocchi che il personaggio può attraversare e anche avanzare. (Tecnicamente, queste sono piattaforme a due vie, dato che puoi saltarle da entrambe le direzioni, ma non dividiamo i capelli!)
Puoi giocare alla demo di Unity o alla versione WebGL (100 MB +), per vedere il risultato finale in azione. Uso WASD spostare il personaggio, sinistro del mouse su un punto per trovare un percorso che puoi seguire per arrivarci, tasto destro del mouse una cella per alternare il terreno in quel punto, e middle-click posizionare una piattaforma a senso unico.
Per gestire le piattaforme a senso unico, è necessario aggiungere un nuovo tipo di tessera alla mappa:
public enum TileType Empty, Block, OneWay
Le piattaforme a senso unico hanno lo stesso peso del pathfinder delle tessere vuote, ovvero, 1
. Questo perché il giocatore può sempre passare attraverso di loro quando salta in su; lo fermano solo quando cade, e ciò non sminuisce in alcun modo il movimento del personaggio.
Abbiamo anche bisogno di una funzione che ci faccia sapere se il riquadro in una data posizione è specificamente una piattaforma a senso unico:
public bool IsOneWayPlatform (int x, int y) if (x < 0 || x >= mWidth || y < 0 || y >= mHeight) return false; return (tiles [x, y] == TileType.OneWay);
Infine, dobbiamo cambiare Map.IsGround
ritornare vero
se una tessera è un blocco solido o una piattaforma a senso unico:
public bool IsGround (int x, int y) if (x < 0 || x >= mWidth || y < 0 || y >= mHeight) return false; return (tiles [x, y] == TileType.OneWay || tiles [x, y] == TileType.Block);
Questa è la parte della mappa del codice ordinata; ora possiamo lavorare sul pathfinder stesso.
Abbiamo anche bisogno di aggiungere due nuove condizioni di filtraggio dei nodi alla nostra lista. Ricorda, il nostro elenco al momento è simile a questo:
3
).0
).Vogliamo aggiungere queste due condizioni:
Il primo punto: vogliamo sempre includere un nodo se si trova su una piattaforma a senso unico:
if ((mClose.Count == 0) || (mMap.IsOneWayPlatform (fNode.x, fNode.y - 1)) ... mClose.Add (fNode);
Il secondo punto: dobbiamo includere un nodo se è a terra e il nodo precedente è su una piattaforma a una via:
if ((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);
Ecco un elenco aggiornato delle condizioni del filtro del nodo; l'algoritmo consentirà di passare attraverso qualsiasi nodo che soddisfi uno dei seguenti requisiti:
3
).0
).Ed ecco il codice che controlla tutte queste condizioni:
if ((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) // contrassegna salti inizia || (fNodeTmp.JumpLength == 0 && fPrevNodeTmp.JumpLength! = 0) // contrassegna atterraggi || (fNode.y> mChiudi [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);
Infine, ecco un esempio di filtraggio con piattaforme a una via.
Questo è tutto ciò che c'è da fare! È un'aggiunta semplice, davvero. Nel prossimo tutorial di questa serie, aggiungeremo un'estensione leggermente più complicata (ma ancora abbastanza semplice), che consente all'algoritmo del pathfinder di trattare i caratteri che sono più grandi dei blocchi 1x1.