Diagonale Sichtlinie mit zwei Ecken

9

Im Moment verwende ich Bresenhams Linienalgorithmus für die Sichtlinie. Das Problem ist, dass ich einen Randfall gefunden habe, in dem Spieler durch Wände schauen können. Tritt auf, wenn der Spieler in bestimmten Winkeln zwischen zwei Ecken einer Wand mit einer Lücke auf der anderen Seite schaut.

Sichtlinienkantenfall

Das gewünschte Ergebnis ist, dass die Kachel zwischen zwei Wänden als ungültig markiert wird.

Erwünschtes Ergebnis

Was ist der schnellste Weg, um den Linienalgorithmus von Bresenham zu modifizieren, um dies zu lösen? Wenn es keine gute Lösung gibt, gibt es einen besser geeigneten Algorithmus? Ideen sind willkommen. Bitte beachten Sie, dass die Lösung auch 3D unterstützen sollte.

Bearbeiten: Meine einfache Lösung bestand darin, zu überprüfen, ob beide Ecken geschlossen sind, wenn sich die x- und y-Koordinaten einer Linie ändern. Den funktionierenden Quellcode und eine interaktive Demo des fertigen Produkts finden Sie unter http://ashblue.github.io/javascript-pathfinding/.

Aschblau
quelle
2
Macht es einen Unterschied, ob Sie den Start- und Endpunkt wechseln? Vielleicht könnten Sie dann einfach Ergebnisse akzeptieren, wenn beide Berechnungen eine ungehinderte Sichtlinie zurückgeben. Möglicherweise finden Sie auch einige der LOS-Artikel bei RogueBasin hilfreich.
Thalador
1
In beiden Fällen sind diese beiden schwarzen Blöcke mit einer Diagonale von 4 bis 5 überhaupt nicht mit einer Wand verbunden, und ich sage dies, weil Sie implizit eine diagonale Bewegung zulassen. Sie müssen diese Diagonale entweder abrunden, um sie zu einer zusammenhängenden Wand zu machen, oder Ihren Linienläufer von seinen diagonalen Bewegungen abrunden, anstatt wie 2-3 und 4-5 rein diagonal zu gehen.
Patrick Hughes
Das Umdrehen klang nach einer guten Idee, löst das Problem jedoch nicht. Ich kann mir nur vorstellen, zu überprüfen, ob eine der beiden Ecken leer ist. Scheint aber teuer.
Ash Blue
5
"Scheint teuer" ist nie genug, um etwas nicht auszuprobieren. "Wird zu teuer sein" ist im Allgemeinen, vorausgesetzt, Sie können beweisen, dass etwas zu langsam sein wird.
Mokosha
3
Die einzige Änderung des erforderlichen Algorithmus besteht darin, dass, wenn sich sowohl X als auch Y im selben Schritt ändern, zuerst X und dann Y geändert werden, dies die Diagonalen insgesamt eliminieren würde.
Patrick Hughes

Antworten:

7

Eric Lippert hat eine exzellente Serie über die Erzeugung von Sichtlinien in C # mit Shadow Casting auf einem rechteckigen planaren Gitter geschrieben.

Eric befasste sich unter anderem mit verschiedenen Fragen, die zu den Anforderungen an die Sichtlinie beantwortet werden müssen, die unterschiedliche Ergebnisse liefern, und gibt Beispiele für einige unterschiedliche Ergebnisse. Einer der Artikel befasst sich ausführlich mit einem Umstand, dass er um die Ecke schaut und in einer frühen Version seines Algorithmus aufgetreten ist.

Ich habe Eric-Algorithmus auf einem hexagonalen Gitter angepasst hier , und es erfolgreich auf großen hexagonalen Gitter verwendet (> 400 x 700) mit einer umfangreichen Sichtbarkeit Radius (> 60 Flüche). Diese Implementierung berechnet und zeigt das vollständige Sichtfeld so schnell ich kann mit einer einzigen i7-CPU an. Dies ist sicherlich schnell genug für alle Verwendungszwecke, die ich erwartet habe.

Update - Sichtlinie mit Höhe:
Die oben verknüpfte Hex-Grid-Implementierung berechnet die Sichtlinie mit Höhe, nicht nur Hindernissen. In den Dokumentationsnotizen wird auch eine zusätzliche Entscheidung erörtert, die in Bezug auf die Höhenberechnungen getroffen werden muss: Die Zielhöhe und die Beobachterhöhe. Die Standardauswahl besteht darin, beide gleich zu machen, wodurch ein symmetrisches Sichtfeld erzeugt wird. Es können jedoch auch Boden-Boden- und Beobachteraugen-Boden ausgewählt werden. (Der Code ist Open Source unter MIT-Lizenz)

Pieter Geerkens
quelle
Ich grabe wirklich Shadow Casting, aber ich bin auf ein Problem gestoßen. Probleme beim Finden von Informationen zum Skalieren des Algorithmus für den Betrieb mit einer Z-Achse. Tut mir leid, das zu erwähnen, aber haben Sie Ressourcen vorgeschlagen, damit es in 3D funktioniert?
Ash Blue
@ AshBlue: siehe Anhang oben
Pieter Geerkens
Ich schaue auf deine Codebasis. Es enthält großartige Dinge, aber ich finde anscheinend keinen Bresenham-ähnlichen Strichzeichnungsalgorithmus, der an Hexen angepasst ist. Machst du es mit LOS?
MLProgrammer-CiM
@EfEs: FieldOfView ist das zurückgegebene Objekt. ShadowCastingFov * .cs generiert das Sichtfeld durch Werfen von Schatten. Wenn Sie spezielle Fragen zum Code haben, werden diese möglicherweise am besten im Abschnitt "Diskussionen" der Website gestellt. allgemeinere Fragen beantworte ich gerne hier.
Pieter Geerkens
@PieterGeerkens können Sie die Frage finden hier gamedev.stackexchange.com/questions/57087/...
MLProgrammer-CiM
1

Was ist, wenn Sie für die LOS-Berechnung ein separates Raster mit höherer Auflösung haben, das die Ecklücken ausfüllt? Ich dachte so etwas:

Geben Sie hier die Bildbeschreibung ein

Das linke ist der ursprüngliche Blockabschnitt von 4 Quadraten.

Das rechte ist die "hochauflösende" Version, da Sie sehen können, dass jedes ursprüngliche Quadrat in Viertel unterteilt wurde und eine der Ecken ausgefüllt wurde. Ich bin mir nicht sicher, ob der Algorithmus dies sofort generiert, aber er kann vorberechnet werden von der aktuellen Karte.

Es bedeutet zwar, dass sich der Koordinatenraum vervierfacht, aber ich kann mir nicht vorstellen, dass dies ein erhebliches Leistungsproblem darstellt.

Davy8
quelle
Ziemlich sicher, dass die höhere Auflösung genauso aussehen würde wie das Original. Wenn Sie ein Raster in ein kleineres Raster unterteilen, erhalten Sie dieselbe visuelle Darstellung, nur mit einem kleineren Raster. Jedes einzelne Quadrat wird nur zu 4 kleineren Quadraten an derselben Stelle.
MichaelHouse
@ Byte56 Richtig, ich meinte, dass nach dem Teilen zusätzliche Logik angewendet wird, um die zusätzlichen Blöcke zu dieser Kopie hinzuzufügen. Die Logik dazu ist eine Übung, die dem Leser überlassen bleibt.
Davy8
Sie können das hochauflösende Raster leicht erzeugen, indem Sie das Original verwischen. Definieren Sie dann einen Schwellenwert von beispielsweise, ob 0.5hochauflösende Zellen gefüllt werden sollen oder nicht. Daher fühlt sich die Verwendung eines hochauflösenden Gitters für mich überhaupt ziemlich hackig an.
Danijar