Pfadfindung im Raster für Objekte, die mehr als eine Kachel belegen

7

In einem gitterbasierten Spiel, an dem ich arbeite, möchte ich Objekte hinzufügen, die mehr als eine Kachel des Gitters belegen. Gibt es Algorithmen oder Techniken, um Pfade für diese Art von Objekten zu finden?

miguelSantirso
quelle

Antworten:

5

Im Allgemeinen passen Sie vorhandene Pfadfindungsalgorithmen an die Breite an. In erster Linie bedeutet dies, A * anzupassen. Da Ihr Spiel jedoch gitterbasiert ist , kann der Algorithmus zum Lösen von Fettlabyrinthen hilfreich sein.

Für A * besteht die grundlegendste Lösung darin, Ihren Berechnungen gemäß Ihren Bewegungsregeln einfach eine Aussage zur Breite hinzuzufügen. Dies führt jedoch zu einem Durcheinander Ihres Pfadfindungscodes und verlangsamt die Pfadfindung für Entitäten normaler Größe.

Alternativ können Sie Ihr Raster als knotenbasiertes Pfadfindungsnetzwerk betrachten. Für Ihre größeren Entitäten können Sie ein sekundäres Netzwerk erstellen, das deren Größe berücksichtigt, und dieses für die Bewegung und Pfadfindung verwenden. Dies hat den Vorteil, dass Sie Ihre Pfadfindung für größere Entitäten so anpassen können, dass sie sich wie erwartet verhält. Sie müssen jedoch mehrere Karten für jede Szene erstellen und im Speicher behalten, was sich auf Spiele auf mobilen Plattformen auswirken kann.

Wenn keine dieser Methoden Ihren Zwecken entspricht, können Sie nach Inspiration für Navigationsnetz- Pfadfindungsalgorithmen suchen , die von Natur aus breitheitsbewusst sind.

Keeblebrox
quelle
6

Eine Möglichkeit wäre, ein zweites Gitter zu berechnen, das die Größe des Objekts berücksichtigt, indem es wie folgt auf das Gitter "gemalt" wird. Hier ist das ursprüngliche Raster:

#########
#..b....#
#.#.....#
#.####..#
#.......#
#.......#
#..#.#..#
#a.#.#..#
#########

Wir wollen sehen, ob ein 2x2-Objekt von abis kommen kann b. Wir berechnen ein zweites Gitter, in dem wir jedes Mal, wenn wir eine Wand haben ( #), darüber und links davon Wände hinzufügen ( x) und jedes einzelne Wandsegment in ein 2x2-Segment verwandeln. Jetzt sieht es so aus:

xxxxxxxxxx
x#########
x#xxb...x#
x#x#xxx.x#
x#x####.x#
x#......x#
x#.xxxx.x#
x#.x#x#.x#
x#ax#x#xx#
x#########

Wir können dann in diesem Raster einen Pfad finden, indem wir das Objekt als 1x1 behandeln, da das Raster selbst seine Größe berücksichtigt.

großartig
quelle
1
Ich mag diese Option nicht sehr, weil ich für jede Objektgröße ein anderes Gitter erstellen müsste ...
miguelSantirso
@miguelSantirso: Nein, Sie müssen nur einen breiten verfügbaren Wert für jede Kachel angeben. Angenommen, Sie haben mehrere Kachelgrößen und ein kleineres Maximum, kann dies sogar ein Bitfeld sein, das angibt, ob jede Größe auf jedes Quadrat passt.
Jack Aidley
0

Sie können die Antwort von munificent erweitern, um ein einzelnes Stützgitter zu speichern. Anstatt die Passierbarkeit für jede unterschiedliche Objektgröße zu speichern, wird ein Entfernungsfeld gespeichert, in dem die Anzahl der Halbkachelbreiten zwischen diesem Standort und der nächstgelegenen Barriere aufgezeichnet wird. (Oder alternativ die Breite des größten Objekts, das auf dieser Kachel zentriert werden kann, ohne etwas zu treffen)

  • Eine Wandfliese hat einen Abstand von -1 (die Mitte dieser Fliese befindet sich innerhalb des Hauptteils der Wand).
  • Eine Fliese, die an mindestens einer Seite an eine Wand angrenzt, hat einen Abstand von 1 (eine halbe Fliese trennt die Mitte dieser Fliese vom Rand der nächsten Wand).
  • Eine Fliese ohne angrenzende Wände, die an eine Fliese angrenzt, die an eine Wand angrenzt, hat einen Abstand von 3 (eine volle Fliesenbreite, um die Mitte des Nachbarn zu erreichen, und eine halbe Fliese von dort bis zur Wand).

Sie können dieses Raster füllen, indem Sie die Karte mit einer Ganzzahl initialisieren, die größer als Ihre Kartengröße in leeren Räumen und -1 an Wandstandorten ist. Setzen Sie dann iterativ jede Kachel> 0 auf das Minimum ihrer Nachbarn plus zwei.

Jetzt ersetzen Sie in Ihrem Pfadfindungsalgorithmus

if (!IsPassable(PassabilityMap[x, y])) continue;

mit

if (DistanceToObstacleMap[x, y] < pathfindingAgent.size) continue;

Jetzt können Sie die Pfadfindung für jede Einheitsgröße mit einer einzigen Karte durchführen, und das Speichern / Überprüfen der Passierbarkeit bleibt hinsichtlich der Kosten mit dem Fall eines Bools pro Kachel vergleichbar.

DMGregory
quelle