PyGame QIX-Klon, der Bereiche füllt


8

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.

Geben Sie hier die Bildbeschreibung ein

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). .


Vielleicht gibt es einige Antworten hier (ähnliche Frage): gamedev.stackexchange.com/questions/26377/...
tigrou

Danke, aber der Link zeigt primitive Anwendungsfälle. Ich habe meine Frage aktualisiert, also ist es vielleicht klarer, was ich zu erreichen versuche
astropanisch

Antworten:


5

So würde ich es angehen:

  1. Es gibt immer einen einzelnen offenen Bereich, der durch ein Polygon dargestellt wird. Alle anderen Bereiche sind irrelevant.
  2. Eine Linie beginnt, wenn Sie sich vom Umfang des Polygons in das Innere des Polygons bewegen.
  3. Eine Linie stoppt, wenn Sie sich vom Inneren des Polygons zurück zum Umfang bewegen.
  4. Wenn Sie die Linie anhalten, haben Sie das Polygon in zwei Polygone unterteilt.
  5. Sie entscheiden dann, welches der beiden Polygone gefüllt und welches als offener Bereich beibehalten werden soll. In Qix blieb die Seite, auf der sich der Qix (Feind) befand, offen und die andere Seite war gefüllt.

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 Startpunkt Aliegt zwischen p1und p2und Ihr Endpunkt Bliegt zwischen p3und p4. 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.


1

Dies ist ein Problem, das mehrere diskrete Teilschritte umfasst. Hier ist ein Überblick über das, was ich vorschlagen würde:

  • Warten Sie, bis der Spieler einen Schnittpunkt mehrerer Linien bildet
  • Holen Sie sich ein Pixel von jeder Seite der Kreuzung
  • Pathfind, um zu sehen, ob sie sich miteinander verbinden können
  • Pixel, die keine Verbindung herstellen können, sind separate Bereiche
  • Führen Sie eine Flutfüllung durch, um alle Pixel im Bereich zu erhalten

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:

. . . | . 
. . . | . 
. . . | x 
. . x < -

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:

  • Fügen Sie alle leeren Pixel neben dem Player / der Kreuzung zu einer Liste hinzu.
  • Durchlaufen Sie die Liste und entfernen Sie Pixel, wenn das nächste Element in der Liste (im Spielfeld) neben dem Element liegt, auf dem Sie sich befinden.

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!


0

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


1
Es ist kein Problem mit Triangulation, PyGame kümmert sich darum. Ich habe meine Frage mit einem Bild aktualisiert und in einigen Anwendungsfällen einen Blick darauf geworfen, damit Sie den Punkt verstehen.
Trotzdem
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.