Nella maggior parte della applicazioni grafiche la simulazione di comportamenti fisici ricopre un ruolo fondamentale. Per questo motivo vi farò vedere un metodo piuttosto elementare ed efficiente per simulare una navicella sottoposta ad un campo gravitazionale costante. Se conoscete il gioco Luna Lander avete già capito a cosa voglio arrivare.
Analisi Fisica
Il primo passo di ogni simulazione fisica consiste nello studiare nel modo più preciso possibile qual’è il comportamento fisico degli oggetti da simulare. Nel nostro caso l’unico elemento che ci interessa è la navicella.
Dal disegno vediamo che in un generico momento la nostra navicella è sottoposta ad una forza F orientata di lungo l’asse verticale. La forza F rappresenta infatti la forza generata dal motore della navicella orientata sempre lungo l’asse della navicella.
Usando la classica formula della dinamica otteniamo:
Dividendo tutto per la massa della navicella:
Il nostro sistema ora è completamente descritto. Tuttavia in questa forma differenziale non è ancora sfruttabile dalla nostra applicazione.
Individuare gli ingressi
Il secondo passo consiste nell’individuare gli ingressi ovvero cosa dipende dallo stato e cosa dipende dall’input? Questo è importante perché gli ingressi sono del tutto imprevedibili o perché troppo complessi da predirre oppure perché generati dal libero arbitrio del giocatore. Nel nostro caso il giocatore controlla direttamente due parametri:
- La forza F del motore. Premendo un tasto (ad esempio la freccetta su) il motore è acceso e genera una forza F, quando il tasto non è premuto il motore è spento e la forza generata è pari a zero.
- L’angolo con cui è orientata la navicella. Per semplicità assumiamo che solo tre valori siano possibili e che tali valori cambino istantaneamente alla pressione del tasto corrispondente. Premendo il tasto direzionale destro , premendo il tasto sinistro e non premendo nulla .
Integriamo
A questo punto, dalla legge che descrive l’accelerazione dobbiamo ricavare la funzione che descrive la posizione (che ci interessa sapere per disegnare la nave sullo schermo nel punto giusto).
Tuttavia integrare una funzione del genere analiticamente è impossibile. Come fare? Approssimando. A questo punto molti metodi sono stati sviluppati ma qui di seguito vi presento il metodo che ho usato più spesso per questo genere di cose. Non so se sia il più preciso ma offre un ottimo realismo con prezzi computazionali piuttosto irrisori.
L’idea che sta alla base di questo metodo è di considerare gli ingressi dell’utente come costanti (sebbene varino platealmente con il tempo). In questo modo integrare e risulta un compito banale.
Da cui
Discretizziamo
Con una formula in tempo continuo ci facciamo ancora poco. Il computer lavora per cicli e, per quanto questi cicli possano essere piccoli, non possono certo essere considerati continui. Per far questo discretizziamo. Un metodo molto semplice consiste nel sostituire . Dove assume solo valori interi e rappresenta la dimensione degli intervalli del ciclo (per simulazioni realtime viene scelto pari a
La formula riscritta in questo modo assume la forma:
Calcoliamo una formula incrementale
La formula precedente ha un grande svantaggio. Ci costringe a dover mantenere nella memoria la velocità iniziale, la posizione iniziale e il numero di cicli trascorsi dall’inizio della simulazione. Senza contare che questa formula da valori completamente sbagliati perché assume che l’accelerazione sia sempre costante: in questo modo quando l’utente accenderà il motore la formula ci darà la posizione che avrebbe avuto la navicella se il motore fosse sempre stato acceso dall’inizio, e viceversa, e non il valore corrispondente ad un motore appena acceso!
Ma a questo c’è una soluzione: basta trovare una formula incrementale che condensi tutte queste informazioni nel suo stato passato.
Per prima cosa vediamo la velocità. Calcoliamo la velocità per $\latex k+1$.
Bene. Possiamo subito notare che questa formula è equivalente a:
Con un procedimento analogo possiamo ricavare anche
Ora abbiamo una formula iterativa che ci permette di calcolare il moto della navicella sotto il comando dell’utente. Possiamo riassiumere l’algoritmo finale in questo modo:
Per ogni “frame” facciamo
- Tramite i comandi dell’utente calcoliamo e .
- Usando i valori appena calcolati e i valori di x, y e velocità precedenti calcoliamo i nuovi valori per x, y e v.
Rendere coerenti le unità di misura e i sistemi di riferimento
Tutto il nostro ragionamento è fatto sulla base di unità di misure fisiche (metri su secondo). Lo schermo però si comporta diversamente. Le coordinate di un oggetto sullo schermo, ad esempio, sono quasi sempre indicate in pixel e non i metri. Dobbiamo quindi scalare i dati di x e y in modo tale che siano coerenti con la rappresentazione grafica.
Se ad esempio un metro sullo schermo ha una dimensione di 10px dobbiamo moltiplicare il valore di x e y di un fattore 10. Analogamente facciamo l’opposto se un pixel rappresenta 10 metri. 🙂
Mi potresti farmi venir voglia di studiare per l’esame di fisica.
Se nei corsi di fisica facessero vedere qualche bella applicazione pratica della stessa sarebbero più appassionanti 😉
Se nei corsi di fisica facessero vedere qualche bella applicazione pratica della stessa sarebbero più appassionanti