Approccio alla programmazione videoludica



Documenti analoghi
f(x) = 1 x. Il dominio di questa funzione è il sottoinsieme proprio di R dato da

HD vs SD: E già ora per l alta definizione?

Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo.

IL MIO PRIMO SITO: NEWS

Calcolo del Valore Attuale Netto (VAN)

INVIO SMS

PLIDA Progetto Lingua Italiana Dante Alighieri Certificazione di competenza in lingua italiana

Logica Numerica Approfondimento 1. Minimo Comune Multiplo e Massimo Comun Divisore. Il concetto di multiplo e di divisore. Il Minimo Comune Multiplo

Gestione della memoria centrale

Esercizi su. Funzioni

NAS 251 Introduzione al RAID

Buongiorno vi ringrazio nuovamente per avermi invitato sono molto lieto di assistervi nella vendita della vostra casa

* Ricordati la BILANCIA Qualunque cosa facciamo ad un lato dell'equazione (piatto della bilancia), dobbiamo farlo anche per l'altro lato.

Note su quicksort per ASD (DRAFT)

APRIRE UN PROGRAMMA DI FOGLIO ELETTRONICO

Capitolo 2. Operazione di limite

risulta (x) = 1 se x < 0.

TRUCCHI PER GIMP - Elemento a colori in foto bianco e nero

ARCHITETTURA DI RETE FOLEGNANI ANDREA

Creare e ripristinare immagine di sistema con Windows 8

Guida all uso di Java Diagrammi ER

Proteggiamo il PC con il Firewall di Windows Vista

MIGRAZIONE SERVER DI POSTA ELETTRONICA

Versione 7.0 Taglie e Colori. Negozio Facile

Il database management system Access

IL MODELLO CICLICO BATTLEPLAN

Innanzitutto andiamo sul sito ed eseguiamo il download del programma cliccando su Download Dropbox.

NUOVA PROCEDURA COPIA ED INCOLLA PER L INSERIMENTO DELLE CLASSIFICHE NEL SISTEMA INFORMATICO KSPORT.

PROGETTO PER LA TRASMISSIONE DOCUMENTI RELATIVI ALL APPROVAZIONE DELLE MANIFESTAZIONI IN FORMA DIGITALE

Guida alla configurazione della posta elettronica dell Ateneo di Ferrara sui più comuni programmi di posta

[Dimensionare la pagina-creare le tabelle-formattare le tabelle-formattare la pagina

L interfaccia utente di Office 2010

SERVIZIO DICHIARAZIONE DI SUCCESSIONE ON LINE (SERVIZIO ATTIVO IN TUTTA ITALIA)

GUIDA ALLA RILEVANZA

Calcolatori Elettronici A a.a. 2008/2009

AT1542C - CED - Tablet offline - manuale utente

Da dove nasce l idea dei video

Invio SMS. DM Board ICS Invio SMS

illustrativa Affidabile, veloce, trasparente.

Quando troncare uno sviluppo in serie di Taylor

WORD 97 SCRIVERE UNA TESI DI LAUREA

4 3 4 = 4 x x x 10 0 aaa

Introduzione. Classificazione di Flynn... 2 Macchine a pipeline... 3 Macchine vettoriali e Array Processor... 4 Macchine MIMD... 6

Come creare il test di Yasso tramite l applicazione Training Center

Impostare e gestire correttamente i Layout per stampare da PLOTTER

LE CARATTERISTICHE DEI PRODOTTI MULTIVARIANTE

Un modello matematico di investimento ottimale

Progetto di simulazione molecolare per il corso di Complementi di algoritmi A.A

Cosa sono i corsi di aggiornamento?

APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI

Osservazioni sulla continuità per le funzioni reali di variabile reale

13. Campi vettoriali

Come creare una pagina Fan su Facebook [GUIDA]

DM Directional Movement

Google AdWords. Corrispondenze Parole Chiave

9. Urti e conservazione della quantità di moto.

Dr. Siria Rizzi NLP Trainer ABNLP DEFINIZIONE DI PNL

Joomla: Come installarlo e come usarlo. A cura di

PROCEDURA INVENTARIO DI MAGAZZINO di FINE ESERCIZIO (dalla versione 3.2.0)

Il calendario di Windows Vista

LE SUCCESSIONI 1. COS E UNA SUCCESSIONE

Modulo didattico sulla misura di grandezze fisiche: la lunghezza

Dispense di Informatica per l ITG Valadier

3. Installare Wamp Server

Benvenuti all esame dell EHRA!

Come masterizzare dischi con Nero 11

Fasi di creazione di un programma

Webinar e Manuale Operativo Tecnica di Trading

COSTER. Import/Export su SWC701. SwcImportExport

INTRODUZIONE AI CICLI

Procedura di iscrizione alla Piattaforma On Line

CHI SIAMO. La tua finestra televisiva su Pavia e Provincia

SISTEMI DI NUMERAZIONE E CODICI

Procedure di ripristino del sistema.

hi-com software realizzato da Hi-Think

MAGAZZINO FISCALE (agg. alla rel )

FAQ 07/01 - ACCORGIMENTI PER LA VISUALIZZAZIONE DEL NUOVO SITO ISS

Statistica. Lezione 6

MINIGUIDA PER RISORSE SU CLASH OF CLANS

Procedura per creare un archivio storico remoto nelle 24 ore giornaliere

I motori di ricerca. Che cosa sono. Stefania Marrara Corso di Sistemi Informativi

COME RIOTTENERE L ACCESSO ALLA CASELLA PEC DI ARUBA

Cookie. Krishna Tateneni Jost Schenck Traduzione: Luciano Montanaro

Guida Rapida di Syncronize Backup

Le query di raggruppamento

I documenti di Gli ingredienti per l allenamento per la corsa LE RIPETUTE

Ulteriori problemi di fisica e matematica

Esercizio 1 Dato il gioco ({1, 2, 3}, v) con v funzione caratteristica tale che:

COME SI ENTRA IN POSIZIONE

Scheduling della CPU. Sistemi multiprocessori e real time Metodi di valutazione Esempi: Solaris 2 Windows 2000 Linux

ATOLLO BACKUP GUIDA INSTALLAZIONE E CONFIGURAZIONE

ESEMPIO 1: eseguire il complemento a 10 di 765

MANUALE EDICOLA 04.05

GHPPEditor è un software realizzato per produrre in modo rapido e guidato un part program per controlli numerici Heidenhain.

EW1051 Lettore di schede USB

Modulo 4 Il pannello amministrativo dell'hosting e il database per Wordpress

Dispensa di Informatica I.1

lo PERSONALIZZARE LA FINESTRA DI WORD 2000

LE FUNZIONI A DUE VARIABILI

Transcript:

Approccio alla programmazione videoludica Fissate il vostro Timestep Questo documento non è completo ne esaustivo riguardo i temi trattati e non contiene delle regole definitive ma solo dei punti cardine da cui partire per solidificare le proprie basi sui principali punti cardine. Gli argomenti di seguito esposti possono essere affrontati e trattati più o meno approfonditamente e attraverso i più svariati argomenti. In questo documento saranno trattati alcuni temi senza andare troppo nel dettaglio e senza addentrarci in esempi se non quelli puramente essenziali. Curatore: Michael Rigamonti Documento realizzato per: michaelrigamonti.it Sito internet: http://michaelrigamonti.it/ Pagina Facebook: https://www.facebook.com/pages/michael-d-acciaio/162245450543276 Tutto il materiale contenuto in questo testo è di proprietà intellettuale dei rispettivi autori. Tutto il suo contenuto viene distribuito tramite licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Italia. Sono consentite copie cartacee di questo testo per esclusivo uso personale, ogni altro utilizzo al di fuori dell'uso strettamente personale è da considerarsi vietato e perseguibile a norma di legge. Per ulteriori informazioni http://creativecommons.org/licenses/by-nc-sa/3.0/it/

Introduzione Abbiamo visto nel precedente articolo La fisica nei videogiochi: integrazione di base come impostare una simulazione fisica. Ora vogliamo rappresentare il frutto di questo studio sullo schermo. Come facciamo? Come abbiamo scoperto nel precedente articolo, la simulazione fisica è effettuata a partire da alcuni stati iniziali (posizione, velocità, ecc), e successivamente integrando le equazioni del moto nel tempo, per far avanzare lo stato della fisica avanti nel tempo a piccoli passi. Il trucco per la visualizzazione di questo simulazione fisica sullo schermo è semplicemente quello di prendere un passo (step) della fisica e quindi tracciare l'oggetto. Ripetendo questo processo più e più volte, saremo in grado di mostrare lo stato dell'animazione fisica nel corso del tempo. Avanti nel tempo La prima cosa che dobbiamo fare è scegliere il passo o timestep per far avanzare la simulazione avanti nel tempo ogni volta che modifichiamo lo stato dell'oggetto. Il modo più facile per farlo è far avanzare la fisica di un certo timestep fisso di tempo ad ogni passo. Per esempio si potrebbe utilizzare un timestep di 1:100 di secondo ogni frame: float dt = 0.01f; // timestep Finchè (! simulazionefinita) ( // Calcoliamo l'avanzamento della fisica tramite l'integrazione Integra (stato, t, dt); Render (stato); // Visualizziamo a video lo stato corrente ) Il problema è che non si potrà mai essere veramente sicuri che il framerate (la velocità con cui le immagini sul nostro monitor vengono aggiornate) sia esattamente identico alla velocità di aggiornamento della simulazione. Alcuni computer renderizzano a 60Hz, mentre altri renderizzano a 75 o 85Hz. Un computer lento può essere in grado di renderizzare solo a 30Hz. Ciò significa che se si fissa un framerate costante delta, ad ogni frame la vostro simulazione sembrerà correre più veloce o più lenta, a seconda di quanto veloce il computer è in grado di renderizzare la vostra scena. È scontato dire che questo non va affatto bene! Un modo per risolvere questo problema è quello di usare un temporizzatore di grande precisione per ottenere l'attuale valore del tempo trascorso ogni volta che si aggiorna la fisica. Si può quindi definire il tempo trascorso in secondi tra la chiamata al calcolo dell'attuale stato fisico e quello precedente e aggiornare la fisica una quantità di volte pari alla differenza di tempo fratto il nostro delta t nel modo seguente: float tempocorrente = tempo(); //La funzione tempo recupera il tempo di sistema Finchè (! simulazionefinito) float nuovotempo = tempo (); float t = nuovotempo tempocorrente; tempocorrente = nuovotempo;

Integra (stato, t, dt); Renderizza (stato); Questo ultimo metodo sembra piuttosto buono. Se il gioco è in esecuzione a 60fps ad ogni dt sarà passato 1/60 di secondo per la simulazione, mentre se il gioco è in esecuzione su un computer più lento la velocità di simulazione passerà, per esempio, a 1/30 di secondo per 30fps. Non importa quanto veloce o lento è il computer, la nostra simulazione funzionarà sempre alla velocità corretta. Ma con questo metodo sorge un problema enorme che vorrei spiegarevi ora! Fissa il tuo timestep o scoppia Il problema è questo. Stiamo utilizzando l'integrazione numerica e così facendo i risultati di integrazione dipenderanno dalla dimensione del nostro timestep. Questo è vero anche per gli integratori come RK4. Più grande è il timestep meno accurati saranno i risultati. Così, se si lancia la simulazione in corso a 60fps e ad un certo punto durante il gioco il framerate scende a 10fps, tutto ciò che abbiamo fatto è stato inutile. Quest affermazione può non sembrare corretta a primo acchito, ma consideriamo che nella simulazione fisica, un piccolo cambiamento di timestep può causare enormi differenze di comportamento. Facciamo un esempio. Se si dispone di una serie di vincoli molto rigidi in una simulazione di assorbimento degli urti in un'auto, piccoli cambiamenti di dt possono effettivamente far sì che la simulazione esploda (che non sia cioè sufficientenmente precisa per essere tenuta in considerazione). Quindi idealmente, ciò che vogliamo, è il meglio di entrambe le tecniche. Vogliamo scegliere un unico dt in modo che ogni volta che si esegue la simulazione essa sia stabile e si comporti esattamente nel modo in cui è stata progettata. Allo stesso tempo vogliamo che la simulazione sia eseguita alla stessa velocità fisica indipendentemente dalla velocità, in framerate, di visualizzazione. Questi due requisiti sembrano completamente in disaccordo, e lo sono, a meno che di poter scindere la fisica e i framerates di visualizzazione. Liberare la fisica Che cosa bisogna fare per far avanzare la simulazione fisica utilizzando un fissato dt, e facendo in modo che la velocità di simulazione venga mantenuta invariata nella visualizzazzione a schermo in modo che il framerate della simulazione sembri funzionare alla stessa velocità? Ad esempio, se il framerate di visualizzazione è 50fps e la simulazione è stata progettata per funzionare a 100fps abbiamo quindi bisogno di far avanzare di due passi la fisica ad ogni aggiornamento del monitor per mantenere la fisica in sincronia. Ma non è sempre così facile. Che cosa succede se il display funziona a 60fps? E se il framerate è di 200fps? In quest'ultimo caso sembrerebbe che abbiamo bisogno di far avanzare la fisica di mezzo passo per ogni aggiornamento del display. Il problema è che noi abbiamo sempre bisogno di fare un passo avanti nella fisica in modo discreto di un valore dt, mentre il massimo che possiamo fare è aggiornare la fisica ogni due aggiornamenti della visualizzazioni a schermo. Che cosa succede se il display framerate oscilla tra 40 e 60fps? Ouch! Se si pensa a cosa esattamente è necessario per mantenere aggiornata la fisica in sincronia con l'aggiornamento del display mantenendo sempre discrete dimensioni dt di timesteps vedrete che la non è così banale. Ma ora vorrei condividere con voi un trucco che rende il tutto molto facile da

attuare correttamente. Il trucco è quello di usare un accumulatore di tempo. Ad ogni aggiornamento si aggiunge il tempo trascorso, memorizzato nella nostra variabile ad alta precisione, al valore del nostro accumulatore. Quindi quando vi sono incrementi superiori al nostro timestep dt si potrà esegue un passo intero di fisica e sottrarre dt dall'accumulatore. Effettivamente in questo modo il timer produce tempo e l'aggiornamento della fisica consuma un tempo discreto dt. costante float dt = 0.01f; float tempocorrente = time(); float accumulatore = 0.0f; Finchè (! simulazioneterminata) float nuovotempo = time(); float deltatempo = nuovotempo - tempocorrente; tempocorrente = nuovotempo; accumulatore += deltatempo; Finchè (accumulatore >= dt) integra(stato, t, dt); accumulatore -= dt; renderizza(stato); Questo codice si occupa sia del sottocampionamento che del sovracampionamento correttamente. Il sottocampionamento si ha quando il framerate del display è più basso rispetto al framerate della fisica ad es. 50 fotogrammi fisica quando il display funziona a 100fps. Il sovracampionamento si ha quando si dispone di un elevato framerate (o qunado si vuole visualizzazione di fisica al rallentatore [slow motion]) e l'aggiornamento della fisica si protrae nel corso di diversi aggiornamenti di visualizzazione. C'è un'ultima cosa a cui bisogna fare attenzione quando si usa questa tecnica. Ora che il nostro simulatore fisico è abbastanza intelligente da avanzare di un passo di grandezza deltatempo eseguendo piccoli incrementi di dimensioni pari a dt, occorre assicurarsi che il valore massimo contenuto nell'accumulatore non sia superiore a 0,25 secondi. Perché? Beh, se per esempio facciamo alt-tab all'interno della finestra di windows contenente la simulazione fisica e torniamo 10 minuti più tardi, avremo un lunghissimo tempo di attesa accumulatosi e quindi dovremo aspettare altrettanto tempo per poter far si che la fisica riesca a recuperare gli ultimi 10 minuti avanzando di un incremento pari a 1:100 di secondo e a video non verrà mai visualizzato niente durante tutta l'attesa Il tocco finale Così sembra che tutto vada bene. La nostra simulazione è stabile e il framerate indipendente, ma c'è ancora un'ultima cosa da fare per renderla perfetta. Consideriamo che cosa accadrà se il display framerate è 55fps e la fisica è in esecuzione a 60fps. In sostanza, l'accumulatore dovrà alternare tra

uno e due passi fisica per ogni aggiornamento dello schermo in modo da assicurarsi che la velocità della ficsica sia conservata. Questo importo irregolare di passi presi per aggiornare la fisica provoca una sottile ma visivamente sgradevole balbuzia della simulazione fisica sullo schermo. Peggio ancora, se avete un caso di sovracampionamento, in modalità rallentatore (ad esempio 1/10 velocità), il nostro effettivo framerate di visualizzazione dovrebbe essere 600fps se lo schermo è in realtà aggiornato a 60fps. Assumendo che la fisica è anch'essa aggiornata a 60fps l'accumulatore dovrebbe eseguire un solo avanzamento di fisica ogni 10 aggiornamenti della visualizzazione. Ciò significa che gli oggetti vengono animati in un tempo discreto ogni 1/6 di secondo. Questo sembra piuttosto scorretto, ma la buona notizia è che non vi è un modo per assicurarsi che tutto vada bene tutte le volte. La soluzione è quella di interpolare tra la precedente situazione fisica e lo stato attuale basato su quanto tempo viene lasciato nell accumulatore. Questo comporterà un aumento di latenza fino a dt per la nostra simulazione fisica, ma i risultati visivi sono decisamente migliori, quindi ne vale la pena. Ecco le modalità di attuazione: costante float dt = 0.01f; float tempocorrente = time(); float accumulatore = 0.0f; Stato statoprecedente; Stato statoattuale; Finchè (! simulazionefinita) float nuovotempo = time(); float deltatempo = nuovotempo - tempocorrente; tempocorrente = nuovotempo; accumulatore += deltatempo; Finchè (accumulatore >= dt) statoprecedente = statoattuale; integra(statoattuale, t, dt); accumulatore -= dt; costante float residuo = accumulatore / dt; Stato state = stotocorrente * residuo + statoprecedente *(1.0f - residuo); renderizza(stato); Quello che ho scritto potrebbe sembrare piuttosto complicato, ma non è poi così difficile. Dopo che deltatime è stato aggiunto all'accumulatore e che tutti gli avanzamenti (con passo dt) nel calcolo della fisica sono stati effettuati, se la fisica e la visualizzazione non sono multipli interi dei fotogrammi, allora un po' di tempo rimarrà nell'accumulatore. Questo residuo è di fatto una misura di quanto tempo è necessario prima che un altro passo fisica possa essere calcolato. Per esempio, un resto di dt / 2 significa che siamo attualmente a metà strada tra il passo di fisica attuale e quello successivo. Un resto di dt * 0,1 significa che l'aggiornamento è a 1/10 della strada

tra il passo attuale e quello successivo. Possiamo utilizzare questo valore rimanente per ottenere un fattore di miscelazione tra l'attuale situazione fisica e lo stato precedente semplicemente dividendo per dt. Questo dà un valore che abbiamo chiamato residuo nell'insieme [0,1], che abbiamo usato per eseguire un'interpolazione lineare tra i due stati fisici al fine di ottenere lo stato attuale da visualizzare a schermo. Questa interpolazione è facile da fare per valori singoli ma anche per i valori del vettore di stato. Può essere usata con tutti i tipi di corpo rigido dinamici a patto di conservarne l'orientamento come un quaternione e utilizzare un'interpolazione lineare sferica (slerp) tra gli orientamenti precedenti e quelli attuali. Vi mostrerò come farlo nel prossimo articolo. Per maggiori informazioni sull'interpolazione sferica lineare tra quaternioni: http://en.wikipedia.org/wiki/slerp Se attuate questa tecnica di interpolazione sarete certi che non vi sarà alcun balbettamento visivo quando il framerates del display e della fisica sono fuori sincronizzazione. Questo tipo di interpolazione consente inoltre di gestire perfettamente il caso del sottocampionamento in modo che gli oggetti si spostino senza problemi quando sono visualizzati in una simulazione al rallentatore o tra dieci anni da ora su un calcolatore veramente veloce. Conclusione L'implementazione del timestep sembra così semplice, ma contiene molte sottigliezze che devono essere capire per essere attuate perfettamente. Spero che potrete usare le tecniche presentate in questo articolo per migliorare la sincronizzazione dei tempi nella vostra simulazione fisica. Certo, se si segue esattamente ciò che vi ho presentato qui è possibile dissociare i framerates dello schermo e della fisica in modo stabile e coerente. Allo stesso tempo potete fare in modo che la vostra animazione fisica sia visualizzata senza intoppi sullo schermo. Ed è il risultato veramente migliore che si possa ottenere. Infine, per ciò che vale la pena, consiglio di utilizzare questa tecnica per il rafforzamento del tempo per tutti i sistemi di gioco. Scegliere un framerate appropriato per il vostro gioco (diciamo 60fps), vi consentirebbe di slegare l'intero motore di aggiornamento del gioco per funzionare con questo framerate fisso. Perché? Per gli stessi motivi di affidabilità e stabilità che ci hanno spinto a fare questo per la fisica applicando al gioco altro codice. Lanciare il vostro codice di gioco diverse volte produrrà solitamente risultati diversi. Scegliendo invece un framerate fisso per tutti i sistemi si può garantire che il gioco si comporti coerentemente indipendente dal framerate di aggiornamento. Ho certamente visto numerosi bug nei codici dei gioco, che non si notano finchè non vengono eseguiti a basso framerates. Non lasciate che questo accada: è sufficiente fissare il vostro timestep e tutto verrà risolto.