In questi due esempi che vedremo, simuleremo un campo di Air Hockey. Non ci concentreremo sul gioco in se, ma sulla simulazione fisica, quindi quello che riguarda il disco e il giocatore. Anche in questo caso il codice è relativamente semplice e basterà sottolieare alcuni punti per far capire il funzionamento globale.
I due esempi differiscono per i movimenti del giocatore. Infatti non basta spostare la mazza sul tavolo, perché altrimenti questa non imprimerebbe nessuna velocità al disco, serve quindi gestire la cosa trattando la mazza come se fosse un oggetto che riceve impulsi, oppure come un oggetto legato al puntatore del mouse e quindi ai suoi movimenti (di conseguenza acquisterà velocità, necessaria per spostare il disco realisticamente).
In entrambi vi sono le funzioni che abbiamo già visto nel precedente articolo, quindi mi limiterò a commentare le differenze e ad analizzare le cose in più.
def add_mouse(space): il mouse costituisce la mazza con la quale colpiremo il disco, quindi creiamo un oggetto circolare che lo rappresenti.
def add_L(space): questa volta utilizzeremo dei segmenti per delimitare il campo di gioco e questa funzione ha il compito di creare proprio quest’ultimo. Visto che non dovranno muoversi, possiamo aggiungerli come statici al nostro spazio pymunk.
Le funzioni successivi le avete già incontrate nell’esempio precedente. Vorrei ricordare che la funzione to_pygame viene utilizzata per la conversione delle coordinate. Anche se io non ne faccio utilizzo in questi piccoli esempi è comunque indispensabile integrare questa funzione in un engine di gioco. Pensate infatti di avere molti più oggetti al quale applicare questo calcolo e con risoluzioni di schermo differenti. Chiamando una funzione del genere, con i dovuti accorgimenti (cioè rilevare l’altezza dello schermo), il codice sarà molto più pulito, più chiaro e più maneggevole.
Chiusa questa piccola parentesi possiamo notare qualche piccola differenza nella funzione run (dalla linea 74). Per prima cosa abbiamo tolto la gravità (cioè non l’abbiamo settata, l’ho lasciata come commento) e abbiamo aggiunto il damping, cioè lo smorzamento, e modificato lo static_hash e l’active_hash per una migliore reattività. Naturalmente valora più grandi, rendono più sensibile e realistico il movimento, aumentando le risorse richieste per far girare il gioco, quindi non eccedete troppo perché questo è solo un file di esempio e ci sono solo due corpi da gestire. Abbiamo aggiunto di seguito le linee, la palla e il mouse (la nostra mazza.)
Tra gli eventi possiamo notare che controlliamo solo il movimento del mouse. In poche parole, viene creato un vettore dalla posizione attuale della mazza fino alla posizione del puntatore in quel momento. Normalizzando quel vettore avremo quindi la direzione che la mazza deve percorrere per raggiungere la nuova posizione del puntatore. Ora non dobbiamo spostare semplicemente la mazza, perché altrimenti non acquisterebbe la velocità che dovrebbe essere trasmessa al disco (come abbiamo detto in precedenza), quindi vi applichiamo un impulso che viene generato dal suo centro di gravità nella direzione indicata.
Per ovviare al fatto che la mazza sarebbe solo in balia di questi impulsi quando il mouse si muove, nel loop principale (dalla linea 102) facciamo semplicemente spostare il corpo della mazza nella posizione attuale del puntatore.
In questo modo abbiamo approssimativamente simulato questo gioco in un banale esempio. Sia ben chiaro, non è perfetto, ma in quasi 120 righe di codice (contando anche gli spazi), mi sembra più che accettabile. Se non ci credete, provate a riscrivere lo stesso giochino senza l’utilizzo di pymunk. Ora vediamo l’altro esempio:
Dalla linea 80 possiamo notare come questo approccio sia completamente differente. In questo caso, il puntatore del mouse è indipendente dalla mazza (che rimane mouse_shape), ma i due corpi sono collegati da un DampedSprig, cioè una molla che ha un coefficente di smorzamento. In questo modo, nel loop dei controlli, dobbiamo solo aggiornare la posizione del puntatore (point_shape) perché la mazza (mouse_shape) è legata ad esso.
Con questo piccolo accorgimento però abbiamo cambiato le meccaniche di gioco, serviva piuttosto per fare vedere come si può variare lostile in base a semplici regole. Infatti siete voi stessi che gestite i “compromessi” della simulazione, in base al tipo di gioco e al progetto che volete realizzare.
Conclusioni
Con questo spero di aver fatto capire alcuni concetti chiave nell’utilizzo di librerie fisiche. L’unico modo per imparare ad utilizzarle è cimentarvi con esse, sperimentare varie soluzioni e testare anche i più piccoli cambiamenti. A volte un coefficente di attrito troppo alto potrebbe compromettere lo stile di gioco. Certo, sono ipotesi un pò esagerate, ma dovete comunque avere ben chiara l’idea finale per raggiungere una soluzione soddisfacente. Di seguito rilascio i sorgenti dei due esempi.
In Appunti Digitali cerchiamo di esprimere punti di vista informati su questioni che conosciamo, materie che pratichiamo professionalmente o passioni seguite a lungo e con metodo. Nei limiti del poco tempo che possiamo dedicare alla scrittura di articoli, speriamo di aiutarvi a costruirvi un’opinione su materie complesse, informarvi e se possibile divertirvi. I conti del server li paghiamo di tasca nostra e ci riserviamo perciò di moderare i commenti a nostra discrezione.