Ich schreibe gerade eine 2D-KI-Simulation, bin mir aber nicht ganz sicher, wie ich überprüfen soll, ob sich die Position eines Agenten im Sichtfeld eines anderen Agenten befindet.
Derzeit ist meine Weltpartitionierung eine einfache Zellraumpartitionierung (ein Raster). Ich möchte ein Dreieck verwenden, um das Sichtfeld darzustellen, aber wie kann ich die Zellen berechnen, die sich mit dem Dreieck schneiden?
Ähnlich wie bei diesem Bild:
Die roten Bereiche sind die Zellen, die ich berechnen möchte, indem überprüft wird, ob das Dreieck diese Zellen schneidet.
Danke im Voraus.
BEARBEITEN:
Nur um die Verwirrung zu verstärken (oder es vielleicht sogar einfacher zu machen). Jede Zelle hat einen Min- und Max-Vektor, wobei Min die untere linke Ecke und Max die obere rechte Ecke ist.
quelle
Antworten:
Berechnen Sie die drei Ecken Ihres Fov-Dreiecks, drehen Sie sie so, dass sie in die richtige Richtung weisen, und führen Sie dann einen der folgenden Schritte aus:
1) Führen Sie einen Punkt-in-Dreieck-Test für alle potenziellen Ziele durch
2) Berechnen Sie den Begrenzungsrahmen dieses Dreiecks und führen Sie einen Punkt-in-Dreieck-Test für alle potenziellen Ziele in Zellen in diesem Begrenzungsrahmen durch. Dies ist ein sehr einfacher Code zum Debuggen
Ein ähnlicher Ansatz besteht darin, einen Quadtree anstelle eines Gitters zu verwenden und die Schnittpunkte darauf zu erstellen. Wenn der Zugriff auf die O (1) -Kachel Sie beschleunigt, sollte es so schnell wie möglich sein, alle Zellen in den Grenzen des Fov-Dreiecks auf In-Dreieck zu testen. Wenn Sie sich andere Optionen ansehen, gehe ich davon aus, dass dies nicht der Fall ist und dass O (1) tatsächlich massive Cache-Fehlkosten verursacht, wenn Sie Ihren Cache verprügeln. Sie können sich natürlich auch die Anweisungen zum Vorabrufen ansehen, um Ihren Begrenzungsrahmen-Spaziergang mit ...
3) "rastern" Sie dieses Dreieck und überprüfen Sie die Zellen, die es "malt" - wahrscheinlich der effizienteste Code, aber vielleicht nur am Rande, da ich spekulieren würde, dass alles von Cache-Fehlzeiten dominiert wird und davon abhängt, wie komplex Ihre Zellen sind und wie beschäftigt Sie sind.
Ein alternativer Ansatz besteht darin, das Sichtfeld in eine Bitmap außerhalb des Bildschirms zu rendern und dann den Pixelwert für jedes Ihrer Objekte zu lesen. Sie können Farbe nicht „entmischen“, aber mit einer begrenzten Anzahl von Objekten. Durch sorgfältige Auswahl Ihrer Farbe können Sie ableiten, wer wen gesehen hat. Dieser Ansatz ähnelt der Anzahl der Spiele, auf die der Benutzer geklickt hat. Er zeichnet die Szene außerhalb des Bildschirms mit Volltonfarben für die Trefferbereiche. GPUs sind bei Dreiecksfüllung sehr schnell ...
quelle
Die kanonische Lösung in Software-Renderern (die genau diesen Algorithmus jedes Mal ausführen müssen, wenn sie ein Dreieck rastern) besteht meines Erachtens darin, das Dreieck jeweils eine Pixelreihe zu scannen. Der linke und der rechte Rand jeder Reihe werden berechnet, indem Sie mit Bresenham die Seiten des Dreiecks hinuntergehen und dann die Reihe zwischen ihnen ausfüllen.
Ich beschönige viele Details, aber das ist die Grundidee. Wenn Sie nach "Software-Rendering" und "Dreieck-Rasterisierung" suchen, werden Sie wahrscheinlich weitere Details finden. Dies ist ein gut gelöstes Problem. Ihre Grafikkarte macht dies millionenfach pro Frame.
Wenn Sie eine roguelike-spezifischere Lösung wünschen, habe ich FOV in meiner implementiert. Es scheint ziemlich schnell zu funktionieren. Es handelt sich im Wesentlichen um einen einfachen Schattenwirker, der jeweils an einem Oktanten arbeitet und vom Player nach außen scannt.
quelle
Ich verwende eine Variation des Scanline-Algorithmus, um genau das gleiche Problem zu lösen. Ich begann damit, die drei Dreieckspunkte nach ihrer Höhe zu sortieren. Ich überprüfe dann grundsätzlich, ob zwei Kanten links oder rechts sind. Für die Seite mit zwei Kanten müssen Sie die Zeile markieren, in der Sie ändern, welche Kante Ihre Zeilen begrenzt. Für die Seite mit einer Kante können Sie diese einfach immer verwenden.
Dann weiß ich für jede Zeile, welche zwei Kanten sie begrenzen, und ich kann die oberen und unteren Grenzen in x-Richtung berechnen. Es klingt ziemlich kompliziert, aber es reduziert sich auf nur wenige Codezeilen. Stellen Sie sicher, dass Sie den Sonderfall behandeln, bei dem eine Kante vollständig horizontal ist!
quelle
Wie wäre es, einen Spaltenbereich für jede Zeile im Dreieck beizubehalten? Sie können die Min- und Max-Spalte für jede Zeile festlegen, in der sich jeder Punkt befindet und in der jede Dreieckslinie eine horizontale Zeilentrennlinie kreuzt.
Ausgabe:
quelle
In der Roguelike-Community gibt es einige Algorithmen, die sich mit FOV / LOS / Beleuchtung in einer kachelbasierten Welt befassen.
Vielleicht finden Sie auf dieser Seite etwas, mit dem Sie Ihr Problem lösen können: http://roguebasin.roguelikedevelopment.org/index.php?title=Field_of_Vision
Insbesondere "Zulässiges Sichtfeld" ist möglicherweise am besten für Ihre Situation geeignet.
quelle