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?
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?
Antworten:
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.
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 a
bis 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.
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)
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.