A * Pathfinding pour les plates-formes basées sur une grille 2D ajout de plates-formes unidirectionnelles

Dans ce court tutoriel, nous allons élargir notre cheminement de plateforme afin qu'il puisse traiter des plateformes à sens unique: blocs que le personnage peut traverser et également franchir. (Techniquement, ce sont des plates-formes à double sens, puisque vous pouvez les traverser de n'importe quelle direction, mais ne coupons pas les cheveux en quatre!)

Démo

Vous pouvez jouer à la démonstration de Unity ou à la version WebGL (100 Mo +) pour voir le résultat final en action. Utilisation WASD déplacer le personnage, click gauche sur un endroit pour trouver un chemin que vous pouvez suivre pour vous y rendre, clic-droit une cellule pour basculer le sol à ce point, et Clic du milieu placer une plate-forme à sens unique.

Modification de la carte pour accueillir des plates-formes à sens unique

Pour gérer les plates-formes à sens unique, nous devons ajouter un nouveau type de mosaïque à la carte:

Énumération publique TileType Empty, Block, OneWay

Les plates-formes unidirectionnelles ont le même poids de trajectoire que les tuiles vides, c’est-à-dire, 1. C'est parce que le joueur peut toujours les parcourir lorsqu'il saute vers le haut. ils ne l'empêchent que quand il tombe, ce qui n'altère en rien le mouvement du personnage.

Nous avons également besoin d’une fonction nous permettant de savoir si la tuile à une position donnée est spécifiquement une plate-forme à sens unique:

public bool IsOneWayPlatform (int x, int y) if (x < 0 || x >= mWidth || y < 0 || y >= mHeight) renvoie false; return (tiles [x, y] == TileType.OneWay); 

Enfin, nous devons changer Map.IsGround revenir vrai si une tuile est soit un bloc solide ou une plate-forme à sens unique:

public bool IsGround (int x, int y) if (x < 0 || x >= mWidth || y < 0 || y >= mHeight) renvoie false; return (tiles [x, y] == TileType.OneWay || tiles [x, y] == TileType.Block); 

C'est la partie de la carte du code triée; maintenant nous pouvons travailler sur le pathfinder lui-même.

Ajout de nouvelles conditions de filtrage de nœud

Nous devons également ajouter deux nouvelles conditions de filtrage de nœuds à notre liste. Rappelez-vous, notre liste ressemble actuellement à ceci:

  1. C'est le noeud de départ.
  2. C'est le noeud final.
  3. C'est un noeud de saut.
  4. Il s’agit du premier noeud en vol d’un saut latéral (un noeud dont la valeur de saut est égale à 3).
  5. C’est le noeud d’atterrissage (un noeud qui avait une valeur de saut non zéo devient 0).
  6. C'est le point culminant du saut (le nœud entre monter et descendre et descendre).
  7. C'est un nœud qui contourne un obstacle.

Nous voulons ajouter ces deux conditions:

  • Le nœud est sur une plate-forme à sens unique.
  • Le nœud est au sol et le nœud précédent était sur une plate-forme à sens unique (ou inversement).

Y compris les nœuds qui sont des plates-formes à sens unique

Le premier point: nous voulons toujours inclure un noeud si c'est sur une plate-forme à sens unique:

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

Inclure les nœuds de terre si le nœud précédent était une plate-forme à sens unique

Le deuxième point: nous devons inclure un nœud s'il est au sol et si le nœud précédent est sur une plate-forme à sens unique:

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

Tous ensemble, alors…

Voici une liste actualisée des conditions de filtrage des noeuds. l'algorithme laissera passer tout nœud qui remplit l'une des conditions suivantes:

  1. C'est le noeud de départ.
  2. C'est le noeud final.
  3. Le nœud est sur une plate-forme à sens unique.
  4. Le nœud est au sol et le nœud précédent était sur une plate-forme à sens unique (ou inversement).
  5. C'est un noeud de saut.
  6. Il s’agit du premier noeud en vol d’un saut latéral (un noeud dont la valeur de saut est égale à 3).
  7. C’est le noeud d’atterrissage (un noeud qui avait une valeur de saut non nulle devient 0).
  8. C'est le point culminant du saut (le nœud entre monter et descendre et descendre).
  9. C'est un nœud qui contourne un obstacle.

Et voici le code vérifiant toutes ces conditions:

if ((mClose.Count == 0) || (mMap.IsOneWayPlatform (fNode.x, fNode.y - 1)) || (mGrid [fNode.x - f]. (fPrevNode.x, fPrevNode.y -1)) || (fNodeTmp.JumpLength == 3) || == 0 && fPrevNodeTmp.JumpLength! = 0) // marquer les atterrissages || (fNode.y> mFermer [mFerme.Compte - 1] .y && fNode.y> fNodeTmp.PY) || < 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);

À quoi ressemble le filtrage avec les plates-formes à sens unique

Enfin, voici un exemple de filtrage avec des plates-formes à sens unique.

Conclusion

C'est tout ce qu'on peut en dire! C'est un ajout simple, vraiment. Dans le prochain didacticiel de cette série, nous ajouterons une extension légèrement plus compliquée (mais toujours assez simple), permettant à l'algorithme de recherche de chemin de traiter des caractères plus grands que des blocs 1x1..