Scripting Engineering Tutorial

Realizzare un gioco no è certo un'impresa facile, specie se lo si debba realizzare da soli. Chir ci è venuto incontro realizzando il MAGE/IJ, un motore scritto in Java che ci consente di realizzare delle avventure grafiche in stile "Vecchia Lucas" (Monkey Island 1 e 2, Indiana Jones 3 e 4, Loom...) senza la necessità di conoscere il JAVA.
Basta conoscere il linguaggio del MAGE, che è un linguaggio molto semplice ed intuitivo...
 
... ma questo non significa che realizzare un gioco sia diventata una cosa facile! :-)
 
Ci sono tanti problemi e tanti ostacoli, per cui bisogna cercare di ottimizzare al meglio (come fanno i veri ingegneri) le nostre possibilità, il nostro tempo e la nostra... mente!
Personalmente non mi ritengo certo un guru della programmazione, ma ho abbastanza esperienza per darvi qualche suggerimento utile. :-) Cominciamo!
Una nota x chi si senta programmatore: leggete anche le prime "lezioni", potreste trovare errori o suggerirmi strade migliori... e fare un bel ripasso ;-)


Innanzitutto cominciamo dalle cose fondamentali: la storia e la sceneggiatura!
Non basta avere in mente una bozza di storia, occorre anche avere una sceneggiatura su cui basarsi. La cosa ideale sarebbe avere la sceneggiatura completa, con tanto di dialoghi, descrizioni e quant'altro, ma possiamo anche utilizzare una sceneggiatura meno dettagliata... ma pur sempre completa! Personalmente, questo è quanto io abbia usato per l'introduzione delle Andy's New Adventures, e che vi riporterò qui come esempio.

E questa è la nostra storia (limitata all'introduzione). Adesso vediamo la sceneggiatura corrispondente: Come potete notare, la sceneggiatura è mooooolto più dettagliata della storia: è più che naturale! Nella sceneggiatura dovrebbero esserci la descrizione delle stanze, la descrizione dei personaggi, i dialoghi e quant'altro: la sceneggiatura è anche lo strumento tramite il quale il grafico/disegnatore riesce a tradurre i pensieri dello sceneggiatore. Occorre quindi dargli quante più informazioni possibili! Questo non significa che bisogni dire proprio tutto tutto... ad esempio nella sceneggiatura ho citato una locanda, degli avventori ed una guardia. Non avendo particolari esigenze, la libertà lasciata al grafico (Riktik) è stata praticamente completa, ed anzi l'immagine della taverna che mi ha fornito è l'esatto opposto di quella che io avevo in mente! Questo non è un problema in questo caso, ma potrebbe esserlo in altre situazioni. Del resto il disegnatore (guardatevi anche il tutorial di Riktik), sfrutta abbondantemente la sceneggiatura per creare i paesaggi: se in una stanza l'azione si svolge vicino ad un caminetto, un disegnatore furbo (come insegna Riktik) lo utilizzerà come cuore dell'immagine... ma sto cominciando a divagare un po' troppo... la cosa fondamentale è quindi: prima di cominciare a scrivere il codice del gioco, bisogna avere la sceneggiatura dello stesso, il più dettagliata possibile.
 
Notate poi come all'interno della sceneggiatura siano state isolate le scene una ad una, indicandone la cronologia e gli avvenimenti. E' come se steste raccontando un film indicando tutto quel che accada... ;-)  
Vediamo cosa riesco adesso a combinare con questa sceneggiatura...


Il primo "comandamento" è quindi di avere una sceneggiatura, e noi l'abbiamo. Cosa facciamo? Cominciamo a tradurla in codice? No.
 
Prima di cominciare a scrivere il codice bisogna fare delle altre cose, che però esulano da questo tutorial. Le elenco semplicemente:

  1. Decidere la risoluzione da utilizzare per il gioco: a questo scopo date un'occhiata alla mia guida al MAGE in cui spiego come calcolare le proporzioni e le dimensioni dell'area di gioco.
  2. Trovare un disegnatore o mettersi di buona lena su matita, china, scanner, programma di grafica (vedi il tutorial di Riktik).
Una volta che avremo tutto... possiamo cominciare.
 
Un mio professore di qualche corso di ingegneria del software una volta disse: “Ogni volta che riscrivi un pezzo di codice, la probabilità che tu faccia un errore aumenta”. Ha ragione: è vero!
Se devo compiere una operazione e mi invento un algoritmo (per chi non lo sapesse: algoritmo significa una sequenza ordinata di passi da compiere per svolgere una qualche cosa) buono e che funziona... lo metto nel codice. Poi mi serve di nuovo. Lo riscrivo.
 
Ma no, io sono moderno! Se è vero che scrivendolo due volte è facile che sbagli... faccio copia e incolla e risolvo il problema.
 
Facendo copia e incolla si risolve il problema della molteplice riscrittura del codice, è vero... ma non si scappa da un altro problema: stanotte ho trovato una soluzione migliore, un algoritmo più rapido, più bello, più facilmente modificabile in futuro. Che faccio? Devo cambiare ogni file in cui ho scritto quel pezzo di codice! Con il rischio di dimenticarne qualcuno...
 
La soluzione è quella di scrivere l'algoritmo UNA SOLA VOLTA, e poi "citarlo" dovunque serva: quando volessi modificarlo, basterà cambiare un solo file, e la cosa si rifletterà dappertutto. Inoltre abbiamo file di dimensioni più piccole e più leggibili. :)
 
Il MAGE ci da' questa possibilità... ma a noi serve? Ho parlato a vanvera oppure la cosa ci torna utile?
 
Abbiamo deciso la risoluzione del nostro gioco, allora cominciamo a scrivere...
Una faticaccia... ma ne è valsa la pena: abbiamo scritto tutta la nostra interfaccia. Dove la mettiamo?
Beh, mettiamola nell'introduzione, nel primo capitolo, nel secondo capitolo, nel...
 
E poi quando dobbiamo cambiare l'immagine di un verbo ci tocca mettere mano a tutto?!? Search&Replace?
 
Chiamiamo il file: interface.adv dopodichè in ogni file dello script inseriamo questa riga, prima di ogni altra istruzione:
In questo modo le modifiche all'interfaccia saranno più sicure, rapide e concentrate.
Può però sorgere la domanda: io voglio avere 4 frame al secondo (blocco FPS) nell'introduzione, e ventiquattro FPS nel primo capitolo. Che faccio?
 
Basta inserire, dopo la riga di importazione dell'interfaccia, un blocco FPS { 24 } all'interno dello script del primo capitolo: il MAGE legge il valore dell'interfaccia per primo, poi continua nella lettura dello script e trova un nuovo valore, il vostro 24. Capisce che ogni modifica è quella "giusta" e usa 24 frame al secondo. È per questo motivo, peraltro, che nel blocco TITLE dell'interfaccia abbiamo scritto poco: in ogni .adv metteremo quel che serve!
Vediamolo subito: stiamo realizzando l'introduzione, quindi il nostro intro.adv sarà fatto così.
Un suggerimento: lasciate gli stessi FPS per tutto il gioco, ha un risultato più pregevole per l'occhio ed il cervello ;-) Qui mi serviva una cavia e ho scelto il blocco FPS.
 
Parola d'ordine di questa sottolezione: "Economia di codice & Riusabilità"


Apro una piccola parentesi sul modo in cui scrivere lo script... qui sopra avete visto un modo di farlo, ma avrei anche potuto fare così:

Il MAGE capisce benissimo quel che sia scritto, perchè quando legge ignora gli spazi vuoti: basta che siano rispettate le righe! Quindi, siamo chiari, lo script funziona... però è assolutamente incomprensibile!
Come avete visto nel MAGE si lavora a blocchi e sottoblocchi: SYSTEM ci fornisce l'interfaccia, al suo interno c'è il sottoblocco FPS, ma c'è anche il sottoblocco INVENTORY che ha altri sottoblocchi...
Ho fatto un esempio scemo senza grandi sottoblocchi, ma immaginatevi una situazione normalissima di questo tipo:
blocco STANZA, con dentro (tra le tante cose) un blocco PERSONAGGIO, con dentro (tra le tante cose) un blocco OGGETTO, con dentro i blocchi dell'oggetto... senza l'indentazione (lo spostarsi con gli spazi o i caratteri di tabulazione) si diventa facilmente pazzi cercando di capire a quale blocco appartenga un sottoblocco. Con l'indentazione si rischia di meno la pazzia ;-)


Ok, finalmente cominciamo con le cose "serie". Bisogna cominciare a scrivere il codice... e qui arriva la vera "ingegnerizzazione". A che serve? Perchè ci serve?
 
Ogni oggetto, personaggio, stanza che apparirà nel vostro gioco avrà un nome, e questo nome deve essere uni(vo)co: non potete avere due guardie dal nome "guardia" o due stanze chiamate "trappola_mortale". Potete farlo solamente se si trovano in file .adv diversi ma occhio! Diversi non significa che mettete "trappola_mortale" in un file, nel secondo pure e poi ci scrivete IMPORT "il_primo_file.adv"!!!
Si tratterebbe in pratica dello stesso file!
 
Occorre quindi scegliere dei nomi diversi. Possiamo provare a fare così:

Ehy, ma aspetta: c'è poi un'altra stanza in cui ci sono proprio due guardie davanti ad una porta! Che facciamo? È un'idea, ma non sembra la migliore... si può fare di meglio.
  1. Dividere gli oggetti nelle seguenti categorie: oggetti che servono solo come sfondo, oggetti che fanno parte dello sfondo ma possono parlare o essere raccolti (sparendo quindi dallo sfondo), oggetti intelligenti con cui si può interagire, parlare, possono muoversi etc.
  2. Inventarsi uno standard per dare dei nomi agli oggetti in modo da facilitarsi la vita.
  3. Ricordarsi che ogni oggetto ha virtualmente ALMENO una immagine associata, quindi bisognerà impazzire un pochino anche per i nomi delle immagini!
Che cosa ci guadagniamo con questa analisi?
prima_guardia era un oggetto con cui potevamo parlare: seconda categoria.
seconda_guardia era un oggetto con cui potevamo interagire e che poi si poteva muovere o allontanarsi: terza categoria.
prima_guardia_davanti_porta e seconda_guardia_davanti_porta erano solamente due oggetti di sfondo per non lasciare vuoto il corridoio.
 
Fatta questa analisi, chiamiamoli in questo modo:
In questo modo le cose si sono semplificate: non dobbiamo più impazzire a ricordare quale fosse la prima e quale la seconda guardia, le riconosciamo in base a quel che sappiamo facciano! Inoltre le due che servivano solo come sfondo hanno un nome che è chiaramente identificabile come oggetto da sfondo.
 
Questo discorso, come anticipato, va allargato anche al nome delle immagini! Innanzitutto l'idea è quella di separare le immagini in cartelle. Tutto quel che riguarda l'interfaccia (bottoni etc etc) lo mettiamo in gr/gui/ [da Graphical User Interface], quello che riguarda il nostro personaggio principale (o i nostri personaggi principali) possiamo metterlo in gr/hero/, dopodichè possiamo separare o con una cartella per ogni stanza o in qualche altro modo che ci sembri comodo. Ad esempio gr/sfondi/, gr/oggetti_di_sfondo/. gr/ombre/, gr/personaggi/, gr/animazioni/... diciamo che qui dipende un po' dal numero di immagini e dalla comodità che si abbia nello sfogliarle.


Torna alla pagina principale del MageGDT