lunedì 18 luglio 2011

Summary: i 5 consigli per sviluppare videogiochi

Ciao a tutti, riassumo qui in un unico post i link ai 5 articoli precedentemente pubblicati.

Come sempre, buon coding!

venerdì 15 luglio 2011

Le 10 frasi che un programmatore non dovrebbe mai dire

Ci sono frasi che un programmatore non dovrebbe mai pronunciare quando si trova al telefono con il cliente che ha un problema (e il cliente al telefono ha sempre un problema). Eccone alcune:

Fase del rifiuto

  1. "Da me funziona..."
  2. "Deve essere un problema di rete"
  3. "Non è fatto per essere usato così"

Fase del dialogo costruttivo

  1. "... e cliccando su Ignora?"
  2. "Come ci siete riusciti?!?"
  3. "C'è Full Control Everyone su tutto il disco?"

Fase dello scarica barile

  1. "E' sicuramente il firewall..."
  2. "Succede solo da voi"

Disperazione

  1. "Gli altri programmi vanno?"

Ultima spiaggia

  1. "Provate a riavviare"

mercoledì 13 luglio 2011

HowTo: svuotare correttamente un STL Container (C++)

La libreria standard del C++ offre numerosi container, oggetti creati per contenere e organizzare altri oggetti. Il più famoso ed utilizzato è probabilmente vector. Molte documentazioni utilizzano però una frase sibillina nello spiegare la funzione del metodo clear() dei container:

il metodo clear elimina tutti gli oggetti contenuti, chiama i rispettivi distruttori, e pone a 0 la size del contenitore.

Una tale definizione sembra mettere al riparo da ogni problema il programmatore che decida (saggiamente) di usare un vector (o una list, un map, o queue) al posto di un comune array o di un oggetto custom. E invece non è così.

Facciamo qui un paio di esempi utilizzando due classi: Enemy e Level. Level conterrà una collezione di oggetti Enemy (anzi, di puntatori ad oggetti di tipo Enemy). Scopo dei due esempi è mostrare come svuotare correttamente tale collezione.

#include <iostream>
#include <vector>

//---------------------------------------------------------------
class Enemy
{
public:
   Enemy();
   ~Enemy();
};

Enemy::Enemy()
{
   std::cout << "Eseguo costruttore Enemy" << std::endl; 
}  

Enemy::~Enemy() 
{     
   std::cout << "Eseguo distruttore Enemy" << std::endl; 
}  

//---------------------------------------------------------------

class Level 
{ 
public:     
   Level();     
   ~Level();  
private:     
   std::vector<Enemy*> m_Enemies;
};

Level::Level()
{
   // creo e inserisco tre elementi Enemy nel vector     
   std::cout << "Eseguo costruttore Level" << std::endl;     

   m_Enemies.push_back(new Enemy());     
   m_Enemies.push_back(new Enemy());     
   m_Enemies.push_back(new Enemy()); 
}  

Level::~Level() 
{     
   // ripulisco il vector
   std::cout << "Eseguo distruttore Level" << std::endl;           
   m_Enemies.clear(); 
}  

//-------------------------------------------------------------- 

int main() 
{     
   Level* lev = new Level();      
   delete lev;      
   return 0; 
}  

Evidenziamo la classe Level, in particolare il suo distruttore. Notiamo che m_Enemies viene pulito tramite il metodo clear(). Sembra logico. Quel che ci attende però dopo l’esecuzione è questo output:



Mancano le chiamate al distruttore di Enemy, il che significa che clear() non ha correttamente liberato la memoria. La documentazione non è sbagliata, solo poco chiara. Se avessimo riempito il nostro vector con degli oggetti concreti anzichè con dei puntatori, il distruttore sarebbe stato chiamato correttamente. Ma, come nella maggior dei casi reali, abbiamo usato puntatori, e il programma non sa quale distruttore andare a pescare per distruggere l’oggetto puntato. Dobbiamo andargli un po’ incontro noi e modificare il distruttore di Level così:

Level::~Level() 
{     
   // ripulisco il vector     
   std::cout << "Eseguo distruttore Level" << std::endl;   
   
   while(!m_Enemies.empty())
   {
      Enemy* obj = m_Enemies.front();
      delete obj;
      m_Enemies.erase(m_Enemies.begin());
   }
}

E’ un po’ più lungo ma l’effetto è garantito. Quel che facciamo è ciclare sul vector finchè non risulta vuoto e ogni volta prendiamo l’elemento in testa. Chiamiamo esplicitamente il distruttore dell’oggetto con la delete ed eliminiamo il puntatore dal vector tramite erase, che diminuisce anche la size, impedendoci di entrare in loop con la guardia del while.

L’esecuzione darà ora questo risultato:



Buon coding!

lunedì 11 luglio 2011

Il gioco indie che forse non conoscete: Canabalt!

Il panorama indie è molto più sviluppato di quanto mediamente si creda. Non solo. E’ anche molto più evoluto, con giochi anche di alta qualità. Alcuni fanno della semplicità il loro punto di forza, ma attenzione: è una semplicità solo apparente, quasi più una ricerca estetica del minimale che un obbligo per mancanza di risorse.


Un valido esempio è Canabalt, un gioco flash giocabile via browser, sicuramente conosciuto a chi già segue la scena indie. L’idea di base di Canabalt è semplice e geniale. Voi siete un omino, e correte. Correte senza potervi fermare. Potete solo sperare di accelerare, ma fermarvi mai. 

Lo scenario è un grigio 2d urbano. Sulla vostra strada troverete ostacoli di ogni tipo, da evitare saltando. Salterete di tetto in tetto, entrerete negli edifici sfondando in volo le finestre, ruzzolando sul pavimento, in una breve illusione di pacifica staticità, solo per rialzarvi e rimettervi a correre.

Avrete una sola vita e la giocherete usando un solo tasto. Dal momento in cui inizierete a correre, sapete che potrà finire solo in due modi: o cadendo in un baratro, o schiantandovi contro un muro. Il vostro successo sarà calcolato in base a quanta strada avrete percorso. L'autore ha evidentemente una visione piuttosto tetra dell'esistenza... o forse è semplicemente realista?

Già, perchè non c’è tempo per riflettere. Si trattiene il respiro. I toni di grigio diventano la tavolozza ideale, anzi l’unica possibile, per dipingere sullo schermo Canabalt... che è poi la metafora del vivere d’oggi.


venerdì 8 luglio 2011

5 consigli pratici per sviluppare videogiochi (parte 5)

Nei quattro articoli precedenti abbiamo visto altrettanti consigli su come affrontare lo sviluppo di un videogioco, in particolare:

  1. Come gestire le idee
  2. Come scegliere gli strumenti da utilizzare
  3. Quali competenze possedere
  4. Da dove partire per fare esperienza e ricevere ispirazione

Il quinto consiglio arriva non a caso come ultimo. Si tratta del più importante, quello che in qualche modo li racchiude tutti, ma anche del più difficile da seguire.

Consiglio #5: Termina quel che inizi


Non c’è nulla di più difficile, veramente. Gli hard disk di migliaia di aspiranti game developer sono zeppi di progetti abbandonati, mentre i giochi finiti sono infinitamente meno. Il mio, naturalmente, non fa eccezione. Dopotutto qualcuno (Oscar Wilde?) diceva di poter accettare prediche solo da chi aveva (molto) peccato.

Ma perchè un progetto viene abbandonato? In fondo siete partiti con una grande idea, l’avete curata e limata a dovere, avete configurato tutto l’ambiente per poterla sviluppare, avete studiato per colmare le vostre lacune o per risolvere i problemi inattesi. Quindi? Perchè mai uno vorrebbe gettare via tutto questo lavoro? Sembra illogico, invece è purtroppo più la regola che l’eccezione.

Esistono in realtà diversi motivi, e forse analizzarli può aiutare a comprenderli e, se possibile, evitarli.

Il Dubbioso
Forse la vostra idea iniziale, che tanto vi ha entusiasmato nelle sue prime 24 o 48 ore di vita, non era poi un gran che. Ve ne siete resi conto solo dopo, magari in seguito ai primi sviluppi, quando avete iniziato a capire veramente quale sforzo comportava realizzarla. A che scopo?, ecco la domanda assassina che vi è balzata in testa. Crudele, ma forse necessaria. Non cercate l’accanimento terapeutico e lasciate morire in pace il progetto. Il vostro prossimo tentativo terrà maggiormente in considerazione il primo consiglio.

L'Ottimista
Forse avete fatto i conti senza l’oste. Le features a cui avevate pensato erano apparse molto più alla vostra portata. Sulla carta tutto sembrava più semplice, anche perchè forse alcune problematiche pratiche sono semplicemente emerse dopo. Non sapevate di non sapere. Poco male, avete perso il progetto (per ora), ma avete guadagnato molto a livello personale: possedete ora una maggiore percezione dei vostri limiti e di quel che occorre per creare un gioco. Sapete in quali campi applicarvi per studiare e colmare le mancanze. Fatelo!

Il Disorientato
Forse siete stati colti da noia improvvisa. L’idea era buona, era anche tutto sommato realizzabile, ma dopo due mesi ancora non siete arrivati a qualcosa di giocabile, e quel momento sembra perso in un orizzonte indefinito. Se potete stringete i denti, tagliate qualcosa e cercate di terminare in un altro paio di giorni (al massimo). Se questo non è possibile vuol dire che vi siete imbarcati in un progetto troppo grande per voi, non tanto per difficoltà ma proprio per dimensioni. Piccolo errore di valutazione iniziale, ma la prossima volta andrà meglio.

Il Curioso
Forse vi siete distratti. Avete visto qualcosa che luccicava di più, avete sospeso momentaneamente i lavori (promettendo a voi stessi che non stavate abbandonando nulla, che poi mi ci rimetto!) e vi siete lanciati nello studio di questa nuova tecnologia/libreria. Riprendere in mano il progetto, man mano che passano i giorni, diventa sempre più un’utopia. Siate almeno onesti con voi stessi. Non lasciate i lavori nel limbo. Tagliate quel cordone ombelicale e andate avanti. Forse la nuova cosa che ha rubato la vostra attenzione merita veramente un tentativo.

Come vedete, di motivi ce ne possono essere veramente tanti. Analizzandoli, si possono trarre delle interessanti conclusioni su come non cadere in tali trappole. In particolare si evince che:


  • I progetti vincenti sono quelli che potete realizzare, non quelli che volete realizzare
  • I progetti vincenti sono quelli fattibili in x giorni, dove x è un numero discreto, ben noto a priori, variabile a seconda del soggetto (voi). Determinarlo è un processo a tentativi. Datevi delle scadenze.
  • Restate focalizzati. Mantenete l’attenzione su cosa state facendo per gli x giorni che servono a farlo. Abbiate fretta di giungere a qualcosa di completo. Non pensate a ottimizzazioni o a particolari abbellimenti. Fate il vostro gioco. Fatelo grezzo. Ma fatelo.
  • Se x sono i vostri giorni per completare il progetto, spenderne la metà o più in analisi, meditazioni e pianificazioni non vi porterà da nessuna parte. Pianificate l’inizio, decidete la rotta e poi partite immediatamente. Tanto non finirete dove avevate pensato nemmeno con un documento di design di 100 pagine.
  • Le dimensioni del precedente progetto vi hanno costretto ad abbandonarlo? Il prossimo pianificatelo per essere il 50% del precedente.
  • Avete già fallito in n progetti precedenti? Continuate a fallire per via degli stessi motivi? Apparentemente non imparate nulla dai vostri errori? Errare è umano, ma perseverare è proprio da programmatori. Siete finiti in un loop mentale. Reset. Anzi, break.


Soprattutto non scoraggiatevi e non demoralizzatevi. Mai. Ci sono fior fior di illustri personaggi che sono passati (e che ci passano ancora!) da questi tristi lidi. Eppure producono giochi di successo.

Vi lascio con un recente post di Thomas Biskup, il creatore di ADOM, uno storico roguelike. Attualmente (già da un po’ di tempo, a dire il vero... eh Tom?) è alle prese con JADE, una sorta di porting Java di ADOM, più moderno e ricco di features. Ma anche, evidentemente, più complesso. Ecco un suo post a proposito, che riprende un po' le conclusioni a cui siamo arrivati noi.

Concludendo...

Non so se questa serie di post aiuterà realmente qualcuno a realizzare il proprio ambizioso desiderio di scrivere un videogioco. Se lo farà, ne sarò felice. Ma lo sarò anche solo se qualcuno si sentirà motivato e invogliato a provarci!

Buon coding!

Post correlati:

mercoledì 6 luglio 2011

5 consigli pratici per sviluppare videogiochi (parte 4)

Ci siamo quasi. Abbiamo le idee chiare, i tool giusti e tutte le abilità necessarie per fare un videogioco. Ci manca solo un po’ di esperienza, di palestra.

Programmare è una abilità che, come tutte le abilità, migliora con la pratica. Difficilmente produrremo il nostro capolavoro al primo tentativo. Occorre invece fare molto e sbagliare molto, oltre naturalmente alla capacità di riconoscere e correggere i propri errori.

Alcuni errori, tuttavia, non si palesano immediatamente come tali. Anzi, spesso ci appaiono come nostre particolari, addirittura geniali, interpretazioni di una regola. Nella programmazione questo accade frequentemente, essendo una attività creativa e quindi volta al problem solving e alla costante ricerca di modi diversi per fare qualcosa.

In quasi ogni progetto, ad esempio, implemento in modo diverso la gestione dei messaggi tra i componenti dell’applicazione. Ogni volta termino con un certo orgoglio, felice della complicata massa di classi e pattern che si interfacciano in modi sempre più sofisticati. Salvo poi riaprire il progetto qualche giorno dopo, e capire di non capirci più nulla. Ogni volta la conclusione è la stessa: la prossima volta devo semplificare qualcosa.

Programmare è una questione di raffinamenti successivi, roba per cui occorre esperienza. Non esiste altra via.

Ma per fare esperienza occorre, indovina un po’... programmare! Dopotutto siamo informatici e la ricorsione non dovrebbe spaventarci. Quindi...

Consiglio #4: Copia i Classici


Il consiglio di questo articolo riguarda proprio il come fare esperienza. Potete lanciarvi subito nell’implementare le vostre idee, certo, ma forse non è il modo migliore. Quando scrivete il vostro gioco siete impegnati su molti fronti, primo fra tutti l’analisi e la ricerca di meccaniche avvincenti e divertenti, oltre che semplici da implementare. Fare esercizio dovrebbe invece essere una attività più focalizzata. Ci si esercita meglio e con maggior profitto se l’area su cui si vuole lavorare è contenuta. Esistono centinaia (migliaia?) di giochi già consolidati e dal provato valore di intrattenimento. Sapreste riprodurli?

Prendiamo Tetris. Tutti lo conosciamo e ci abbiamo giocato. Non ci occorre ragionarci per più di un paio di minuti per focalizzarne gli aspetti principali del gameplay. Dovremmo anche riuscire a vederne mentalmente il codice e capire di quali componenti è fatto:


  • l’area di gioco (una semplice sezione rettangolare dello schermo, nera o con un’immagine di sfondo);
  • l’anteprima del blocco successivo
  • l’area dei punteggi
  • il blocco corrente, unico elemento che si muove (in automatico verso il basso e con l’interazione del giocatore per le rotazioni e i movimenti laterali)
  • il muro che si forma
  • le righe complete (da riconoscere ed eliminare in tempo reale, abbassando il muro)
  • il muro che raggiunge la cima dell’area di gioco (condizione di gameover)
  • il numero di righe completate che raggiunge il numero stabilito dal livello (condizione di vittoria)



Una volta fatta questa lista avete messo nero su bianco le caratteristiche fondamentali di Tetris. Potete considerarla il documento di analisi e design, o la lista dei requisiti! Il gioco funziona, non dovete preoccuparvi di aspetti quali regole e giocabilità. Dovete solo scriverlo.

Tetris è, naturalmente, solo un esempio, ma non l’ho citato a caso. E’ in effetti uno dei primi giochi che andrebbero scritti, perchè fornisce una ottima palestra per comprendere i meccanismi di base di un videogioco: il game loop (ricevi ed elabora l’input, aggiorna lo stato degli oggetti, disegna il frame), le collisioni e la gestione della logica (punteggi, passaggi di livello).


Altri giochi sono l’immancabile Pong, Breakout (Arkanoid), Space Invaders, Asteroids... una cosa molto divertente e stimolante che potete fare è scaricarvi e installarvi il progetto Mame32, che contiene una vera miniera di giochi arcade anni ‘80-’90. (Ri-)Scopriteli e giocateli. Riuscirete a trovarne decine e decine da clonare per esercizio e, perchè no, anche da migliorare con vostre aggiunte.

Quando avrete implementato un paio di questi classici non solo avrete acquisito molte conoscenze indispensabili, ma avrete affinato il vostro stile di programmazione e la vostra mente. Sarete in grado di guardare ai giochi più complessi con maggior senso critico. Capirete (e riconoscerete in altri giochi, anche più recenti) le meccaniche di gameplay caratteristiche dei vari generi (platform, puzzle, shooter...).

E, cosa più importante, potrete finalmente dire: io scrivo videogiochi!



Post correlati:


 

lunedì 4 luglio 2011

Il gioco indie che forse non conoscete: Appy 1000mg!

Ludum Dare è un concorso online, ormai storico e giunto alla 20esima edizione, che sfida i partecipanti a produrre un gioco funzionante in 48 ore. Il gioco viene poi valutato secondo molti aspetti, ma non è del Ludum Dare che intendo parlare, bensì del vincitore di questa 20esima edizione: Appy 1000mg.

Un titolo curioso, come da tradizione indie, ma che si svelerà nel suo terribile significato solo finendo il (breve) gioco. Per la cronaca si tratta di un platform, ma questa definizione lascia il tempo che trova. Sarebbe più opportuno etichettarlo come Poesia. Una poesia molto triste, tra l’altro. Appy 1000mg si lascia finire in meno di 10 minuti ma può arrivare a commuovere i più sensibili! Ancora una volta lo sviluppo indie ha dimostrato la sua incredibile capacità di descrivere la realtà, soprattutto nei suoi aspetti più oscuri.


Il gameplay è essenziale. All’inizio del gioco possiamo solo saltare, vagando per un ambiente bucolico fatto di erba verde e bubbies, simpatiche e innocue creaturine rosa. Nelle fasi più avanzate avremo a disposizione anche uno zainetto jet col quale compiere piccoli voli e raggiungere così piattaforme altrimenti impossibili.

La grafica è eccellente e sembra quasi incredibile che sia stata concepita e realizzata in appena 48 ore! Non è semplicemente ben curata, ma riesce a dare un vero tocco di personalità all'intero gioco, aumentando il senso di immersione nel piccolo mondo. Il blog di sviluppo (eh già, questo ragazzo ha anche avuto il tempo di scrivere post!) svela qualche dettaglio relativo al sistema utilizzato per il rendering della mappa, che inizialmente doveva essere random ma che poi, per motivi di praticità, è stato declassato a semi-random. Le informazioni sul terreno di gioco sarebbero lette da una bitmap di 400x100 pixel, scalata a 4x e creata tramite un algoritmo basato sul deposito di sedimenti. Anche il particle engine è stato sviluppato ad hoc per l'occasione, e il risultato è veramente notevole.

L’autore ha prodotto anche una seconda versione del gioco, fuori concorso, nella quale intende migliorare il gameplay aggiungendo elementi ed ampliando il mondo (e magari inserendo una colonna sonora). Ma la sensazione è che quel che Appy 1000mg aveva veramente da dire, l’abbia detta. E’ sicuramente possibile migliorare il gioco, ma la scintilla d’arte che c’è dentro è già perfetta.


Appy 1000mg è un gioco che difficilmente vi lascerà indifferenti. Nella piccola manciata di minuti che vi ruberà riuscirà a farvi sorridere, preoccupare, divertire e, soprattutto, riflettere. Già, perchè il senso di inquietudine con cui affronterete l'ultima fase non sarà dato solo dall'improvvisa svolta della trama e dall'uso di pixel dai colori più scuri, ma dal fatto di riconoscere situazioni tristemente reali, e di mescolare la pietà con l'orrore.