In che modo i videogiochi memorizzano le informazioni fuori dallo schermo?


16

Sto cercando di creare un videogioco da zero, ma sono davvero nuovo e continuo a imbattermi in problemi di base. Ancora più importante, in che modo i videogiochi memorizzano le informazioni fuori schermo? Quello che voglio dire è, come fa il programma a sapere cosa visualizzare accanto allo schermo? O anche, se il giocatore cambia l'ambiente, come rimane questa modifica per il prossimo caricamento sullo schermo?

Ad esempio, in New Super Mario Bros, se colpisci un? bloccare e poi andare fuori dallo schermo, e tornare indietro, rimane ancora colpito. Come vengono conservate e poi eseguite queste informazioni la volta successiva che il giocatore carica il blocco? Perché non si reimposta?


24
Pedanteria: in Super Mario Bros, se colpisci un? blocca e poi vai fuori dallo schermo, non puoi tornare indietro - il gioco scorre solo in una direzione e tutti i tubi di ordito sono a senso unico.
Trevor Powell,

61
Quando leggi un documento di testo e scorri verso il basso, il tuo elaboratore di testi cancella l'inizio del documento?
Philipp,

31
Il monitor mostra una finestra sul mondo di gioco. Il mondo esiste fuori dalla tua finestra, semplicemente non lo vedi.
Felsir,

11
La domanda di programmazione per principianti molto più tipica è: "Come posso visualizzare le mie informazioni sullo schermo?". Lavora attraverso qualsiasi tutorial di programmazione e quando arrivi a quella domanda dovresti già avere la risposta alla tua domanda.
Peter,

4
Mi chiedo con che tipo di ambiente di sviluppo stai lavorando che mantenere le cose fuori dallo schermo sembra più complicato che metterle sullo schermo :) O è solo una domanda puramente teorica?
Luaan,

Risposte:


59

Di solito dovresti separare lo stato logico dell'ambiente di gioco dalla rappresentazione visiva.

Il giocatore può vederne solo una piccola parte sul proprio schermo, ma si mantiene comunque in memoria lo stato dell'intero livello e di solito si calcola anche la meccanica di gioco per l'intero livello. Quando il tuo mondo è così vasto che questo richiederebbe troppa RAM e / o CPU, puoi sospendere le aree più lontane sul disco rigido.

La subroutine di rendering controlla quali parti del livello sono attualmente sullo schermo e quindi disegna solo quelle. Qualunque cosa sia fuori dallo schermo non viene disegnata, ma ciò non significa che non sia aggiornata.


37

Ci stai andando al contrario.

Inizi con lo stato logico del tuo gioco e modellalo. L'intero stato logico di tutto il mondo sarà quasi certamente troppo per essere conservato in memoria contemporaneamente, quindi lo si scompone in parti più piccole che possono essere caricate e salvate in modo indipendente. Queste parti vengono spesso definite blocchi . Questi blocchi possono formare un mondo continuo, ma possono anche essere livelli / istanze separati. La terminologia varia notevolmente a seconda del genere e della tecnica che si desidera utilizzare.

Quindi si caricano quelle parti che sono di interesse, vale a dire pezzi che si trovano nelle vicinanze del giocatore. I blocchi troppo lontani vengono salvati su disco / memoria permanente e scaricati dalla memoria.

E poi, come ultimo passo, determini ciò che è effettivamente visibile e crei la rappresentazione visiva dello stato di gioco corrente e lo visualizzi sullo schermo.

Ovviamente si cercherebbe di non ricostruire l'intera rappresentazione visiva ogni volta, ma di memorizzarla nella cache e riutilizzarla se si hanno parti già costruite, ma questo è il principio principale.


Questo vale per qualsiasi programma che ha un output. Se si scrive un programma con una normale GUI, come un editor di testo, è probabile che modifichi il documento, quindi la GUI determina lo stato e le parti visibili del documento e lo visualizza sullo schermo. Oppure compila i campi del modulo in modo appropriato, oppure.

L'essenziale è: pensare a dove e come archiviare prima i dati (probabilmente insieme a come rappresentarli). Quasi tutti i programmi hanno a che fare con l'archiviazione dei dati. Esistono solo pochissimi casi in cui non si memorizzano dati.


7
pezzi? Definirei quei livelli di pezzi più piccoli .
gbjbaanb,

3
Questo è buono, tranne per "così lo si scompone in parti più piccole che possono essere caricate e salvate in modo indipendente. Queste parti sono spesso chiamate blocchi", che sembra essere specifico per i giochi con mondi molto grandi. Molti giochi non hanno bisogno di fare una cosa del genere. Non sarei sorpreso se potessi mettere in memoria tutti i dati di livello per ogni sidescroller 2D mai creato.
user253751

3
@gbjbaanb 'Livello' è un termine datato e 'pezzo' è molto più completo e un concetto chiaramente distinto. Non tutti i blocchi sono livelli e non tutti i livelli sono blocchi.
Lilienthal,

3
Penso che un modo utile per pensarci sia che dovrebbe essere tecnicamente possibile giocare a tutto il gioco senza che sia riprodotto un singolo pixel, cioè l'intero gioco è separato dalla rappresentazione visiva.
Nathan K,

1
@Lilienthal certo, ma penso che il livello sia ancora in uso comune, e molti giochi hanno ancora il concetto - non sono sicuro che nessuno di loro faccia apparire una schermata di "caricamento" quando recupera una nuova "arena", quindi il giocatore le attraversa. Quindi potrebbe essere più comprensibile, in particolare per l'OP chi è nuovo ai giochi di un termine relativamente tecnico che non avrebbe mai visto prima.
gbjbaanb,

6

Come altri hanno già detto, si mantiene una mappa (ad esempio in un array) e si disegna la parte visibile di essa sullo schermo e non si rilegge dallo schermo.

Ma in alcuni sistemi meno recenti manterresti letteralmente i dati fuori dallo schermo. Ci sarebbero, diciamo, 400x300 pixel di memoria video per un display 320x200 e definiresti una finestra ("inizia da X = 10 Y = 30"). Quindi puoi scorrere lo schermo semplicemente regolando un registro. Non dovresti spendere i centomila cicli necessari per spostare i byte, basta cambiare il punto in cui l'hardware video inizia a leggerli.

Il NES ha questo, combinato con un sistema basato su piastrelle: http://wiki.nesdev.com/w/index.php/PPU_scrolling

Il NES non costruisce mai l'intera immagine in memoria, perché non ha abbastanza RAM. Invece, c'è un array RAM che definisce un set di riquadri su due schermi. Un byte per tipo di riquadro. L'hardware video cerca le piastrelle e le coordinate di offset X / Y per decidere quale pixel deve apparire in qualsiasi punto.


6
Sebbene sia vero, questo è un dettaglio di implementazione - il principio principale è ancora che tu abbia uno stato logico e lo renda (e spesso come ho detto memorizzane alcune parti, già prepari alcune cose che verranno al punto di vista successivo ecc.).
Polygnome,

2
@Polygnome Beh, ho scritto molti giochi in cui lo schermo era lo stato del gioco. È incredibile quello che puoi fare con 4000 byte di VRAM! :)
Luaan

1

Bene, se stai facendo questo tipo di domande, avrai una lunga strada da percorrere per arrivare al punto in cui puoi fare un gioco. Ma, arrivando al nocciolo della tua domanda, il programma può salvare lo stato di molte cose diverse in variabili che si trovano nel back-end del tuo programma. Diamo un'occhiata a un paio di esempi.

Mario Brothers (o simile) salva lo stato del livello in cui ti trovi. Ciò potrebbe includere quanto lontano sei andato prima di morire, se un blocco è stato colpito o no. In un certo senso più orientato agli oggetti, il gioco dice semplicemente "essere un blocco qui" e il blocco esiste. quindi quando si colpisce il blocco, il blocco cambia il suo stato interno per dire "Sono stato colpito". Dati del genere possono essere archiviati in vari modi.

Il tuo elaboratore di testi salva i suoi dati in una struttura di dati. Ora ci sono molti di questi e molti modi in cui possono essere implementati, ma probabilmente usa una forma di albero. In un albero hai almeno un nodo. Tutto ciò che è stato aggiunto prima di andare a sinistra. Qualunque cosa aggiunta dopo, va a destra. Dopo aver aggiunto tre nodi, due di essi pendono dal nodo centrale. E l'albero può crescere ancora di più con nuovi pezzi aggiunti ovunque e l'albero si ricostruirà da solo. Esempio di albero Oppure pensa ai giochi sparatutto in cui il tuo nemico vaga. Ognuno di essi ha variabili che tracciano la loro posizione, vita, ecc. In modo che quando ne ferisci uno, ricorderà che è stato ferito.

Tutte queste cose richiedono una conoscenza delle strutture di dati. Va ben oltre ciò che vedi sullo schermo. Suggerirei di leggere array, elenchi, hash (a volte chiamati dizionari o mappe) e poi tornare al tuo problema.

Ecco alcuni buoni materiali di partenza:


0

In una certa misura, questa è una funzione della modalità di rendering 3D. Ad esempio, OpenGL eliminerà automaticamente la geometria al di fuori dell'intervallo -1,0, +1,0 nello spazio dello schermo XY (Z è più complesso ma simile). La geometria abbattuta non genera mai frammenti (approssimativamente pixel) e quindi non viene mai trasformata in immagini reali, nonostante venga inviata al sistema per il rendering. In ogni caso, è impossibile scrivere nello spazio all'esterno della finestra di rendering (se tutto funziona come dovrebbe).

In alcuni contesti, è sufficiente fare affidamento su questo comportamento come ottimizzazione. Tuttavia, devi ancora passare tutti i tuoi dati di gioco attraverso almeno una fase di rendering (vertex shader) prima che la scheda video possa sapere cosa è visibile. In qualcosa come, diciamo, Skyrim, sarebbe impraticabile. Non solo devi inviare tutti i vertici del mondo attraverso la pipeline di rendering, ma devi caricare tutti i vertici nella memoria di sistema / video. È inefficiente, se possibile.

Quindi, molti giochi faranno uso dell'abbattimento basato sulla CPU. In genere implementeranno una sorta di sistema LOD (livello di dettaglio), in cui la qualità e l'esistenza delle risorse sono influenzate dall'importanza della loro valutazione in un determinato contesto. Una maglia piramidale potrebbe essere un'approssimazione accettabile per una montagna se ci si trova a 50 miglia di distanza. Se non riesci a vederlo (come se fosse bloccato da altre montagne), non è nemmeno necessario caricarlo. Esistono diversi metodi più complessi per farlo che sono argomenti che non ritengo siano direttamente pertinenti alla profondità richiesta da questa domanda, ma guardiamo alla tassellatura per uno degli esempi più comuni.

La vera essenza di ciò è che la grafica è solo il prodotto del gioco. I dati effettivi non hanno nulla a che fare direttamente con ciò che si vede o non si vede per la maggior parte del tempo, e i dati vengono filtrati da varie fasi per rimuovere informazioni estranee prima di colpire il punto in cui un'immagine viene scritta sullo schermo. A seconda del design del motore, gli elementi visivi possono essere estremamente disaccoppiati dalla reale logica di gioco, nella misura in cui qualcosa come avere un'interfaccia 2D e 3D nello stesso gioco è una possibilità. È anche possibile che molti motori di gioco funzionino senza output; a volte questo è usato per testare l'intelligenza artificiale del gioco.

È lì che le cose possono complicarsi, però. In qualcosa di semplice come un gioco di Mario, non è troppo proibitivo calcolare il movimento di tutti i nemici nel livello, anche se non sono visibili. Nei contesti moderni, ciò che sta accadendo fuori dallo schermo è una vera domanda di seria considerazione. Se ci sono più intere città di NPC, come gestisci il loro comportamento quando sono completamente abbattuti, come quando il giocatore si trova in una città diversa? Vuoi davvero calcolare centinaia di decisioni degli NPC su tutta la mappa? La risposta di solito è no, ma l'approccio esatto per non farlo può variare e può avere un impatto sul gioco.

È importante notare che è così che funzionano le cose adesso . I vecchi giochi di Mario erano probabilmente programmati in modi molto diversi (non posso parlare con i modi esatti), dati i limiti estremi dell'hardware in quel momento. Il concetto di 3D non esisteva allora; eppure oggi quasi tutti i giochi, anche quelli interamente in 2D, usano il rendering 3D in qualche forma, anche se non sanno che lo fanno. L'hardware video moderno è il primo in 3D e il rendering 2D (almeno quando utilizza correttamente l'hardware) ignora semplicemente la terza dimensione.


Oltre alle tecniche LoD, sarebbe bene aggiungere uno scenario a questa risposta, in cui un mondo può essere tenuto in memoria e 'cullato dalla CPU' in base a ciò che è all'interno della vista.
gbjbaanb,

0

Per rispondere alla tua domanda: i videogiochi mantengono lo stato del mondo di gioco in una struttura di dati astratta che non ha nulla a che fare con lo schermo. Questo viene quindi visualizzato sullo schermo secondo necessità (cioè, a seconda di dove si trova il giocatore).

I giochi che utilizzano direttamente la RAM video per scopi statali erano negli anni '80 nell'8-bit, forse anche nell'era a 16-bit, ma a meno che non si stia sviluppando per quella piattaforma o per alcuni µC che invece carica la sua RAM in KB di GB, non pensarci più.

Detto questo, sembri essere molto nuovo in tutto ciò che riguarda la programmazione, o la domanda non sarebbe emersa. Suggerisco di procedere passo dopo passo, programmando prima cose molto semplici; forse qualcosa che ha solo input / output testuali (istruzioni semplici e tutto il resto). Ad essere sincero, il momento in cui l'ho fatto è circa 30 anni fa, quindi non ho davvero buone risorse per te, ma la tua biblioteca locale potrebbe essere migliore di Internet per darti un ottimo inizio nella programmazione.

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.