Schema comune per ridimensionare le "unità reali" in pixel?


10

Questa è una domanda di follow-up a quest'altra .

Vorrei sapere se esiste un modello comune / tipico / migliore per ridimensionare la mia rappresentazione del mondo (attualmente 160Kmx160Km) per adattarla all'area di disegno (attualmente 800x600 pixel).

Mi vengono in mente almeno quattro approcci diversi:

Uno ingenuo (il modo in cui l'ho fatto finora). Ho implementato una funzione globale sc(vector)che restituirà semplicemente una copia ridotta del vettore passato. Questo ovviamente funziona, ma mi obbliga a scrivere codice come:

drawCircle(sc(radius), sc(position))

Funzioni di avvolgimento . Potrei definire diverse funzioni, ognuna delle quali racchiude quella del middleware originale. Ad esempio, potrei definire myDrawCircleche prima ridimensionerebbe gli argomenti che necessitano di ridimensionamento, e poi chiamerei drawCirclecon quest'ultimo. Ciò renderebbe il mio codice forse più leggibile e più facile da mantenere, ma dovrei scrivere molte funzioni di wrapping, che sembrano sciocche.

Decoratore di funzioni . Potrei semplicemente decorare le funzioni del middleware esistenti, fornendo il ridimensionamento automatico per tutti i parametri che sono un'istanza della classe Vector3D, ma il problema è che quelle funzioni funzionano anche con gli stessi parametri essendo listo Vector2Dtroppo, e il decoratore non avrebbe modo di sapere quali elenchi devono essere ridimensionati (ad esempio il raggio) e quali no (i valori RGB).

Inizializzazione della superficie . Quando definisco la superficie su cui disegnerò, potrei definire il fattore di ridimensionamento (in modo da utilizzare quindi i parametri e non i pixel come parametri). Questo funzionerebbe in modo trasparente per me e sarebbe la mia soluzione preferita, ma ovviamente dovrebbe essere implementato nel middleware, quindi non è una vera opzione.

... comunque: dato che si tratta di un problema molto comune, mi chiedo se esiste un modello consolidato che risolva elegantemente questo problema che non sono riuscito a trovare.

PS: Per questo progetto sto usando python (con pygame ), ma - sebbene una risposta specifica per python / pygame sia molto apprezzata, sono più interessato alla descrizione generale / di alto livello del modello piuttosto che alla sua concreta implementazione.

Grazie in anticipo per il tuo tempo e competenza.

Risposte:


6

Il modo standard per farlo è quello di impostare una matrice di trasformazione per eseguire la conversione durante il rendering. Per il rendering 3D è la matrice di trasformazione della vista per la telecamera che lo fa.

La maggior parte delle API 2D ha anche un modo per specificare una trasformazione della vista, come matrice 2x3 o come scala, traduzione e rotazione separate.

Una rapida occhiata alla documentazione di pygame suggerisce che dovrai implementare tu stesso una matrice di trasformazione della vista. Ti consente di derivare la tua classe dalla sua classe di superficie per consentirti di aggiungere quella funzionalità?


La tua risposta è molto utile (+1). Posso sottoclassare la mia classe di superficie, ma ho bisogno di più tempo per esplorare se riesco a ottenere quanto indicato nel tuo post. Sono molto nuovo nella programmazione dei giochi e nella grafica in generale, hai qualche link da consigliare per spiegare questo approccio a matrice (o anche solo la matematica che coinvolge l'uso di una matrice per ridimensionare una superficie?). Grazie!
mac,

1
Dal momento che è 2D e non vi è alcuna rotazione in questione, @mac in pratica sta dicendo di avvolgere le funzioni e puoi usare la tua semplice divisione della scala in quei wrapper. Il motivo per cui viene normalmente utilizzata una matrice completa è che la maggior parte delle API ha una matrice che controlla il viewport, ma sembra che pygame non lo faccia, quindi devi farlo da solo a un livello.
Patrick Hughes,

2

dal momento che questo è un problema molto comune, mi chiedo se esiste un modello stabilito che risolva elegantemente questo problema che non sono riuscito a trovare.

Di solito le persone non tentano di eseguire il ridimensionamento di runtime nei giochi 2D. Non sono d'accordo che sia un problema comune. Se le persone desiderano una mini-mappa o altri riscalaggi fissi, spesso viene creato un nuovo set di grafica per questo scopo. È raro che tu abbia bisogno di una singola routine per correre a 2 diversi livelli di zoom in un gioco 2D.

Se si utilizza un'API 3D, è possibile ottenere gratuitamente questa funzionalità: basta modificare i parametri della videocamera / finestra.

PyGame è un'API molto vecchia e purtroppo è davvero adatta solo al 2D. Anche se potessi elaborare adeguati sistemi di ridimensionamento per i diversi livelli di zoom, le prestazioni non saranno abbastanza buone e l'aspetto sarà probabilmente inaccettabilmente negativo.

Vorrei consigliare che se si desidera ingrandire e rimpicciolire molto, si passa a una moderna API 3D il più presto possibile. Consiglierei Pyglet ma probabilmente ce ne saranno anche altri.


Grazie per la tua risposta (+1). Ho già usato pygletsin passato per una simulazione 3D. È sicuramente più capace di pygame, ma il supporto per il 2D è di livello piuttosto basso rispetto a quello in pygame. La documentazione / gli esempi disponibili sono anche meno dettagliati, il che è un peccato per me dato che sono un principiante nello sviluppo del gioco e ho davvero bisogno di capire le basi delle operazioni più comunemente eseguite. :) Per quanto riguarda l '"età" di Pygame: hai ragione. Una modernizzazione è tuttavia in corso! :)
mac

Per quanto riguarda: "È raro che tu abbia bisogno di una singola routine per eseguire a 2 diversi livelli di zoom" ... Ho pensato che fosse quello che sarebbe stato usato quando si cambiavano le dimensioni di una finestra / la risoluzione di un gioco a schermo intero. Dal tuo commento ho capito che non lo è: qualche puntatore a ciò che è "comune" invece?
mac,

Quali operazioni 2D stai eseguendo in cui pyglet è più basso livello di pygame? Entrambi consentono di disegnare uno sprite con 1 riga di codice. Quando cambi la dimensione della finestra di un gioco 2D, il rapporto pixel-unità-mondo rimane quasi sempre costante. Quindi finisci per disegnare più sprite: non li disegni in modo diverso.
Kylotan,

Per quanto riguarda le cose di basso livello: non sono veramente un esperto di nessuna delle due librerie, ma nei pyglet non sono riuscito a replicare immediatamente i comportamenti di rendering di gruppo offerti da pygame (come pygame.sprite.LayeredUpdatesad esempio). Per quanto riguarda il rapporto immutabile: ho capito cosa intendi. Il comportamento che descrivi non è quello che voglio replicare, ma ho capito cosa intendi, grazie per il chiarimento! :)
mac

pyglet ha oggetti OrderedGroup - i documenti sono qui se tu o qualcun altro è interessato: pyglet.org/doc/programming_guide/displaying_images.html#sprites
Kylotan
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.