Ich spiele mit PyGame herum.
Jetzt versuche ich, einen QIX- Klon zu implementieren .
Ich habe meine Spielschleife und kann den Spieler (Cursor) auf dem Bildschirm bewegen.
In QIX hinterlässt die Bewegung des Players eine Spur (Schwanz) auf dem Bildschirm, wodurch eine Polylinie erstellt wird.
Wenn die Polylinie mit den Bildschirmgrenzen ein Polygon erstellt, wird der Bereich gefüllt.
Wie kann ich dieses Verhalten erreichen?
Wie speichere ich den Schwanz im Gedächtnis?
Wie erkennt man, wann eine geschlossene Form entsteht, die gefüllt werden soll?
Ich brauche keine exakte funktionierende Lösung, einige Hinweise, Algo-Namen wären cool.
Zu Beginn gibt es nur den grauen Rand, an dem der Spieler seinen Cursor bewegen kann.
- Erstes Szenario:
Der Benutzer bewegt seinen Cursor von Punkt A durch Punkt B und zeichnet die rote Mehrfachlinie bis Punkt C. An diesem Punkt sollte der Punkt A aufgrund des Grenzübertritts automatisch mit Punkt C verbunden werden, wodurch ein Polygon erstellt wird, das gefüllt werden sollte ( das orangefarbene Zeug auf meiner Zeichnung). Das Füllen des Polygons ist in PyGame verdammt einfach, da ich die Folge von Punkten gebe und PyGame sich um den Rest kümmert.
- Zweites Szenario:
Der Benutzer bewegt sich am Rand zu Punkt D, von wo aus er eine Linie zu Punkt E zeichnet. Da er die Linie des vorherigen Polygons kreuzt und mit seinen Linien und dem Rand ein weiteres Polygon erstellt werden kann, sollte es ebenfalls gefüllt werden. (der Grüne).
- Drittes Szenario:
Der Spieler bewegt sich weiter auf dem Polygon (er kann sich auf vorhandenen Polygonlinien bewegen) und zeichnet eine Linie von Punkt G zu Punkt F. Auch hier sollte aufgrund des Rahmens und der vorhandenen Linien ein anderes Polygon gefüllt werden (das blaue). .
Antworten:
So würde ich es angehen:
Wie unterteilen Sie das Polygon? Sie verwenden die Endpunkte Ihrer Linie, um den Polygonumfang in zwei Abschnitte zu unterteilen, und verwenden dann die neue Linie, um diese beiden Abschnitte in neue Polygone zu vervollständigen.
Angenommen, Ihr offener Bereich ist ein Polygon mit Punkten
[p0, p1, p2, p3, p4, p5]
. Ihr StartpunktA
liegt zwischenp1
undp2
und Ihr EndpunktB
liegt zwischenp3
undp4
. Die neue Linie, die gezeichnet wurde, ist[A, s, t, u, v, B]
. Wir teilen zuerst das Polygon in zwei Segmente[A, p2, p3, B]
und[B, p4, p5, p0, p1, A]
. Diese beiden Segmente bilden zusammen das ursprüngliche Polygon. Dann kleben wir die neue Linie in jede (einmal vorwärts, einmal rückwärts), formen[A, p2, p3, B, v, u, t, s]
und[B, p4, p5, p0, p1, A, s, t, u, v]
. Sie füllen eines dieser Polygone und behalten das andere als neuen offenen Bereich.Ich habe dies nicht implementiert und weiß nicht genau, ob es funktionieren wird, aber das ist der Ansatz, den ich verwenden würde: Polygonunterteilung anstelle von Polygonfüllung.
quelle
Dies ist ein Problem, das mehrere diskrete Teilschritte umfasst. Hier ist ein Überblick über das, was ich vorschlagen würde:
Ich würde den Status der Pixel des Spiels in einem Numpy-Array (numpy dot scipy dot org) speichern. Die Farbe könnte drei separate Arrays für RGB sein, aber das Array, auf das ich mich konzentrieren werde, ist das Line / No Line-Array. Initialisieren Sie es einfach mit Nullen und stellen Sie es auf die Größe Ihres Spielfelds ein. Setzen Sie jedes Mal, wenn der Spieler ein Pixel durchläuft, das entsprechende Element im Array auf 1. Sie möchten diese auf dem Bildschirm in einer anderen Farbe anzeigen , wie sie deine Linie sind!
Jedes Mal, wenn sich das Player-Pixel bewegt, überprüfe ich, ob es eine vorhandene Linie passiert (und eine Linie daneben gezogen hat). Wenn ja, würde ich von jeder möglichen Unterteilung ein Pixel erhalten:
Punkte sind leere Pixel, Linien sind (offensichtlich) Linien und Xs sind die leeren Pixel, die wir auswählen möchten. Wir können dies auf folgende Weise tun:
Wenn Sie Pixel von allen möglichen Seiten der Kreuzung haben, führen Sie A * für jedes mögliche Paar aus. ( Weitere Informationen finden Sie unter http://www-cs-students.stanford.edu/~amitp/gameprog.html#paths oder bei Google a-star.) Wenn zwischen einem Paar ein Pfad gefunden werden kann, entfernen Sie eines der verbundenen Pixel von der Liste.
Nach dem Schleifen und Pfaden für alle Paare sollten sich die verbleibenden Pixel jeweils in einem separaten, geschlossenen Bereich befinden! Um alle Pixel in jedem Bereich zu erhalten, führen Sie eine Flutfüllung aus den Pixeln dieses Bereichs durch. Siehe http://en.wikipedia.org/wiki/Flood_fill .
Viel Glück!
quelle
Ihre Bereiche sind nur eine Reihe von Punkten. Die harte Arbeit besteht darin, die Reihe von Punkten, die (normalerweise) ein konkaves Polygon bilden, zu nehmen und zu triangulieren, damit Sie eine Textur rendern und wahrscheinlich darauf projizieren können. Weitere Informationen finden Sie unter http://en.wikipedia.org/wiki/Polygon_triangulation
quelle