Ich habe eine Matrix aus Kacheln, auf einigen dieser Kacheln befinden sich Objekte. Ich möchte berechnen, welche Kacheln für den Spieler sichtbar sind und welche nicht, und ich muss es sehr effizient ausführen (damit es schnell genug berechnet werden kann, selbst wenn ich große Matrizen (100x100) und viele Objekte habe).
Ich habe versucht, es mit Bresenhams Linienalgorithmus zu machen , aber es war langsam. Außerdem gab es mir einige Fehler:
----XXX- ----X**- ----XXX-
-@------ -@------ -@------
----XXX- ----X**- ----XXX-
(raw version) (Besenham) (correct, since tunnel walls are
still visible at distance)
(@ is the player, X is obstacle, * is invisible, - is visible)
Ich bin mir sicher, dass dies möglich ist - schließlich haben wir NetHack, Zangband und alle haben sich irgendwie mit diesem Problem befasst :)
Welchen Algorithmus können Sie dafür empfehlen?
Für meine Bedürfnisse definiere ich sichtbar wie folgt: Plättchen ist sichtbar, wenn mindestens ein Teil (z. B. eine Ecke) des Plättchens mit einer geraden Linie, die kein Hindernis schneidet, mit der Mitte des Spielerplättchens verbunden werden kann.
quelle
Antworten:
Ihre Definition von Sichtbar lautet wie folgt:
Sie können dieses Konzept buchstäblich umsetzen, indem Sie die Strahlen von Ihrem Spielerplättchen verfolgen und sie mit Ihrer Szene schneiden. Sie brechen jede Iteration ab, sobald der Strahl auf ein Hindernis trifft (oder eine bestimmte Entfernungsschwelle überschreitet), da Sie nur an den Feldern interessiert sind, die der Spieler direkt sehen kann. Ich werde den Prozess für Sie abbrechen:
Hier ist ein Bild mit 3 Beispielstrahlen. Die dunkleren Kacheln sind das "Ergebnis" jedes Strahls, dh wo die Kollision stattgefunden hat. Sie müssen dies jedoch im gesamten Kreis wiederholen:
Stellen Sie den maximalen Abstand und die Anzahl der Strahlen für die Leistung ein. Zu wenig und Sie werden Fliesen verpassen, zu viel und Ihre Leistung wird leiden. Je weiter die Strahlen wandern müssen, desto größer wird der "Fehler" und desto präziser wird es.
Bearbeiten
Überprüfen Sie das folgende Tutorial zum Raycasting, insbesondere Schritt 3 und Schritt 4, um das Schnittbit des Algorithmus zu implementieren:
http://www.permadi.com/tutorial/raycast/rayc7.html
quelle
Ich würde lieber Schattenstrahlen als Sichtlinienstrahlen werfen.
Angenommen, dies ist Ihr Ansichtsbereich (der potenziell sichtbare Bereich).
Die # Blöcke sind nicht sichtbar, während die. sind sichtbar
Lassen Sie uns ein Hindernis setzen X:
Sie haben eine Liste der X, die sich im Ansichtsbereich befinden. Dann markieren Sie jedes Feld, das sich hinter jedem dieser Hindernisse befindet, als ausgeblendet. Wenn ein Hindernis als ausgeblendet markiert ist, entfernen Sie es aus der Liste.
Im obigen Beispiel können Sie sehen, wie der Schatten ganz rechts von der Bodenwand geworfen wird und wie dieser Schatten das verborgene Hindernis aus der Liste des zu prüfenden Hindernisses löscht (X muss prüfen; * markiert).
Wenn Sie die Liste mit einer Binär-Partition sortieren, so dass zuerst das cosest X geprüft wird, können Sie Ihre Prüfung etwas beschleunigen.
Sie können eine Art "Naval Battles" -Algorithmus verwenden, um einen Block von Xs auf einmal zu überprüfen (im Grunde suchen Sie nach einem benachbarten X in einer Richtung, die den Schattenkegel breiter machen kann).
[BEARBEITEN]
Es werden zwei Strahlen benötigt, um einen Schatten korrekt zu werfen. Da eine Kachel rechteckig ist, können viele Annahmen unter Verwendung der verfügbaren Symmetrien getroffen werden.
Die Strahlkoordinaten können mithilfe einer einfachen Raumaufteilung um das Hindernisplättchen berechnet werden:
Jeder rechteckige Bereich bestimmt, welche Ecke der Kachel als Schattenkegelkante verwendet werden soll.
Diese Überlegung kann weiter vorangetrieben werden, um mehrere benachbarte Kacheln zu verbinden und sie wie folgt einen einzelnen, breiteren Kegel werfen zu lassen.
Der erste Schritt besteht darin, sicherzustellen, dass sich keine Hindernisse in Richtung des Betrachters befinden. In diesem Fall wird stattdessen das nächste Hindernis berücksichtigt:
Wenn das gelbe Plättchen ein Hindernis ist, wird dieses Plättchen zum neuen roten Plättchen.
Betrachten wir nun die obere Kegelkante:
Die blauen Kacheln sind alle mögliche Kandidaten, um den Schattenkegel breiter werden zu lassen: Wenn mindestens eine von ihnen ein Hindernis ist, kann der Strahl unter Verwendung der Raumteilung um diese Kacheln wie zuvor gesehen bewegt werden.
Die grüne Kachel ist nur dann ein Kandidat, wenn sich der Beobachter über der folgenden orangefarbenen Linie befindet:
Gleiches gilt für den anderen Strahl und für die anderen Positionen des Betrachters zum roten Hindernis.
Die Grundidee besteht darin, für jeden Kegelwurf so viel Fläche wie möglich abzudecken und die Liste der zu überprüfenden Hindernisse so schnell wie möglich zu verkürzen.
quelle
Das Problem, das Sie zu lösen versuchen, wird manchmal als Sichtfeld, kurz FOV, bezeichnet. Wie Sie als Beispiel Roguelikes erwähnt haben, sollten Sie sich ansehen, was das RogueBasin-Wiki zu diesem Thema zu sagen hat (es gibt sogar Links zu Implementierungen): http://www.roguebasin.com/index.php?title=Field_of_Vision
Es gibt einige verschiedene Algorithmen mit unterschiedlichen Vor- und Nachteilen - ein sehr praktischer Vergleich ist auch bei RogueBasin verfügbar: http://www.roguebasin.com/index.php?title=Comparative_study_of_field_of_view_algorithms_for_2D_grid_based_worlds
quelle
Ich habe auch folgendes gefunden, das eine funktionierende Demo hat:
http://www.redblobgames.com/articles/visibility/
quelle
Sie könnten http://blogs.msdn.com/b/ericlippert/archive/2011/12/12/shadowcasting-in-c-part-one.aspx nützlich finden , zusammen mit dem Rest der Serie .
quelle