Clone di PyGame QIX, aree di riempimento


8

Sto giocando con PyGame.

Ora sto cercando di implementare un clone QIX .

Ho il mio loop di gioco e posso spostare il giocatore (cursore) sullo schermo.

In QIX, il movimento del giocatore lascia una traccia (coda) sullo schermo, creando una polilinea.

Se la polilinea con i bordi dello schermo crea un poligono, l'area viene riempita.

Come posso realizzare questo comportamento?

Come conservare la coda in memoria?

Come rilevare quando crea una forma chiusa che dovrebbe essere riempita?

Non ho bisogno di una soluzione di lavoro esatta, alcuni puntatori, i nomi degli algo sarebbero fantastici.

inserisci qui la descrizione dell'immagine

All'inizio, c'è solo il bordo grigio, in cui il giocatore può muovere il cursore.

  • Primo scenario:

L'utente sposta il cursore dal punto A al punto B, disegnando la multilinea rossa fino al punto C. A questo punto, a causa dell'attraversamento del bordo, il punto A dovrebbe essere collegato automaticamente al punto C, creando un poligono, che dovrebbe essere riempito ( quella roba arancione sul mio disegno). Riempire il poligono è dannatamente semplice in PyGame, perché fornisco la sequenza di punti e PyGame si prende cura di tutto il resto.

  • Secondo scenario:

L'utente si sposta sul bordo fino al punto D, da dove disegna una linea al punto E. Poiché sta attraversando la linea del poligono precedente, e con le sue linee e il bordo può essere creato un altro poligono, dovrebbe essere riempito anche. (quello verde).

  • Terzo scenario:

Il giocatore si sposta ulteriormente sul poligono (può muoversi su linee poligonali esistenti) e disegna una linea dal punto G al punto F. Anche in questo caso, a causa del bordo e delle linee esistenti, un altro poligono dovrebbe essere riempito (quello blu) .


Forse ci sono alcune risposte qui (domanda simile): gamedev.stackexchange.com/questions/26377/…
tigrou,

Grazie, ma il link mostra casi d'uso primitivi. Ho aggiornato la mia domanda, quindi forse è più chiaro cosa cerco di realizzare
astropanico

Risposte:


5

Ecco come mi avvicinerei:

  1. C'è sempre un'unica area aperta, rappresentata da un poligono. Tutte le altre aree sono irrilevanti.
  2. Una linea inizia quando ci si sposta dal perimetro del poligono all'interno del poligono.
  3. Una linea si interrompe quando ci si sposta dall'interno del poligono sul perimetro.
  4. Quando interrompi la linea, hai diviso il poligono in due poligoni.
  5. Decidi quindi quale dei due poligoni deve riempire e quale mantenere come area aperta. A Qix, il lato su cui si trovava il Qix (nemico) rimase aperto e l'altro lato fu riempito.

Come si suddivide il poligono? Usa gli endpoint della tua linea per dividere il perimetro poligonale in due sezioni, quindi usa la nuova linea per completare quelle due sezioni in nuovi poligoni.

Ad esempio, supponiamo che l'area aperta sia un poligono con punti [p0, p1, p2, p3, p4, p5]. Il punto iniziale Asi trova tra p1e p2e il punto finale Bsi trova tra p3e p4. La nuova linea che è stata disegnata è [A, s, t, u, v, B]. Dapprima abbiamo diviso il poligono in due segmenti [A, p2, p3, B]e [B, p4, p5, p0, p1, A]. Questi due segmenti insieme formano il poligono originale. Quindi incolliamo la nuova linea in ciascuna (una volta in avanti, una volta all'indietro), formando [A, p2, p3, B, v, u, t, s]e [B, p4, p5, p0, p1, A, s, t, u, v]. Riempi uno di questi poligoni e tieni l'altro come nuova area aperta.

Non l'ho implementato e non so per certo se funzionerà, ma questo è l'approccio che userei: suddivisione poligonale anziché riempimento poligono.


1

Questo è un problema che coinvolge più passaggi secondari discreti. Ecco uno schema di ciò che suggerirei:

  • Aspetta che il giocatore formi un incrocio di più linee
  • Ottieni un pixel da ciascun lato dell'intersezione
  • Pathfind per vedere se riescono a connettersi l'un l'altro
  • I pixel che non possono connettersi tra loro sono aree separate
  • Eseguire un riempimento per ottenere tutti i pixel nell'area

Vorrei memorizzare lo stato dei pixel del gioco in un array Numpy (numpy dot scipy dot org). Il colore potrebbe essere tre array separati per RGB, ma l'array su cui mi concentrerò è l'array line / no line. Basta inizializzarlo con zeri e impostarlo sulla dimensione del campo di gioco, e ogni volta che il giocatore passa attraverso un pixel, imposta l'elemento corrispondente nell'array su 1. Ti consigliamo di visualizzarli sullo schermo con un colore diverso , poiché sono la tua linea!

Ogni volta che il pixel del giocatore si sposta, vorrei verificare se ha superato (e tracciato una linea accanto) una linea esistente. In tal caso, otterrei un pixel da ogni possibile divisione:

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

I punti sono pixel vuoti, le linee sono (ovviamente) linee e le X sono i pixel vuoti che vogliamo selezionare. Possiamo farlo nel modo seguente:

  • Aggiungi tutti i pixel vuoti adiacenti al giocatore / intersezione a un elenco.
  • Scorri l'elenco rimuovendo i pixel se l'elemento successivo nell'elenco è adiacente (nel campo di gioco) a quello in cui ti trovi.

Una volta che hai pixel da tutti i lati possibili dell'intersezione, esegui A * su ogni possibile coppia. (Vedi http://www-cs-students.stanford.edu/~amitp/gameprog.html#paths o Google a-star per ulteriori informazioni.) Se è possibile trovare un percorso tra una coppia, rimuovere uno dei pixel collegati dall'elenco.

Dopo il looping e il pathing per tutte le coppie, i pixel rimanenti dovrebbero trovarsi ciascuno in un'area separata e chiusa! Per ottenere tutti i pixel in ciascuna area, esegui un riempimento di riempimento dal pixel di quell'area. Vedi http://en.wikipedia.org/wiki/Flood_fill .

In bocca al lupo!


0

Le tue aree sono solo una serie di punti. Il duro lavoro consiste nel prendere la serie di punti che formano (di solito) un poligono concavo e triangolarli in modo da renderli e probabilmente proiettare su di essi una trama. Vedi http://en.wikipedia.org/wiki/Polygon_triangulation per maggiori dettagli


1
non è un problema con la triangolazione, PyGame se ne occupa. Ho aggiornato la mia domanda con un'immagine e, in alcuni casi d'uso, dai un'occhiata in modo da ottenere il punto. Grazie comunque
astropanico il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.