And so you want to be a game programmer…
16
E così alla fine è arrivata anche la mia parte di questo corso sulla realizzazione di Video Giochi, dopo una prima trance di otto ore, gestita da Gabriele Ferri, sul Game Design, e una seconda, di quattro, proposta da Riccardo Cavalieri, sulla Grafica Digitale. E davanti ad una classe di una ventina di ragazzi (la maggior parte studenti di ingegneria o di informatica), ho iniziato un percorso che, auspicabilmente, dovrebbe fornire almeno una visione di insieme del processo che porta da una idea ad un programma (un gioco!) che gira sul PC e/o sul cellulare o sul tablet. Ammetto che le prime due ore, in cui ho cercato di capire sia il grado di competenza degli studenti, sia le loro aree di interesse, possono essere sembrate abbastanza caotiche. Dopo un discorso più organico iniziale, l’impressione che una lezione passo passo potesse essere superflua per la maggior parte dei presenti (già alle prese con prove per le loro realizzazioni) mi ha fatto propendere per una lezione più rapida ed ampia (abbiamo spaziato tra un mare di tematiche differenti) in modo che si potesse arrivare, come è capitato, almeno ad una definizione più chiara delle prossime due lezioni.
Ma di cosa abbiamo parlato, nello specifico, vi starete forse chiedendo? Beh, nel caso siate curiosi, questo è più o meno il discorso che è stato proposto.
Volete realizzare un videogioco, questo è chiaro. Ma siete sicuri di volerlo PROGRAMMARE? Forse non lo sapete, ma ci sono molti strumenti (alcuni gratuiti, altri a costi contenuti) che permettono di realizzare giochi rapidamente, e senza necessità di conoscere poco più che un semplice linguaggio di script, con ambienti RAD, e normalmente store per comprare risorse (dedicati ad una tipologia specifica come FPS Creator, Shoot’em up Kit, Adventure Maker, RPG Maker, eccetera, oppure più “generici” come GameSalad).
Se volete invece programmare il vostro gioco, cosa è meglio usare? Dipende molto dal gioco che avete in mente, ma anche dal vostro target di uscita. HTML5+javascript (o anche l’ormai vituperato Flash), o Java, permettono di fare giochi “da browser” che al momento possono essere molto simili (o identici) a quelli a cui giocate su cellulare.
Oppure potete lavorare con linguaggi in parte specializzati, normalmente associati a librerie multipiattaforma e a strumenti di sviluppo integrati (come DarkBasic, o, cambiando completamente genere, Inform), oppure con SDK (come Cocos2D o Corona SDK) che vi permettono di lavorare con facilità anche con linguaggi non dedicati.
Ma se volete fare uno sforzo un po’ più grande, avendo come contropartita più libertà d’azione e prestazioni più elevate, rimanendo comunque in ambito multipiattaforma, il mio consiglio è quello di usare un linguaggio più general-purpose, ovvero il C o C++, appoggiandovi (per la maggior parte dei target) direttamente alle OpenGL per la grafica e alle OpenAL per l’audio.
È possibile infatti utilizzare il C/C++ con OpenGL/OpenAL, per fare giochi nativi per Windows / Mac / Linux / iOS / Android / Bada e (almeno per il discorso linguaggio) da poco anche per Windows Mobile. Tutte le piattaforme richiederanno solo un po’ di codice specializzato per fare partire l’applicazione e per “recuperare” l’input o per accedere a particolari tipi di risorse o informazioni, ma un (ridotto) layer in Java (per Android), Object-C (per iOS e Mac OSX), C# per Windows Mobile e in C/C++ per gli altro OS, sarà abbastanza per consentire di avere tutto il resto in comune.
E sappiate che C/C++ hanno svariati compilatori e IDE per praticamente qualunque piattaforma esistente, librerie a basso livello per le cose basilari, enormità di codice d’esempio e di manualistica. Permettendovi quindi da un lato di sviluppare il grosso del vostro gioco per dispositivi mobile dal vostro sistema operativo preferito (con solo la necessità di avere eventualmente accesso ad un computer specifico e al dispositivo fisico target solo quando tutto è come vi aspettate che sia), e dall’altro di trovare facilmente supporto o risorse che vi aiutino nel vostro percorso.
Ma cosa è esattamente un videogioco, se lo si considera dal punto di vista della programmazione?
Un videogioco è un programma che (in astratto, ma a prescindere dalla tipologia o dalla categoria di appartenenza) ha uno schema di questo tipo:
init(); while(!endgame()) { readinput(); gameAI(); moveeverything(); drawandplaysounds(); } reset();
Uno schema microscopico che accomuna però il più semplice dei giochi testuali (come “indovina un numero”) con il più complesso dei giochi 3D, e che può essere applicato (con un piccolo sforzo mentale) anche ai casi di programmazione ad eventi, o nei casi di uso di threading per la gestione di una parte delle operazioni. La fase di input (che può in certi casi sembrare di attesa di input, come in una avventura testuale, o in gioco a turni) è spesso in realtà un semplice check sull’input, che lascia al flusso la libertà di continuare e all’intelligenza del programma (in senso lato) il compito di tenere conto di tutto quello che succede, approfittando (se necessario) del tempo di attesa anche per preparare strategie (capita ad esempio nei giochi come gli scacchi) o anche solo per controllare che le regole del gioco siano rispettate (verificando, sempre ad esempio, lo scadere del tempo, in un puzzle game).
Nota: la lettura dell’input, per un gioco che vuole essere multipiattaforma e comprendere dispositivi differenti come caratteristiche, è il caso che sia virtualizzata (in modo da accettare, ad esempio, il touch su un tablet, e il click del mouse su un PC, o l’interazione con un joypad fisico o virtuale, producendo lo stesso tipo di dati per il codice core del vostro gioco) eventualmente simulando con artifici quei tipi di input (accelerometro, coordinate GPS o altro) che non sono normalmente disponibili nella vostra configurazione di lavoro.
Un gioco però normalmente è più di un programma in cui si entra subito nel cuore dell’azione. Come rientrano gli aspetti che normalmente vediamo (ad esempio una sezione iniziale, una che mostra i punteggi ottenuti, eccetera), nello schema proposto? Semplicemente lo schema base si moltiplica per le varie parti di un gioco, trasformando la sequenza logica di scene un videogame, in una sequenza di loop con le proprie regole di input e le proprie strutture di intelligenza artificiale (che possono anche limitarsi al trasformare un input in un passaggio ad una scena successiva, come l’iniziare il gioco, premendo “Start”). E anche l’esistenza di livelli di gioco diversi, o di scene di intermezzo, o di menu di pausa, possono essere gestiti allo stesso modo. Con cicli autonomi (che possono o meno avere parti in comune) tra i quali si può passare secondo quanto stabilisce il programmatore.
Quindi, se la struttura più ad alto livello di un gioco qualunque è più o meno sempre comune, sarà molto diverso quello che sta “sotto”? Sì, certo, ma solo in parte. Alla fine gli aspetti comuni tra giochi anche molto differenti sono tantissimi. La maggior parte dei giochi ha “attori” (con caratteristiche che variano dalle coordinate, alla grafica, passando da valori che possono andare dalla resistenza e al numero di proiettili, al ruolo di un pezzo di un boardgame, o all’indice di una lettera in un gioco alla Ruzzle) e un “mondo” in cui questi si muovono (una scacchiera, una griglia, un labirinto, eccetera, che può essere stato creato completamente dal programmatore, oppure generato in automatico, seguendo schemi o pattern più o meno complessi) con delle regole precise. Ed esiste un campo di visione del “mondo” in cui ci si muove (l’area visibile in un platform 2d, la telecamera in gioco 3d, piuttosto che l’area intorno alla pallina nel gioco di un flipper) e una regola che determina un punteggio o un metodo per determinare se si vince, o si perde, o quando il gioco viene considerato finito.
Quello che cambia maggiormente tra un gioco e l’altro non è quindi tanto l’aspetto strutturale o formale, ma solo (o soprattutto) l’insieme di regole, l’interazione tra gli elementi, il modo in cui l’input diventa parte della visuale di output. Tutto questo per dire che non importa quanto complesso è il gioco che si ha in mente di fare, perché è molto probabilmente suddivisibile in tanti piccoli sottoelementi (a loro volta risuddivisi in altri sottoelementi) che assomigliano a qualcosa di già visto e relativamente semplice. A patto, chiaramente, che il programmatore riesca a mantenere la visione di insieme, e a decidere quale è il modo migliore e corretto perché tutti questi pezzettini si muovano insieme nel modo desiderato.
Ma se di questo aspetto – non più quindi del fare un gioco, ma del fare IL gioco, il VOSTRO gioco – non abbiamo al momento volontà di parlare (perché, come dicevamo, questo richiede di seguire una sequenza di sentieri che cominciano a differenziarsi in modo specifico), abbiamo ancora almeno due aspetti (comuni alla maggior parte dei giochi) di cui possiamo parlare, che sono la grafica e il suono.
In astratto grafica e suono sembrano due realtà chiare e precise, ma quando si parla di usarle, per realizzare un videogioco, bisogna scindere l’aspetto più teorico (l’essere gradevoli e adatte per i vostri scopi) da quello più concreto (l’essere utilizzabili, per formato, tipologia, dimensione e caratteristiche).
Sulla grafica le macrodivisioni principali sono 2d e 3d. Per il 2d ci si suddivide ancora tra bitmapped e vettoriale, e sul bitmapped ci si suddivide ancora eventualmente tra con e senza trasparenze (jpeg vs png, anche se in realtà molti altri sono i formati “comodi” da utilizzare per entrambe le tipologie). Sul 3d le cose si complicano ancora, e ben prima della divisione tra statica ed animata (frame based o skeleton based), bisognerebbe parlare di formati perché l’utilizzo di grafica 3d richiede più codice per lettura e gestione e perché ogni formato ha i suoi pregi e i suoi limiti. Il più semplice formato 3d da leggere (senza animazioni) è quasi sicuramente il formato WaveFront OBJ, quello che consiglio per le animazioni framebased è il vecchio MD2 (quake), l’ms3d (milkshake 3d) per le animazioni skeleton based. Ma in realtà ognuno deve decidere cosa usare e come, in base agli obiettivi che ha, e alla fine (per entrambe le tipologie di grafica) il formato migliore è quello che gli strumenti che abbiamo a disposizione ci permettono di adoperare al meglio (o di convertire come ci risulterà più comodo utilizzare).
Sul suono le divisioni principali sono tra compresso e non compresso. Ma se si decide di usare le OpenAL compresso può essere quasi solo un aspetto di lettura, e quindi si torna al discorso dei formati da valutare in base alla loro complessità di gestione, come per il discorso 3d. Un buon compromesso (tra dimensione e accessibilità di lettura e decompressione) lo fornisce il formato OGG – tra l’altro nativo ad esempio su Android, ma un formato come l’IMA ADPCM, se si accetta un po’ di perdita in ampiezza, ha un buon compromesso tra compressione e rapidità di decompressione.
Ho dimenticato di riportare qualcosa delle due ore di lezione – oltre ai riferimenti ai giochi su cui gli studenti stanno lavorando? Possibile. Probabile. Anche se questo resoconto dovrebbe più o meno contenere tutti i punti principali di questa prima lunga chiacchierata, che si è conclusa con una richiesta più diretta sugli argomenti (e le modalità) delle prossime lezioni che riguarderanno un esempio pratico di realizzazione di un gioco 2D (lunedì prossimo) e la realizzazione pratica di un piccolo gioco a tre dimensioni (per l’ultimo incontro).