✚ Sviluppo videogiochi

Fisica semplice nei giochi: gravità, velocità e un buon salto

Gravità, velocità e accelerazione in un gioco 2D: integrazione di Eulero semi-implicita, salto calibrato per altezza e durata, attrito e limiti.

Non serve un motore fisico completo per far muovere bene un personaggio. Nella maggior parte dei giochi d'azione 2D bastano tre grandezze, posizione, velocità e accelerazione, aggiornate con poche righe di codice. La parte difficile non è la matematica, ma la taratura: un salto «giusto» è una scelta di design prima ancora che di fisica.

Posizione, velocità, accelerazione

Il legame tra queste grandezze è semplice:

  • la velocità indica di quanto cambia la posizione ogni secondo;
  • l'accelerazione indica di quanto cambia la velocità ogni secondo.

La gravità è un'accelerazione costante verso il basso. A ogni aggiornamento, con un passo temporale dt, si applicano due operazioni:

velocita.y += gravita * dt
posizione.y += velocita.y * dt

L'ordine conta. Aggiornare prima la velocità e poi la posizione con la velocità nuova si chiama Eulero semi-implicito (o simplettico) ed è più stabile della versione «ingenua», che usa la velocità vecchia. Per i giochi è il metodo standard: semplice, economico e abbastanza preciso se il passo è fisso e piccolo.

Nelle coordinate dello schermo di solito l'asse y cresce verso il basso, quindi la gravità ha segno positivo e un salto ha velocità iniziale negativa. È una fonte frequente di confusione quando si passa da un motore all'altro.

Progettare il salto a partire dal risultato

Scegliere valori a caso per gravità e forza del salto porta a lunghe sessioni di tentativi. È più efficace partire da due parametri comprensibili per un game designer:

  • altezza massima del salto, in pixel o in tasselli;
  • tempo per raggiungere l'apice, in secondi.

Dalle leggi del moto uniformemente accelerato si ricavano direttamente le grandezze fisiche:

gravita = 2 * altezza / (tempo_apice * tempo_apice)
velocita_salto = -2 * altezza / tempo_apice

Per esempio, un salto alto 96 pixel che raggiunge l'apice in 0,4 secondi richiede una gravità di 1.200 pixel al secondo quadrato e una velocità iniziale di −480 pixel al secondo. Se poi si vuole un salto più alto, si cambia solo l'altezza e il resto si ricalcola, mantenendo la stessa sensazione di durata.

Rendere il salto piacevole

Un salto fisicamente realistico, con la parabola perfettamente simmetrica, spesso risulta «galleggiante». Alcuni accorgimenti molto diffusi nei platform:

Gravità maggiore in discesa

Applicare una gravità più forte quando il personaggio scende, per esempio 1,5 o 2 volte quella di salita, rende la caduta più decisa e il controllo più reattivo.

Altezza variabile

Il giocatore si aspetta che una pressione breve produca un salto basso e una lunga un salto alto. Il modo più semplice: se il tasto viene rilasciato mentre il personaggio sta ancora salendo, si riduce la velocità verticale, per esempio dimezzandola. In alternativa si aumenta la gravità finché il tasto non è premuto.

Velocità di caduta massima

Senza un limite, una caduta lunga porta il personaggio a velocità enormi, che rendono difficile atterrare con precisione e possono causare attraversamenti di piattaforme sottili. Un tetto alla velocità verticale, spesso chiamato terminal velocity, risolve entrambi i problemi.

Movimento orizzontale: accelerazione e attrito

Anche il movimento laterale beneficia di un'accelerazione invece di uno scatto istantaneo:

se destra premuta:
    velocita.x += accelerazione * dt
altrimenti se sinistra premuta:
    velocita.x -= accelerazione * dt
altrimenti:
    velocita.x = avvicina_a_zero(velocita.x, attrito * dt)

velocita.x = limita(velocita.x, -velocita_max, velocita_max)

La funzione avvicina_a_zero riduce il valore assoluto senza superare lo zero, evitando che il personaggio oscilli avanti e indietro quando si ferma. Valori diversi di accelerazione e attrito producono sensazioni molto diverse:

Accelerazione Attrito Sensazione
Alta Alto Controllo preciso, scatto immediato
Bassa Basso Movimento scivoloso, come sul ghiaccio
Alta Basso Partenza rapida, frenata lunga
Bassa Alto Personaggio pesante, partenza lenta

È utile anche ridurre il controllo in aria rispetto a terra: un personaggio che cambia direzione in volo con la stessa prontezza che ha sul pavimento risulta poco credibile, ma toglierlo del tutto rende il gioco frustrante. Un valore intermedio è quasi sempre il compromesso migliore.

Altre forze utili

Lo stesso schema si estende facilmente:

  • vento o correnti: un'accelerazione orizzontale costante in una zona del livello;
  • rimbalzo: dopo una collisione con il suolo si inverte la velocità verticale moltiplicandola per un coefficiente minore di 1;
  • spinta di un nemico: si aggiunge un impulso istantaneo alla velocità, cioè un cambiamento immediato invece di un'accelerazione nel tempo;
  • acqua: gravità ridotta e attrito aumentato in entrambe le direzioni.

Rendere tutto modificabile

Il consiglio più pratico è esporre ogni parametro in un file di configurazione o in un pannello di debug modificabile mentre il gioco è in esecuzione. Nel mio lavoro ho visto che la differenza tra un movimento mediocre e uno piacevole sta quasi sempre in piccoli aggiustamenti fatti provando il gioco, non nelle formule. Ricompilare a ogni modifica di un numero rallenta enormemente questo processo.

In sintesi

  • Posizione, velocità e accelerazione bastano per una fisica di gioco convincente.
  • L'integrazione di Eulero semi-implicita, con passo fisso, è stabile e semplice.
  • Gravità e velocità del salto si ricavano da altezza desiderata e tempo per l'apice.
  • Gravità maggiore in discesa, salto variabile e velocità massima migliorano la sensazione.
  • Accelerazione e attrito orizzontali definiscono il carattere del movimento.
MM
Marco Marzaduri

Marco Marzaduri si occupa di cybersecurity, informatica forense e sviluppo web. Laureato in informatica, unisce il rigore dell'analisi tecnica all'attenzione per le persone che usano la tecnologia.

Leggi anche