State usando un IHttpHandler (.ashx) nel vostro progetto asp.net e quel maledetto script ajax crasha perché l'oggetto Session nel context dell'handler è nullo?
Niente paura, la soluzione c'è ed è tremendamente semplice: basta dichiarare l'handler come implementazione dell'interfaccia IRequiresSessionState o, in alternativa, di IReadOnlySessionState, a seconda dei gusti.
Le due interfacce fungono praticamente da attributi, dato che sono vuote! Ma il risultato è tutt'altro che vuoto: la Session sarà ora correttamente popolata.
Buon coding!
martedì 23 ottobre 2012
lunedì 17 settembre 2012
.NET e la OpenFileDialog che fa crash!
Appunto di viaggio: se stai usando una OpenFileDialog e improvvisamente tutta la tua applicazione diventa instabile con crash nei punti più strani, non disperare. Il web ti dirà tante cose, come usare la Dispose o impostare la dialog a null dopo il suo utilizzo, oppure ancora aprire la dialog all'interno di un child MDI. Non dargli retta. Fai invece così, prima di chiamare la fatidica ShowDialog:
dialog.RestoreDirectory = true;E vai con fiducia.
giovedì 30 agosto 2012
Android: Only the original thread that created a view hierarchy...
... can touch its views.
Sì, il maledetto messaggio che vi da il log degli errori quando una funzione invocata da un thread secondario cerca di modificare qualcosa nella GUI dell'Activity, ad esempio nascondere una progress bar attiva.
Si risolve facilmente, per fortuna. E' sufficiente dare a Cesare quel che è di Cesare, ovvero forzare l'esecuzione della funzione incriminata all'interno del thread che gestisce la user interface. Così:
Buon coding!
Sì, il maledetto messaggio che vi da il log degli errori quando una funzione invocata da un thread secondario cerca di modificare qualcosa nella GUI dell'Activity, ad esempio nascondere una progress bar attiva.
Si risolve facilmente, per fortuna. E' sufficiente dare a Cesare quel che è di Cesare, ovvero forzare l'esecuzione della funzione incriminata all'interno del thread che gestisce la user interface. Così:
runOnUiThread(new Runnable(){
@Override
public void run() {
// qui il codice che crea l'errore
// ...
}
});
E il gioco è fatto. Tanto semplice quanto facile da dimenticare.Buon coding!
venerdì 24 agosto 2012
HowTo: Primi passi per sviluppare un Flash Game
Circa sei mesi fa ho deciso di smettere di snobbare ActionScript e cimentarmi nell'esperimento di produrre un gioco Flash. Tutt'ora non sono ben sicuro sull'usare il termine Flash piuttosto che Flex, ma ci siamo capiti.
La prima bella sorpresa è stata essersi trovati di fronte ad un linguaggio, ActionScript 3 appunto, che nulla aveva a che fare con lo script, termine che personalmente ho sempre relegato, sbagliando per carità, a qualcosa di riduttivo, disordinato, poco elegante e anche un po' sporco. No, quello che mi trovavo tra le mani era un vero linguaggio di programmazione, con tutta la dignità di un Java o un C# (e, a mio personale giudizio, anche la medesima comoda curva di apprendimento e immediata produttività).
La seconda bella sorpresa è stata scoprire un ottimo IDE free e ottime librerie a supporto. Ma...
...c'è un ma, e anche bello grosso. Prima di arrivare a tutto questo, infatti, mi sono trovato veramente spaesato in mezzo ad una miriade di possibilità e opzioni, senza una vera bussola che non fosse bussare in qualche forum, pigiare tasti Cerca e, naturalmente, chiedere a Google. Alla fine di questo processo di documentazione sono giunto ad una mia configurazione. La reputo produttiva, completa e, soprattutto, semplice, quindi la condivido qui su questa pagina.
Naturalmente non possiedo una licenza per Adobe Flash in nessuna sua forma o versione ma, anche se fosse, non avrei di certo perso l'occasione di provare un ottimo IDE open source quale FlashDevelop.
Il download per Windows sono circa 16 mega di ambiente fresco e pulito, con già tutte le librerie necessarie per partire con lo sviluppo di numerose tipologie di progetti con target non solo il noto Player di Adobe, ma anche AIR, l'ambiente (sempre di Adobe) per applicazioni desktop.
Come IDE, a parte essere bello (ho una passione per gli editor di testo, per cui passatemi l'aggettivo), è anche piuttosto completo e performante, comprendendo features come l'autocompletamento, l'intellisense (ma che funziona, non come quella di Code::Blocks...), un buon debugger (non come... ah, l'ho già detto), opzioni per il refactor e via dicendo.
La prima cosa da fare, quindi, è andare sul sito di questo ottimo progetto, scaricarselo e installarlo.
A questo punto si tratta di utilizzare FlashPunk per istanziare il suo Engine e iniziare a creare i Worlds, qualcosa che somiglia moltissimo ad una gestione degli stati. Ma tutto questo è spiegato benissimo nei tutorial sul sito di FlashPunk quindi, as usual,
buon coding!
La prima bella sorpresa è stata essersi trovati di fronte ad un linguaggio, ActionScript 3 appunto, che nulla aveva a che fare con lo script, termine che personalmente ho sempre relegato, sbagliando per carità, a qualcosa di riduttivo, disordinato, poco elegante e anche un po' sporco. No, quello che mi trovavo tra le mani era un vero linguaggio di programmazione, con tutta la dignità di un Java o un C# (e, a mio personale giudizio, anche la medesima comoda curva di apprendimento e immediata produttività).
La seconda bella sorpresa è stata scoprire un ottimo IDE free e ottime librerie a supporto. Ma...
...c'è un ma, e anche bello grosso. Prima di arrivare a tutto questo, infatti, mi sono trovato veramente spaesato in mezzo ad una miriade di possibilità e opzioni, senza una vera bussola che non fosse bussare in qualche forum, pigiare tasti Cerca e, naturalmente, chiedere a Google. Alla fine di questo processo di documentazione sono giunto ad una mia configurazione. La reputo produttiva, completa e, soprattutto, semplice, quindi la condivido qui su questa pagina.
Step 1: un IDE di nome FlashDevelop
Naturalmente non possiedo una licenza per Adobe Flash in nessuna sua forma o versione ma, anche se fosse, non avrei di certo perso l'occasione di provare un ottimo IDE open source quale FlashDevelop.
Il download per Windows sono circa 16 mega di ambiente fresco e pulito, con già tutte le librerie necessarie per partire con lo sviluppo di numerose tipologie di progetti con target non solo il noto Player di Adobe, ma anche AIR, l'ambiente (sempre di Adobe) per applicazioni desktop.
Come IDE, a parte essere bello (ho una passione per gli editor di testo, per cui passatemi l'aggettivo), è anche piuttosto completo e performante, comprendendo features come l'autocompletamento, l'intellisense (ma che funziona, non come quella di Code::Blocks...), un buon debugger (non come... ah, l'ho già detto), opzioni per il refactor e via dicendo.
La prima cosa da fare, quindi, è andare sul sito di questo ottimo progetto, scaricarselo e installarlo.
Step 2: una libreria di nome FlashPunk
Non intendevo affrontare il framework Flex di petto, lo ammetto. Frequentando come giocatore diversi giochi Flash mi ero reso conto che molti condividevano parecchie caratteristiche comuni, vuoi nei font, vuoi nei loghi in apertura. Le paroline Powered by riportate nei credits indicavano quasi sempre un paio di nomi: FlashPunk o Flixel.
Dilemma. Alla fine ho scelto FlashPunk con la stessa angoscia con cui in terza media decidiamo dove indirizzare le nostre vite. Anche la conoscenza di cosa scartavo era più o meno la stessa, così come la profondità delle motivazioni di tale scelta: di FlashPunk mi è piaciuto di più il sito. Ma anche la documentazione.
Step 3: Hello World
Provenendo dal C++ ed essendo FlashPunk un framework opensource di cui avevo appena scaricato i sorgenti ero già pronto a perdere non meno di 4 ore nel farli accettare al compilatore e farli trovare al linker, e invece mi sbagliavo. Mi ci sono voluti 30 secondi, 20 dei quali spesi in pausa di sorpresa.
E' infatti sufficiente fare copia/incolla della cartellina con i sorgenti di Flashpunk all'interno della cartella src del vostro progetto (creata dall'IDE) e il gioco è fatto.
Quale tipo di progetto creare? Già, in effetti se c'è una cosa un po' spaesante è proprio la quantità di tipologie di progetti realizzabili con FlashDevelop, ma quello che interessa a noi è AS3 Project!
A questo punto si tratta di utilizzare FlashPunk per istanziare il suo Engine e iniziare a creare i Worlds, qualcosa che somiglia moltissimo ad una gestione degli stati. Ma tutto questo è spiegato benissimo nei tutorial sul sito di FlashPunk quindi, as usual,
buon coding!
Etichette:
flash,
flashdevelop,
flashpunk,
howto,
programmazione,
tutorial
venerdì 3 febbraio 2012
Android: impostare un context grafico OpenGL ES
E così vuoi fare un gioco per Android.
Benvenuto compagno di viaggio.
Non hai ancora deciso se sarà un 3D o un 2D, ma tanto non ti interessa, dato che non ti piegherai ad usare un Canvas o una semplice View per disegnare, tu vuoi codare the hard way, vuoi la potenza dell'accelerazione hardware, vuoi OpenGl ES.
E allora eccoci qui. La prima cosa da fare è capire come si imposta il contesto grafico, e arrivare alla mitica schermata monocolore. Da lì in avanti, lo sappiamo, è tutta in discesa... (chi ha detto caduta libera?)
Suppongo tu sappia già come funziona una applicazione Android, e se non lo sai, beh, sappilo. Mi riferisco a inezie tipo il concetto di Activity (non ti servirà comunque molto altro).
Quindi, il nostro progetto partirà con una Activity vuota ma funzionante. Per impostare il nostro contesto grafico ci occorrono essenzialmente due cose:
La prima ce la fornisce il framework, ma in un progetto reale vorremo probabilmente ereditare da quella base per accedere alle notifiche dell'input utente e, in generale, avere maggiore controllo sulla vita dell'applicazione. Per ora possiamo accontentarci, ad ogni modo, di usarla così come è.
La seconda necessita invece di un po' di codice. GLSurfaceView.Renderer è l'interfaccia dell'oggetto che si occupa di creare il contesto opengl, gestirne i cambiamenti (risoluzione dello schermo) e disegnare il frame. Implementandola, dovremo scrivere il codice per i metodi:
Dove GL10 è l'oggetto wrapper sulle API OpenGL (1.0).
Ecco una semplice implementazione:
Per un gioco 2D, naturalmente, imposteremo la GL_PROJECTION con una glOrtho, o gluOrtho2D... insomma, OpenGL rimane sempre lei.
Il main, oops, scusate, la OnCreate dell'Activity, resta banale:
Tutto quel che facciamo è istanziare il Renderer e la GLSurfaceView e passare a quest'ultima la nostra implementazione, quindi assegnare la View all'Activity.
E adesso via a scrivere il vostro gioco!
Benvenuto compagno di viaggio.
Non hai ancora deciso se sarà un 3D o un 2D, ma tanto non ti interessa, dato che non ti piegherai ad usare un Canvas o una semplice View per disegnare, tu vuoi codare the hard way, vuoi la potenza dell'accelerazione hardware, vuoi OpenGl ES.
E allora eccoci qui. La prima cosa da fare è capire come si imposta il contesto grafico, e arrivare alla mitica schermata monocolore. Da lì in avanti, lo sappiamo, è tutta in discesa... (chi ha detto caduta libera?)
Suppongo tu sappia già come funziona una applicazione Android, e se non lo sai, beh, sappilo. Mi riferisco a inezie tipo il concetto di Activity (non ti servirà comunque molto altro).
Quindi, il nostro progetto partirà con una Activity vuota ma funzionante. Per impostare il nostro contesto grafico ci occorrono essenzialmente due cose:
- Una istanza della classe GLSurfaceView
- Una implementazione dell'interfaccia GLSurfaceView.Renderer
La prima ce la fornisce il framework, ma in un progetto reale vorremo probabilmente ereditare da quella base per accedere alle notifiche dell'input utente e, in generale, avere maggiore controllo sulla vita dell'applicazione. Per ora possiamo accontentarci, ad ogni modo, di usarla così come è.
La seconda necessita invece di un po' di codice. GLSurfaceView.Renderer è l'interfaccia dell'oggetto che si occupa di creare il contesto opengl, gestirne i cambiamenti (risoluzione dello schermo) e disegnare il frame. Implementandola, dovremo scrivere il codice per i metodi:
public void onDrawFrame(GL10 gl); public void onSurfaceChanged(GL10 gl, int width, int height); public void onSurfaceCreated(GL10 gl, EGLConfig conf);
Dove GL10 è l'oggetto wrapper sulle API OpenGL (1.0).
Ecco una semplice implementazione:
public class MyRenderer implements Renderer {
@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onSurfaceChanged(GL10 gl, int w, int h) {
gl.glViewport(0, 0, w, h);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 45f, (float)w / (float)h, 0.1f, 450f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig conf) {
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
gl.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
}
}
Per un gioco 2D, naturalmente, imposteremo la GL_PROJECTION con una glOrtho, o gluOrtho2D... insomma, OpenGL rimane sempre lei.
Il main, oops, scusate, la OnCreate dell'Activity, resta banale:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyRenderer renderer = new MyRenderer();
GLSurfaceView surface = new GLSurfaceView(this);
surface.setRenderer(renderer);
setContentView(surface);
}
Tutto quel che facciamo è istanziare il Renderer e la GLSurfaceView e passare a quest'ultima la nostra implementazione, quindi assegnare la View all'Activity.
E adesso via a scrivere il vostro gioco!
mercoledì 11 gennaio 2012
Unit Test in C++ con MiniCppUnit
Continua la carrellata di tool utilissimi e semplici da usare per arricchire la nostra cassetta degli attrezzi C++.
Dopo aver visto quanto sia facile fare parsing ed editing di documenti xml con TinyXML, vi segnalo una libreria molto pratica per lo unit testing: MiniCppUnit.
MiniCppUnit condivide con TinyXML l'approccio lib-free, ovvero non la trovate compilata come libreria da includere nel vostro progetto, ma come due semplici file (un header e la relativa implementazione) da aggiungere e compilare assieme al vostro codice (C++ standard, STL e nessuna dipendenza esterna... good!).
L'utilizzo segue la logica del più noto JUnit per Java, di cui esiste il porting C++, CppUnit, del quale il nostro MiniCppUnit non è altro che la versione semplificata. Per chi non conoscesse JUnit (o NUnit per .Net) facciamo un rapidissimo ripassino:
MiniCppUnit permette di verificare vari tipi di asserzioni:
...e pure una macro sul controllo delle eccezioni!
Sono poche e semplici, ma sicuramente l'essenziale per mettere in piedi un sistema di testing più evoluto di un main con tanti cout, o peggio ancora di no tests at all.
Il main è quanto di più banale possa esistere:
Il singleton TestFixtureFactory va in automatico a prendersi tutte le classi TestFixture (registrate tramite apposita macro REGISTER_FIXTURE()) e le esegue, riportando il risultato in una schermata di console. Semplice, pratico e pulito.
Il pacchetto che scaricate, oltre ai due file da includere nel vostro progetto, contiene anche altri due file con un esempio d'uso, da cui ho preso il codice d'esempio. Sono più che sufficienti a togliere ogni dubbio residuo sull'utilizzo, ma se servisse altro c'è pure una ottima documentazione doxygen online.
Niente scuse, quindi: il vostro prossimo progetto C++ godrà di unit testing, perché if it ain't tested, it's broken!
Dopo aver visto quanto sia facile fare parsing ed editing di documenti xml con TinyXML, vi segnalo una libreria molto pratica per lo unit testing: MiniCppUnit.
MiniCppUnit condivide con TinyXML l'approccio lib-free, ovvero non la trovate compilata come libreria da includere nel vostro progetto, ma come due semplici file (un header e la relativa implementazione) da aggiungere e compilare assieme al vostro codice (C++ standard, STL e nessuna dipendenza esterna... good!).
L'utilizzo segue la logica del più noto JUnit per Java, di cui esiste il porting C++, CppUnit, del quale il nostro MiniCppUnit non è altro che la versione semplificata. Per chi non conoscesse JUnit (o NUnit per .Net) facciamo un rapidissimo ripassino:
- si crea un progetto per il test di un altro progetto/classe/sottosistema
- si creano una o più classi speciali marcate come TestFixture e contenenti metodi marcati come Test
- si scrivono test basati sull'utilizzo di asserzioni
- si danno tutte le TestFixture in pasto ad un motore che le esegue e riporta i risultati (successo/fallimento)
NB: per info più precise sullo Unit Testing si veda la Rete.
Cosa mi fa testare?
MiniCppUnit permette di verificare vari tipi di asserzioni:
ASSERT(3==1+2); ASSERT_MESSAGE( 2==1+1, "2 should be 1 plus 1 "); ASSERT_EQUALS(expected, result); ASSERT_EQUALS_EPSILON(expected, result, 0.05);
...e pure una macro sul controllo delle eccezioni!
Sono poche e semplici, ma sicuramente l'essenziale per mettere in piedi un sistema di testing più evoluto di un main con tanti cout, o peggio ancora di no tests at all.
Come lo lancio?
Il main è quanto di più banale possa esistere:
#include "MiniCppUnit.hxx"
int main()
{
return TestFixtureFactory::theInstance().runTests() ? 0 : -1;
}
Il singleton TestFixtureFactory va in automatico a prendersi tutte le classi TestFixture (registrate tramite apposita macro REGISTER_FIXTURE()) e le esegue, riportando il risultato in una schermata di console. Semplice, pratico e pulito.
Il pacchetto che scaricate, oltre ai due file da includere nel vostro progetto, contiene anche altri due file con un esempio d'uso, da cui ho preso il codice d'esempio. Sono più che sufficienti a togliere ogni dubbio residuo sull'utilizzo, ma se servisse altro c'è pure una ottima documentazione doxygen online.
Concludendo
Niente scuse, quindi: il vostro prossimo progetto C++ godrà di unit testing, perché if it ain't tested, it's broken!
venerdì 30 dicembre 2011
Programmazione: Ecco perché dovresti usare i private accessors
Ah, gli accessors. Per molti programmatori in erba sono quasi degli sconosciuti. Per i più navigati (e pigri) poco più che delle seccature. Per alcuni IDE, un modo come un altro per generare warnings e riempirvi il codice di fastidiose sottolineature.
E' tuttavia pratica comune ammettere che gli accessors pubblici hanno un loro perché, tirando fuori il principio di Incapsulamento dell'OOP. Ma cosa si può dire di un accessor privato?
Prendiamo ad esempio il seguente frammento di codice C++:
Il membro hp è privato e la classe Player vi accede in modo diretto all'interno dei suoi metodi. Che c'è di male? Beh, niente. Tutto lecito. Il compilatore va avanti e il programma funzia. Ma vediamo come apparirebbe con l'utilizzo di accessors privati:
E' vero, c'è del codice in più. E' vero, codice in più == bug in più. Ma ci sono anche ottimi motivi per operare in questo modo. Elenchiamoli:
I vantaggi qui elencati sono solo esempi. Scommetto che lavorandoci se ne potrebbero trovare altri.
Buon coding...e Buon Anno!
L'articolo originale da cui ho tratto lo spunto per questa riflessione è pubblicato sul blog Joel on Software
E' tuttavia pratica comune ammettere che gli accessors pubblici hanno un loro perché, tirando fuori il principio di Incapsulamento dell'OOP. Ma cosa si può dire di un accessor privato?
Prendiamo ad esempio il seguente frammento di codice C++:
class Player
{
public:
void hurt(int damage){
this->hp -= damage;
}
void heal(int amount){
this->hp += amount;
}
private:
int hp;
}
Il membro hp è privato e la classe Player vi accede in modo diretto all'interno dei suoi metodi. Che c'è di male? Beh, niente. Tutto lecito. Il compilatore va avanti e il programma funzia. Ma vediamo come apparirebbe con l'utilizzo di accessors privati:
class Player
{
public:
void hurt(int damage){
setHp(getHp()-damage);
}
void heal(int amount){
setHp(getHp()+amount);
}
private:
int hp;
private:
void setHp(int value){
this->hp = value;
}
int getHp(){
return this->hp;
}
}
E' vero, c'è del codice in più. E' vero, codice in più == bug in più. Ma ci sono anche ottimi motivi per operare in questo modo. Elenchiamoli:
- Tutte le modifiche in un punto solo
Sappiamo che questo vale per gli accessors pubblici, perché non dovrebbe valere per quelli privati? Ogni modifica al membro hp verrà fatta dentro setHp(), riducendo la complessità di debug e manutenzione del codice (un solo breakpoint). - Validazione
E' possibile operare logiche aggiuntive in un unico punto. Ad esempio si potrebbe controllare che gli hp non scendano sotto lo zero, o che non salgano sopra una certa soglia, mettendo tutti i controlli nella setHp() anziché spargerli nelle varie hurt(), heal() e così via. - Unit test?
Con qualche accorgimento (tipo un metodo wrapper pubblico sugli accessor privati, magari da commentare dopo la fase di test) possiamo scrivere dei test più sicuri ed efficienti, perché andranno a spremere con tutte le logiche possibili un unico metodo. (I moderni tool di unit testing solitamente hanno poi escamotage per raggiungere anche i metodi privati, senza chiederci di sporcare il codice con wrapper vari.) - Incapsulamento
Ancora una volta, l'essere privato non elimina i vantaggi del pubblico. E' vero, stiamo "nascondendo" dettagli implementativi alla stessa classe che li implementa, il che può apparire sciocco. Ma non è mai sciocco racchiudere funzionalità operanti su un membro in un unico punto. - Ridefinizione nelle classi derivate
Ok, qui bariamo un attimo e rendiamo i nostri accessors virtual e protected. Le classi derivate possono ridefinire l'accesso al membro. Se questa esigenza fosse sorta dopo un po' e non avessimo avuto gli accessors privati saremmo stati costretti quantomeno ad un pericoloso refactoring. - Undo e Redo
Altro figlio dell'avere le modifiche in un solo punto è la possibilità di aggiungere con facilità funzionalità di undo e redo.
I vantaggi qui elencati sono solo esempi. Scommetto che lavorandoci se ne potrebbero trovare altri.
Buon coding...e Buon Anno!
L'articolo originale da cui ho tratto lo spunto per questa riflessione è pubblicato sul blog Joel on Software
mercoledì 28 dicembre 2011
Dwarf Fortress: come ti sopravvivo al primo anno (parte 1)
Questo post poteva anche appartenere alla serie "Il gioco indie che forse non conoscete...", ma chi non ha mai sentito parlare di Dwarf Fortress? Chi non ha mai provato a giocarci e, dopo solo tre minuti, l'ha cestinato per via della sua inconcepibile complessità? E chi, tra questi, ha mantenuto quell'amaro in bocca dovuto alla sensazione di aver appena rinunciato ad una esperienza di gioco potenzialmente molto valida?
Ebbene, se siete tra i tanti frustrati che ci hanno provato ma ne sono stati sconfitti, questo post tenterà di farvi tornare la voglia per un nuovo tentativo. Sì, perché qui si parla della base di partenza per creare una fortezza e mantenerla in vita per il primo anno di gioco.
E' vero, ci sono tanti tutorial su Dwarf Fortress, quindi perché anche questo?
Beh, DF è un gioco grosso (ma rende meglio all'americana: HUGE!) e, quasi fosse fisiologico, anche i tutorial che vanno ad occuparsene finiscono per diventarlo. Inoltre sono spesso scritti da guru del gioco, persone che ormai ne padroneggiano i segreti più occulti e che hanno perso di vista quella sensazione di muro che si trova davanti il novizio.
Io no. Ho perso le mie prime fortezze in molti modi: per fame, per sete, per rabbia dei nani, per fantasmi (!), per cause ignote ma che mi lasciavano nani morti ammazzati in giro per le sale e per altri divertimenti assortiti.
Dopo diversi tentativi ho però trovato la formula per l'equilibrio, quel tanto che basta a far vivere e prosperare la fortezza fino all'arrivo della prima carovana di mercanti, e anche un po' più in la. Tutto si riassume in due parole: cibo e alcolici. Fate in modo di produrne in quantità regolari (ma anche abbondanti) e avrete risolto i bisogni primari dei vostri nani.
Produrre cibo e alcol sottintende avere una o più fattorie (farm plot) funzionanti. Per fare una fattoria occorrono però una serie di passi intermedi che vanno dal tagliare gli alberi allo scavare in un terreno adatto (o irrigare). Fondamentale sarà anche tenere un conto preciso delle scorte.
In questa prima parte prenderemo solo confidenza con i meccanismi di base del gioco.
Incredibilmente, per essere un gioco tanto complesso, le meccaniche sono essenzialmente tre o quattro, e si ripetono sempre uguali.
All'inizio troverete i vostri nani (sette, naturalmente) attorno al wagon, il carro con cui sono giunti al luogo della spedizione. Sul wagon ci sono un sacco di robe utili, ma per ora non ce ne preoccupiamo.
Il gioco parte in stato di pausa, come vedete nella parte alta a sinistra della schermata. Lo stato di Pausa è fondamentale e ci passerete gran parte del tempo. Occorre quindi padroneggiarlo. Si entra in pausa in due modi: o per volontà, premendo Space dal menu principale, o in automatico, quando si entra in un sottomenu. Durante la pausa il tempo si blocca (ma dai!), i nani non fanno nulla e non accade niente di divertente, ma potete navigare tra i ricchi sottomenu in santa pace e assegnare ordini e direttive ai vostri nani, o capire cosa non va e con chi. Per ora allenatevi ad entrare ed uscire dalla pausa, acquisendo coscienza di essa.
Potete dare ordini ai nani premendo 'd' (Designations), come vedete nella parte destra dello schermo. Da qui si accede ad un sottomenu con i vari ordini, da scavare (Mine), a tagliare alberi (Chop down trees), a raccogliere erbe (Gather plants) ecc.
Ogni voce ha un suo tasto associato, che occorre premere. Mine, ad esempio, ha la 'd'. Per selezionare l'azione scavare, quindi, occorre premere 'd' e poi ancora 'd'. A questo punto la X gialla nella schermata di mappa con i nani diventa un cursore. Dobbiamo selezionare l'area interessata dall'azione, specificandone il vertice alto a sinistra e basso a destra. Per farlo portiamo il cursore (con le frecce) nel punto desiderato (alto a sinistra) e premiamo Enter. Quindi ci portiamo nel secondo vertice (basso a destra) e premiamo Enter di nuovo. L'area viene evidenziata. Nel caso dello scavare, l'area evidenziata rappresenta la fetta di terra/roccia da eliminare. Naturalmente ha senso solo se fatta in una zona con una parete rocciosa, oppure sotto terra.
Altro menu importante è quello delle costruzioni (Buildings). Ci si accede col tasto 'b' e vengono mostrate le possibili costruzioni. Ci torneremo, nel frattempo esplorate pure i vari sottomenu, specialmente quello dei laboratori (Workshops).
E' importante capire che non comandate direttamente i singoli nani, ma specificate cosa deve essere fatto (è un gestionale). I nani hanno poi delle statistiche e il sistema invia i nani più skillati nel lavoro scelto. A volte capita che nessun nano sappia fare la cosa scelta. In questo caso occorre agire sul singolo nano, abilitandolo al lavoro specifico (Labor). Ma questa è un'altra storia. Se avete scelto di giocare subito (consigliato) anziché preparare il viaggio con cura avrete a disposizione sette nani capaci di svolgere i compiti basilari.
Altra abilità importante che dovete sviluppare come giocatori di Dwarf Fortress è il concetto di Z-Level e come muoversi tra essi. DF è un gioco in 2D, ma simula il 3D lavorando con i livelli, come un programma di fotoritocco. Premendo '>' si scende di un livello (si va in profondità), mentre con '<' si risale. Quando i vostri nani inizieranno a scavare (o a costruire verso l'alto, perché no) diventerà essenziale navigare tra i livelli. Fate esercizio già da ora e vedrete come i livelli più bassi appaiano ora quasi del tutto neri (solida roccia), magari con qualche falda acquifera qua e la, mentre quelli più alti vadano a perdere di dettaglio man mano che si sale. Se vi perdete niente paura: con F1 si torna al wagon.
Coraggio dunque, iniziate la vostra avventura nanica e prendete la mano con i comandi di base e la mentalità del gioco, che nella prossima puntata si parte con la strategia di sopravvivenza.
Ebbene, se siete tra i tanti frustrati che ci hanno provato ma ne sono stati sconfitti, questo post tenterà di farvi tornare la voglia per un nuovo tentativo. Sì, perché qui si parla della base di partenza per creare una fortezza e mantenerla in vita per il primo anno di gioco.
E' vero, ci sono tanti tutorial su Dwarf Fortress, quindi perché anche questo?
Beh, DF è un gioco grosso (ma rende meglio all'americana: HUGE!) e, quasi fosse fisiologico, anche i tutorial che vanno ad occuparsene finiscono per diventarlo. Inoltre sono spesso scritti da guru del gioco, persone che ormai ne padroneggiano i segreti più occulti e che hanno perso di vista quella sensazione di muro che si trova davanti il novizio.
Io no. Ho perso le mie prime fortezze in molti modi: per fame, per sete, per rabbia dei nani, per fantasmi (!), per cause ignote ma che mi lasciavano nani morti ammazzati in giro per le sale e per altri divertimenti assortiti.
Dopo diversi tentativi ho però trovato la formula per l'equilibrio, quel tanto che basta a far vivere e prosperare la fortezza fino all'arrivo della prima carovana di mercanti, e anche un po' più in la. Tutto si riassume in due parole: cibo e alcolici. Fate in modo di produrne in quantità regolari (ma anche abbondanti) e avrete risolto i bisogni primari dei vostri nani.
Produrre cibo e alcol sottintende avere una o più fattorie (farm plot) funzionanti. Per fare una fattoria occorrono però una serie di passi intermedi che vanno dal tagliare gli alberi allo scavare in un terreno adatto (o irrigare). Fondamentale sarà anche tenere un conto preciso delle scorte.
In questa prima parte prenderemo solo confidenza con i meccanismi di base del gioco.
Incredibilmente, per essere un gioco tanto complesso, le meccaniche sono essenzialmente tre o quattro, e si ripetono sempre uguali.
All'inizio troverete i vostri nani (sette, naturalmente) attorno al wagon, il carro con cui sono giunti al luogo della spedizione. Sul wagon ci sono un sacco di robe utili, ma per ora non ce ne preoccupiamo.
Fermi tutti!
Il gioco parte in stato di pausa, come vedete nella parte alta a sinistra della schermata. Lo stato di Pausa è fondamentale e ci passerete gran parte del tempo. Occorre quindi padroneggiarlo. Si entra in pausa in due modi: o per volontà, premendo Space dal menu principale, o in automatico, quando si entra in un sottomenu. Durante la pausa il tempo si blocca (ma dai!), i nani non fanno nulla e non accade niente di divertente, ma potete navigare tra i ricchi sottomenu in santa pace e assegnare ordini e direttive ai vostri nani, o capire cosa non va e con chi. Per ora allenatevi ad entrare ed uscire dalla pausa, acquisendo coscienza di essa.
Potete dare ordini ai nani premendo 'd' (Designations), come vedete nella parte destra dello schermo. Da qui si accede ad un sottomenu con i vari ordini, da scavare (Mine), a tagliare alberi (Chop down trees), a raccogliere erbe (Gather plants) ecc.
Sì, ma come?
Ogni voce ha un suo tasto associato, che occorre premere. Mine, ad esempio, ha la 'd'. Per selezionare l'azione scavare, quindi, occorre premere 'd' e poi ancora 'd'. A questo punto la X gialla nella schermata di mappa con i nani diventa un cursore. Dobbiamo selezionare l'area interessata dall'azione, specificandone il vertice alto a sinistra e basso a destra. Per farlo portiamo il cursore (con le frecce) nel punto desiderato (alto a sinistra) e premiamo Enter. Quindi ci portiamo nel secondo vertice (basso a destra) e premiamo Enter di nuovo. L'area viene evidenziata. Nel caso dello scavare, l'area evidenziata rappresenta la fetta di terra/roccia da eliminare. Naturalmente ha senso solo se fatta in una zona con una parete rocciosa, oppure sotto terra.
Altro menu importante è quello delle costruzioni (Buildings). Ci si accede col tasto 'b' e vengono mostrate le possibili costruzioni. Ci torneremo, nel frattempo esplorate pure i vari sottomenu, specialmente quello dei laboratori (Workshops).
Chi fa cosa?
E' importante capire che non comandate direttamente i singoli nani, ma specificate cosa deve essere fatto (è un gestionale). I nani hanno poi delle statistiche e il sistema invia i nani più skillati nel lavoro scelto. A volte capita che nessun nano sappia fare la cosa scelta. In questo caso occorre agire sul singolo nano, abilitandolo al lavoro specifico (Labor). Ma questa è un'altra storia. Se avete scelto di giocare subito (consigliato) anziché preparare il viaggio con cura avrete a disposizione sette nani capaci di svolgere i compiti basilari.
Su e giù
Altra abilità importante che dovete sviluppare come giocatori di Dwarf Fortress è il concetto di Z-Level e come muoversi tra essi. DF è un gioco in 2D, ma simula il 3D lavorando con i livelli, come un programma di fotoritocco. Premendo '>' si scende di un livello (si va in profondità), mentre con '<' si risale. Quando i vostri nani inizieranno a scavare (o a costruire verso l'alto, perché no) diventerà essenziale navigare tra i livelli. Fate esercizio già da ora e vedrete come i livelli più bassi appaiano ora quasi del tutto neri (solida roccia), magari con qualche falda acquifera qua e la, mentre quelli più alti vadano a perdere di dettaglio man mano che si sale. Se vi perdete niente paura: con F1 si torna al wagon.
Coraggio dunque, iniziate la vostra avventura nanica e prendete la mano con i comandi di base e la mentalità del gioco, che nella prossima puntata si parte con la strategia di sopravvivenza.
mercoledì 30 novembre 2011
HowTo: usare la fotocamera su Android
Domanda: sto facendo una mia app per Android. Devo permettere all'utente di scattare una foto per farci poi alcune cose, come faccio?
Risposta: chiedi in prestito la camera ad Android.
Il concetto di base è quello di sfruttare il meccanismo degli Intent per chiedere al sistema di prestarci la sua gestione della fotocamera. Gli Intent sono una caratteristica veramente interessante di Android e chiunque decida di fare sul serio con questa piattaforma dovrebbe studiarseli per bene. Volendo comunque riassumere in due righe cosa sono e perché ci servono, possiamo dire che gli Intent sono lo strumento a disposizione delle applicazioni per esprimere la propria necessità di fare qualcosa (scattare una foto, mostrare una pagina web, vedere un video...), anche senza specificare il come farla. Di questo si delega il sistema stesso, che sceglie l'applicazione più consona a soddisfare l'esigenza.
La nostra esigenza, ovviamente, è scattare una foto e averla poi a disposizione. Una volta impostata la nostra Activity e l'azione che deve scatenare la richiesta, come pigiare un button, non ci resta che scrivere il poco codice che serve.
Come vedete il codice si compone di due fasi:
A questo punto siamo già in grado di lanciare la gestione della fotocamera e scattare le foto. Alla chiusura dell'Activity della fotocamera, però, non abbiamo più il controllo sui dati della foto scattati. Per fare questo ci occorre gestire l'override di un metodo della classe base Activity,
Ci facciamo restituire la Bitmap leggendone i dati dal nostro file temporaneo. Con questa, volendo, andiamo ad impostare una ImageView che ci fornisce l'anteprima dell'immagine (la ImageView deve essere opportunamente presente nella nostra Activity e referenziata attraverso
La seconda cosa che vogliamo fare è ottenere una immagine jpeg compressa partendo dalla grossa bitmap ottenuta. Lo facciamo con le tre righe che seguono l'impostazione della preview, nelle quali specifichiamo il grado di compressione (70, nell'esempio) tenendo conto che 0 significa massima compressione e 100 massima qualità.
Infine, puliamo la memoria eliminando il nostro file temporaneo, che ci sembra sempre cosa buona e giusta.
Non ci resta altro da fare che aggiungere nel Manifest le
Buone foto!
Risposta: chiedi in prestito la camera ad Android.
Il concetto di base è quello di sfruttare il meccanismo degli Intent per chiedere al sistema di prestarci la sua gestione della fotocamera. Gli Intent sono una caratteristica veramente interessante di Android e chiunque decida di fare sul serio con questa piattaforma dovrebbe studiarseli per bene. Volendo comunque riassumere in due righe cosa sono e perché ci servono, possiamo dire che gli Intent sono lo strumento a disposizione delle applicazioni per esprimere la propria necessità di fare qualcosa (scattare una foto, mostrare una pagina web, vedere un video...), anche senza specificare il come farla. Di questo si delega il sistema stesso, che sceglie l'applicazione più consona a soddisfare l'esigenza.
La nostra esigenza, ovviamente, è scattare una foto e averla poi a disposizione. Una volta impostata la nostra Activity e l'azione che deve scatenare la richiesta, come pigiare un button, non ci resta che scrivere il poco codice che serve.
NB: prima di iniziare, preciso che tutto il codice qui indicato è esente da qualsiasi gestione delle eccezioni, anche da quelle comandate, in favore della leggibilità. Non è un grosso problema, dato che l'IDE (e Java) stesso vi obbligheranno a gestire le Exceptions necessarie.
private static final int CAMERA_REQUEST = 100; // un numero a nostro piacimento
File tmpFotoFile = null;
private void launchCamera(){
// Fase 1
//
tmpFotoFile = File.createTempFile("myappprefix", null);
// Fase 2
//
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tmpFotoFile));
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
Come vedete il codice si compone di due fasi:
- dobbiamo creare un'area di memoria in cui salvare i dati della foto che andremo a scattare. Volendo potremmo anche creare un file fisico, ma per questo tutorial supponiamo che non vogliate (o possiate) scrivere sulla SDCard. Il nostro file temporaneo in memoria è gestito da tmpFotoFile.
- ora possiamo chiedere al sistema di lanciare la sua gestione della fotocamera. Per fare questo creiamo la giusta Intent, dicendogli che ci serve qualcosa per ottenere una ACTION_IMAGE_CAPTURE. Decoriamo ulteriormente la Intent con una informazione extra: l'output, caro Android, mettimelo per cortesia in tmpFotoFile. Come vedete è tutto estremamente generico, proprio perché adattabile anche ad altri contesti. Fatto questo, lanciamo la nuova Activity risultante dall'Intent specificata in modo da attenderne (e gestirne) il risultato.
A questo punto siamo già in grado di lanciare la gestione della fotocamera e scattare le foto. Alla chiusura dell'Activity della fotocamera, però, non abbiamo più il controllo sui dati della foto scattati. Per fare questo ci occorre gestire l'override di un metodo della classe base Activity,
onActivityResult, intercettando il corretto codice di request. Ecco come:byte[] bitmapdata;
ImageView preview;
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST) {
Bitmap datifoto = android.provider.MediaStore.Images.Media.getBitmap(this.getContentResolver(), Uri.fromFile(tmpFotoFile));
preview.setImageBitmap(datifoto);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
datifoto.compress(CompressFormat.JPEG, 70, bos);
bitmapdata = bos.toByteArray();
tmpFotoFile.delete();
}
}
Ci facciamo restituire la Bitmap leggendone i dati dal nostro file temporaneo. Con questa, volendo, andiamo ad impostare una ImageView che ci fornisce l'anteprima dell'immagine (la ImageView deve essere opportunamente presente nella nostra Activity e referenziata attraverso
findViewById(...)).La seconda cosa che vogliamo fare è ottenere una immagine jpeg compressa partendo dalla grossa bitmap ottenuta. Lo facciamo con le tre righe che seguono l'impostazione della preview, nelle quali specifichiamo il grado di compressione (70, nell'esempio) tenendo conto che 0 significa massima compressione e 100 massima qualità.
Infine, puliamo la memoria eliminando il nostro file temporaneo, che ci sembra sempre cosa buona e giusta.
Non ci resta altro da fare che aggiungere nel Manifest le
uses-permission necessarie a far funzionare il tutto, ovvero:<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"> <uses-feature android:name="android.hardware.camera" />
Buone foto!
venerdì 25 novembre 2011
Povero italiano!
Grazie ad internet abbiamo modo di accedere alle idee e ai pensieri di migliaia di nostri simili, tutti i giorni. Ciò è bene. Il male è vedere come molta di questa gente si esprime. Non saprei dire se la colpa sia di internet, quel che è certo è che la Rete ha fatto emergere una inquietante incapacità del giovane italiano medio nel maneggiare la propria lingua.
Scriviamo veramente male. Quel che è peggio è che ci stiamo abituando a tollerare certi orrori. I forum sono pugnalate agli occhi. I commenti nei blog nascondono spesso calci rotanti al dizionario. Gli stessi post, che ti aspetteresti editati con un minimo di cura, spesso non sono migliori.
Non parlo di qualche refuso. Non entro nel merito di accenti gravi o acuti. Ma il verbo avere, su! Quella benedetta acca sarà anche muta ma mica invisibile!
Le virgole non sono orpelli grafici, non se ne vanno a zonzo da sole per la frase; amano invece stare in compagnia, sempre attaccate alla parola che le precede, ma staccate dalla successiva, per aiutare il benedetto periodo ad acquisire un senso.
Il punto! Cosa c'è di più bello che mettere un bel punto al termine della frase? E' come fare una release. Ecco, ho finito un pensiero. Punto!
I due punti poi! Meraviglia della sintesi. Riassumono tutto un pensiero appena espresso. Il fatto che se ne vedano pochi è triste, ma anche significativo: nessun pensiero da riassumere, evidentemente.
Il punto e virgola... Carneade! Chi era costui? A differenza di virgole e punti, seminati qua e là e abbandonati a loro stessi, i punti e virgola sono proprio ignorati, spesso oggetto di oscure supposizioni.
Ad un maschio gli, ad una femmina le. Cavoli, persino i presentatori (ma ho sentito addirittura dei doppiatori) in tv ad una signora gli...
Volendo passare anche sopra la punteggiatura e le piccolezze particellari, non si fa un grande affare. Già, perché ci si costringe a guardare i verbi e le loro coniugazioni, e sono dolori. Il congiuntivo non è una malattia degli occhi! Villaggio ci ironizzava su vent'anni fa, con i suoi venghi e dichi, ma è ancora tutto tristemente attuale.
Le doppie! La z prolifica, la regola del zio, zia, zie è un patrimonio culturale ormai andato perduto. Le k e le x hanno guadagnato posizioni di potere persino nelle parole più intime della nostra povera lingua.
Ma tutto questo è ancora niente.
La cosa più inquietante è la palese confusione che regna nelle menti. Quando non si è capaci di formulare una frase di senso compiuto, io penso, è ora di iniziare a preoccuparsi sul serio, e di cose serie.
Scriviamo veramente male. Quel che è peggio è che ci stiamo abituando a tollerare certi orrori. I forum sono pugnalate agli occhi. I commenti nei blog nascondono spesso calci rotanti al dizionario. Gli stessi post, che ti aspetteresti editati con un minimo di cura, spesso non sono migliori.
Non parlo di qualche refuso. Non entro nel merito di accenti gravi o acuti. Ma il verbo avere, su! Quella benedetta acca sarà anche muta ma mica invisibile!
Le virgole non sono orpelli grafici, non se ne vanno a zonzo da sole per la frase; amano invece stare in compagnia, sempre attaccate alla parola che le precede, ma staccate dalla successiva, per aiutare il benedetto periodo ad acquisire un senso.
Il punto! Cosa c'è di più bello che mettere un bel punto al termine della frase? E' come fare una release. Ecco, ho finito un pensiero. Punto!
I due punti poi! Meraviglia della sintesi. Riassumono tutto un pensiero appena espresso. Il fatto che se ne vedano pochi è triste, ma anche significativo: nessun pensiero da riassumere, evidentemente.
Il punto e virgola... Carneade! Chi era costui? A differenza di virgole e punti, seminati qua e là e abbandonati a loro stessi, i punti e virgola sono proprio ignorati, spesso oggetto di oscure supposizioni.
Ad un maschio gli, ad una femmina le. Cavoli, persino i presentatori (ma ho sentito addirittura dei doppiatori) in tv ad una signora gli...
Volendo passare anche sopra la punteggiatura e le piccolezze particellari, non si fa un grande affare. Già, perché ci si costringe a guardare i verbi e le loro coniugazioni, e sono dolori. Il congiuntivo non è una malattia degli occhi! Villaggio ci ironizzava su vent'anni fa, con i suoi venghi e dichi, ma è ancora tutto tristemente attuale.
Le doppie! La z prolifica, la regola del zio, zia, zie è un patrimonio culturale ormai andato perduto. Le k e le x hanno guadagnato posizioni di potere persino nelle parole più intime della nostra povera lingua.
Ma tutto questo è ancora niente.
La cosa più inquietante è la palese confusione che regna nelle menti. Quando non si è capaci di formulare una frase di senso compiuto, io penso, è ora di iniziare a preoccuparsi sul serio, e di cose serie.
lunedì 21 novembre 2011
Quando il programmatore è anche musicista... MMA!
Una delle esigenze più comuni per i poveri mortali che gettano ore del proprio tempo libero nello studio di uno strumento musicale è avere a disposizione delle basi su cui suonare. Uno si studia un lick, ci si esercita a bocce ferme, cioè suonandolo solo sul proprio strumento, arriva a padroneggiarlo e poi, quando anche il metronomo gli da ragione, avrebbe ben piacere di sentire l'effetto che fa se suonato su un accompagnamento. Sacrosanto.
Ebbene, mi sono trovato spesso nella situazione ma ho sempre dribblato il problema vuoi con la band (complicato...), vuoi con veloci registrazioni di me stesso su una drum machine (macchinoso e poco scalabile... cambio accordi? cambio velocità?), vuoi arrangiandomi con qualche mezzo di fortuna, come editare accordi su un software per tabulazioni come PowerTab (uff...).
Ieri, complice una domenica nebbiosa e pigra, non avevo voglia di fare nulla di tutto ciò, solo di suonare il mio dannato lick su una base. E allora Google. E scopro che un settore di software apparentemente banale è in realtà pieno di applicazioni commerciali e di pochissimo free. Già mi prudevano le mani e nasceva l'idea per un progetto, quando mi sono imbattuto (per fortuna) in questo MMA: Musical MIDI Accompaniment.
E' in python, quindi portabile su diverse piattaforme. Per l'occasione navigavo con una macchina Windows, ma al più presto lo installerò anche sulla mia Fedora. Cercavo il modo quick and dirty per fare quel che mi serviva e... beh, più quick e, soprattutto, più dirty sarebbe stato difficile trovare!
MMA è software per un programmatore. Editare la propria base è proprio come scrivere un programma, e l'editor in sé è niente più che un editor di testo. Esatto, potete scrivere la vostra base anche con gedit, o notepad, proprio come fosse un listato C. Poi, tra le (poche) voci di menu che mi trovo? Build, naturalmente. Il risultato della build è un midi.
Ecco un esempio di base:
L'impatto è stato un po' una sorpresa, un po' un ritrovarsi a casa propria, come potete immaginare. Per un programmatore nulla di più intuitivo che scrivere codice, fare build e verificare il risultato. Rimane da capire se anche gli utenti non del mestiere si trovino bene con questa modalità operativa.
Per quanto mi riguarda, un software assolutamente da segnalare! E ora scusatemi, ho dei fraseggi da debuggare...
Ebbene, mi sono trovato spesso nella situazione ma ho sempre dribblato il problema vuoi con la band (complicato...), vuoi con veloci registrazioni di me stesso su una drum machine (macchinoso e poco scalabile... cambio accordi? cambio velocità?), vuoi arrangiandomi con qualche mezzo di fortuna, come editare accordi su un software per tabulazioni come PowerTab (uff...).
Ieri, complice una domenica nebbiosa e pigra, non avevo voglia di fare nulla di tutto ciò, solo di suonare il mio dannato lick su una base. E allora Google. E scopro che un settore di software apparentemente banale è in realtà pieno di applicazioni commerciali e di pochissimo free. Già mi prudevano le mani e nasceva l'idea per un progetto, quando mi sono imbattuto (per fortuna) in questo MMA: Musical MIDI Accompaniment.
E' in python, quindi portabile su diverse piattaforme. Per l'occasione navigavo con una macchina Windows, ma al più presto lo installerò anche sulla mia Fedora. Cercavo il modo quick and dirty per fare quel che mi serviva e... beh, più quick e, soprattutto, più dirty sarebbe stato difficile trovare!
MMA è software per un programmatore. Editare la propria base è proprio come scrivere un programma, e l'editor in sé è niente più che un editor di testo. Esatto, potete scrivere la vostra base anche con gedit, o notepad, proprio come fosse un listato C. Poi, tra le (poche) voci di menu che mi trovo? Build, naturalmente. Il risultato della build è un midi.
Ecco un esempio di base:
Tempo 120 Groove Tango 1 C 2 F 3 G7 4 C / Em 5 C 6 / 7 F 8 C
L'impatto è stato un po' una sorpresa, un po' un ritrovarsi a casa propria, come potete immaginare. Per un programmatore nulla di più intuitivo che scrivere codice, fare build e verificare il risultato. Rimane da capire se anche gli utenti non del mestiere si trovino bene con questa modalità operativa.
Per quanto mi riguarda, un software assolutamente da segnalare! E ora scusatemi, ho dei fraseggi da debuggare...
mercoledì 9 novembre 2011
Il blog che forse non conoscete: 1 Month Game!
Ci risiamo. Sembra proprio che la cosa di cui gli sviluppatori amatoriali sentono maggiormente la mancanza sia la condivisione. Condivisione dei propri sforzi, dei propri stimoli, delle proprie idee. Deve essere così, altrimenti non si spiegherebbero i successi di tutti i contest posti nella forma fai un gioco in X ore/giorni. E' chiaro che non è la sfida di fare un gioco in un certo lasso di tempo a convincere migliaia di sviluppatori a tapparsi in casa a produrre codice, sprite e musiche. La sfida e l'agonismo ci sono, ma in minima parte. Quel che realmente decreta il successo di tali iniziative è senza dubbio la gran voglia di condividere non solo il frutto delle proprie fatiche, ma le fatiche stesse. E tra persone che le capiscono e le apprezzano, cioè tra altri sviluppatori con lo stesso obiettivo.
E' bello vedere emergere lo spirito di animale sociale in una categoria, la nostra, tacciata troppo spesso (e sempre più senza ragione) di luposolitarismo e asocialità. Ed è bello anche un blog che mi è capitato di trovare un po' per caso, tra una catena non più producibile di tweet e link: 1 Month Game.
Non si tratta di un contest ma di un vero blog a cura di Sophie Houlden in cui, seguendo alcune semplici regole, chiunque può postare il devlog del proprio progetto. Unica regola: terminare in un mese!
Per i più timidi rimane comunque un bel posto dove passare un po' di tempo, confrontandosi con quel che producono gli altri. I progetti sono infatti facili da seguire grazie alle linee guida di Sophie che impongono titoli dei post che indicano numero di settimana e giorno di sviluppo, da Week 1 - Day 1 a Week 4 - Day 7.
Come sempre, leggere e capire cosa fanno gli altri (e come) rimane un'esperienza e un'opportunità impagabile, di cui forse siamo un po' assuefatti oggi, ma che continua a stupire quelli che quando internet ancora non c'era...
E' bello vedere emergere lo spirito di animale sociale in una categoria, la nostra, tacciata troppo spesso (e sempre più senza ragione) di luposolitarismo e asocialità. Ed è bello anche un blog che mi è capitato di trovare un po' per caso, tra una catena non più producibile di tweet e link: 1 Month Game.
Non si tratta di un contest ma di un vero blog a cura di Sophie Houlden in cui, seguendo alcune semplici regole, chiunque può postare il devlog del proprio progetto. Unica regola: terminare in un mese!
Per i più timidi rimane comunque un bel posto dove passare un po' di tempo, confrontandosi con quel che producono gli altri. I progetti sono infatti facili da seguire grazie alle linee guida di Sophie che impongono titoli dei post che indicano numero di settimana e giorno di sviluppo, da Week 1 - Day 1 a Week 4 - Day 7.
Come sempre, leggere e capire cosa fanno gli altri (e come) rimane un'esperienza e un'opportunità impagabile, di cui forse siamo un po' assuefatti oggi, ma che continua a stupire quelli che quando internet ancora non c'era...
venerdì 4 novembre 2011
Quanta ne sai di C e C++?
Il saggio sa di non sapere. Il programmatore... beh... non sempre si dimostra saggio! Il programmatore in erba semplicemente non sa di cosa sta parlando, quindi ben che vada da fiato alle trombe e spara qualche orrore. Va corretto, ma con misericordia; in fondo è solo rumore ingenuo.
Più grave è la sindrome che troppo spesso colpisce i programmatori più esperti, o che si reputano tali. Sembra infatti che provino un certo gusto nel dare ai meno fortunati questuanti da forum mezze risposte, talvolta allusive, vedo e non vedo, che costringono i supplicanti a nuove richieste di spiegazioni. Il programmatore un-po'-più-esperto di solito riconosce questi personaggi come programmatori in erba evoluti, ma non ancora completi.
Ma attenzione. Anche il programmatore un-po'-più-esperto, quello che a prima vista può apparire saggio, che scrive tutorial, che dimostra pazienza, ha quasi certamente delle lacune. Il saggio sa di non sapere, dicevamo. Il difetto principale del programmatore è che, pur sapendo di non sapere (nei casi più fortunati), non lo ammette. Perché è cattivo? No di certo. Perché la programmazione è un lavoro di problem-solving, e la mente del programmatore è allenata ad affrontare quotidianamente sfide. Al mattino, quando si siede al pc, è conscio di affrontare qualcosa per la quale non ha ancora la soluzione, ma fiducioso sul fatto che a sera avrà la sua routine funzionante. Quindi ok, posso anche non sapere qualcosa, ma quel che so è sufficiente. Più che sufficiente. Sono un esperto.
...ne sei sicuro? Sì, dico a te, te che con il C hai passato gli anni dell'università, che hai già visto migliaia e migliaia di righe in C++, che credi di digerire poliformismo e allocazioni dinamiche come acqua fresca, te che in questo momento stai scrivendo questo post (io?) sì, sì, proprio te! Scendi dal piedistallo e vatti a fare questo test: Deep C!
Poi ne riparliamo!
Più grave è la sindrome che troppo spesso colpisce i programmatori più esperti, o che si reputano tali. Sembra infatti che provino un certo gusto nel dare ai meno fortunati questuanti da forum mezze risposte, talvolta allusive, vedo e non vedo, che costringono i supplicanti a nuove richieste di spiegazioni. Il programmatore un-po'-più-esperto di solito riconosce questi personaggi come programmatori in erba evoluti, ma non ancora completi.
Ma attenzione. Anche il programmatore un-po'-più-esperto, quello che a prima vista può apparire saggio, che scrive tutorial, che dimostra pazienza, ha quasi certamente delle lacune. Il saggio sa di non sapere, dicevamo. Il difetto principale del programmatore è che, pur sapendo di non sapere (nei casi più fortunati), non lo ammette. Perché è cattivo? No di certo. Perché la programmazione è un lavoro di problem-solving, e la mente del programmatore è allenata ad affrontare quotidianamente sfide. Al mattino, quando si siede al pc, è conscio di affrontare qualcosa per la quale non ha ancora la soluzione, ma fiducioso sul fatto che a sera avrà la sua routine funzionante. Quindi ok, posso anche non sapere qualcosa, ma quel che so è sufficiente. Più che sufficiente. Sono un esperto.
...ne sei sicuro? Sì, dico a te, te che con il C hai passato gli anni dell'università, che hai già visto migliaia e migliaia di righe in C++, che credi di digerire poliformismo e allocazioni dinamiche come acqua fresca, te che in questo momento stai scrivendo questo post (io?) sì, sì, proprio te! Scendi dal piedistallo e vatti a fare questo test: Deep C!
Poi ne riparliamo!
venerdì 14 ottobre 2011
Il gioco indie che forse non conoscete: One and One Story!
E' con piacere che vi segnalo One and One Story, un puzzle game sviluppato dal giovanissimo e italianissimo Mattia Traverso (utente come molti di noi di IndieVault), e fruibile tramite Armor Games.
Il gioco propone una serie di livelli con modalità di gameplay mutevoli e a tratti piuttosto impegnative, dove lo scopo è sempre il medesimo: far congiungere i due personaggi sullo schermo, un lui e una lei.
A fare da cornice alle loro unioni troviamo scenari con blocchi da spostare, salti, spuntoni e mortali cadute da evitare. Quel che affascina, però, non è tanto il gameplay in sé (comunque molto ben curato), quanto l'atmosfera che permea l'intero gioco.
Sia la grafica, che la musica, che i testi che compaiono tra un livello e l'altro, immergono il giocatore in una romantica malinconia, a tratti tragica, che sfocia in un finale, a parere del sottoscritto, molto profondo. Mi ha ricordato un altro piccolo capolavoro di cui si era parlato su queste pagine, Appy 1000mg, con il quale condivide l'aura malinconica (e un finale per certi aspetti simile).
Il web è già pieno di recensioni su questo One and One Story, ed è giusto così. Questa vuole solo essere una eco del tam tam che si sta diffondendo, che più che altro dice a tutti gli sviluppatori, giovani e non, che sì, si può fare!
Il gioco propone una serie di livelli con modalità di gameplay mutevoli e a tratti piuttosto impegnative, dove lo scopo è sempre il medesimo: far congiungere i due personaggi sullo schermo, un lui e una lei.
A fare da cornice alle loro unioni troviamo scenari con blocchi da spostare, salti, spuntoni e mortali cadute da evitare. Quel che affascina, però, non è tanto il gameplay in sé (comunque molto ben curato), quanto l'atmosfera che permea l'intero gioco.
Sia la grafica, che la musica, che i testi che compaiono tra un livello e l'altro, immergono il giocatore in una romantica malinconia, a tratti tragica, che sfocia in un finale, a parere del sottoscritto, molto profondo. Mi ha ricordato un altro piccolo capolavoro di cui si era parlato su queste pagine, Appy 1000mg, con il quale condivide l'aura malinconica (e un finale per certi aspetti simile).
Il web è già pieno di recensioni su questo One and One Story, ed è giusto così. Questa vuole solo essere una eco del tam tam che si sta diffondendo, che più che altro dice a tutti gli sviluppatori, giovani e non, che sì, si può fare!
Etichette:
appy 1000mg,
indie,
one and one story,
videogiochi
lunedì 10 ottobre 2011
Il programma Free che forse non conoscete: StoryBook!
Ancora una segnalazione per gli amanti della scrittura creativa. Questa volta si tratta di un utile tool per pianificare ed organizzare la propria fatica letteraria, in modo tale da non perdersi nel susseguirsi cronologico degli avvenimenti. Apparentemente è tutto qui, ma in questo StoryBook (java, multipiattaforma) c'è ben altro.
Il vero aiuto viene dato dalla struttura schematica a cui ci obbliga il software. Il suo ottuso xxx field is mandatory è da leggersi in realtà come domanda molto meno sciocca: stai forse pensando di andare avanti a scrivere questa parte senza sapere esattamente dove si svolge? E per dove si intende veramente dove: luogo, città, nazione. E quando si svolge? E con chi? Guarda che il personaggio che stai usando è privo di qualsiasi descrizione. Ah, non ha nemmeno la data di nascita. E' forse Egli un dio?
Insomma, ci aiuta a riflettere e a ragionare, e ci ricorda di prestare attenzione ai dettagli.
Presenta poi diversi report con cui visualizzare i capitoli e le scene che li compongono (sì, perchè ogni tuo capitolo è diviso in scene vero? e in quella scena ci sono quei personaggi e quegli oggetti, vero? E di ognuno di questi conosci forma, colore e odore, vero?). Ci sono le anagrafiche dei personaggi (divisi in principali e secondari), con diversi (ma non troppi) campi da compilare, delle locations, degli oggetti importanti.
A prima vista può sembrare tanto lavoro in più, ma non è così. La fase di analisi, qualunque sia la vostra religione a riguardo, va in qualche modo fatta. Per chi ama fare scalette è lo strumento principe: nulla fuori posto, tutto cronologicamente coerente, possibilità di pianificare intere trilogie prima di iniziare a scriverne una sola pagina. Per chi, al contrario, non ama andare troppo avanti con la trama per lasciarsi stupire dalla piega degli eventi, StoryBook rimane un valido aiuto. Anche solo concentrandosi sul capitolo che abbiamo davanti, infatti, induce a ragionare e a schiarire le idee.
Va sottolineato che non si tratta di un editor di testi. Non scriverete il vostro romanzo dentro StoryBook, che non presenta campi appositi per questo (a meno di non voler usare i campi note, ma francamente non credo sia stato progettato per questo). Resta da capire se lo si possa utilizzare anche in altri ambiti, magari nella progettazione di software...
Il vero aiuto viene dato dalla struttura schematica a cui ci obbliga il software. Il suo ottuso xxx field is mandatory è da leggersi in realtà come domanda molto meno sciocca: stai forse pensando di andare avanti a scrivere questa parte senza sapere esattamente dove si svolge? E per dove si intende veramente dove: luogo, città, nazione. E quando si svolge? E con chi? Guarda che il personaggio che stai usando è privo di qualsiasi descrizione. Ah, non ha nemmeno la data di nascita. E' forse Egli un dio?
Insomma, ci aiuta a riflettere e a ragionare, e ci ricorda di prestare attenzione ai dettagli.
Presenta poi diversi report con cui visualizzare i capitoli e le scene che li compongono (sì, perchè ogni tuo capitolo è diviso in scene vero? e in quella scena ci sono quei personaggi e quegli oggetti, vero? E di ognuno di questi conosci forma, colore e odore, vero?). Ci sono le anagrafiche dei personaggi (divisi in principali e secondari), con diversi (ma non troppi) campi da compilare, delle locations, degli oggetti importanti.
A prima vista può sembrare tanto lavoro in più, ma non è così. La fase di analisi, qualunque sia la vostra religione a riguardo, va in qualche modo fatta. Per chi ama fare scalette è lo strumento principe: nulla fuori posto, tutto cronologicamente coerente, possibilità di pianificare intere trilogie prima di iniziare a scriverne una sola pagina. Per chi, al contrario, non ama andare troppo avanti con la trama per lasciarsi stupire dalla piega degli eventi, StoryBook rimane un valido aiuto. Anche solo concentrandosi sul capitolo che abbiamo davanti, infatti, induce a ragionare e a schiarire le idee.
Va sottolineato che non si tratta di un editor di testi. Non scriverete il vostro romanzo dentro StoryBook, che non presenta campi appositi per questo (a meno di non voler usare i campi note, ma francamente non credo sia stato progettato per questo). Resta da capire se lo si possa utilizzare anche in altri ambiti, magari nella progettazione di software...
venerdì 30 settembre 2011
HowTo: Integrare SQLite nel proprio gioco Java
Come tutti i programmi, anche i giochi necessitano di dati. Abbiamo già parlato in precedenza di alcuni metodi per gestire (scrivere e rileggere) tali dati, utilizzando file xml piuttosto che file binari o ASCII. Ci sono naturalmente anche altri modi, e uno di questi è senza dubbio SQLite, un piccolo e leggero database relazionale su file.
(Per gli amici C++: SQLite è scritto in C, quindi la sua integrazione con C/C++ è assolutamente fattibile. Ne esiste anche la versione managed per .NET).
Questo pacchetto va poi inserito nel vostro progetto ed incluso tra le librerie in uso (in Eclipse si fa il tutto da Progetto->Proprietà->Java Build Paths->Librerie->Aggiungi JAR).
A questo punto siete pronti per scrivere codice! Vi servono solo 2 righe, che sono queste:
dove db/miodatabase.sqlite è il percorso + nome del vostro database, relativo alla root del progetto.
Per SQLite invece è pieno il mondo di programmi di amministrazione. Pensateli come fossero i vostri editor per i dati, perché è proprio quel che sono. C'è ad esempio un plugin per Firefox, SQLite Manager, comodissimo e ben realizzato, che vi fa creare ed editare il vostro database da browser. Check it out!
Una volta creato il vostro oggetto Connection potrete interrogare la base dati attraverso un oggetto Statement. La query in questo esempio preleva tutte le Quest di un ipotetico gioco di ruolo fornite da un personaggio non giocante con un certo id. Si riempie quindi un oggetto di gioco Quest con i dati prelevati e lo si aggiunge alla lista da restituire. Quando il set di dati finisce (
Con questo spero di avere aggiunto un'ulteriore freccia alla faretra dello sviluppatore in erba. Considerate che esistono anche i database e che non è vietato utilizzarli. Specie se se ne restano confinati in un unico, piccolo file binario.
Buon coding!
Un database? Non sarà un po' troppo?
Dipende. Sicuramente se volessimo scomodare un vero server di database come MySQL o SQLServer occorrerebbe una giustificazione più che valida. Ma SQLite è, come lascia intendere il nome, piccolino. Piccolino ma, attenzione, adatto a gestire grandi mole di dati, soprattutto in lettura. Pensate alla comodità di avere le varie entità del vostro gioco serializzate in modo ordinato in tabelle di una base dati. La tabella Livelli, con i dati relativi ad ogni livello di gioco, la tabella Nemici, con tutte le statistiche delle varie tipologie di nemici, la tabella Oggetti, con tutti gli item presenti nel vostro modo, e perché no, la tabella Partite, con i salvataggi del giocatore. E così via. Tutti dati che dovreste comunque gestire in una qualche forma di file.I vantaggi del relazionale.
Una volta modellata la base dati potrete poi sfruttare il principale vantaggio del suo utilizzo: le relazioni. La tabella NemiciPerLivello potrebbe contenere in modo semplice le coppie Livello-Nemico con la posizione all'interno del livello del tale nemico, ad esempio. In poche parole avete tra le mani, in forma gratuita, la potenza di chiavi primarie, chiavi esterne, vincoli di check e quant'altro.I vantaggi del linguaggio di query.
Recuperare (ma anche salvare, aggiornare o eliminare) i dati diventa semplice. Volete popolare il livello con una lista di oggetti casuali ma che siano di valore compreso tra min e max? Complicato con xml, un delirio con ASCII o binario, ma semplice ed immediato con una query SQL come:SELECT * FROM ITEMS WHERE ITEMVALUE >= @min AND ITEMVALUE <= @maxGià, ma come lo integro nel mio game?
Ed eccoci al punto. Per questo articolo prenderò come linguaggio di esempio Java. Essendo un linguaggio orientato per motivi storici ad applicazioni enterprise (da ufficio, per intenderci) ha già una buona integrazione con oggetti esterni come le basi dati. Per prima cosa occorre scaricare il pacchetto (.jar) contenente SQLite: al momento in cui scrivo ne trovate una copia qui.(Per gli amici C++: SQLite è scritto in C, quindi la sua integrazione con C/C++ è assolutamente fattibile. Ne esiste anche la versione managed per .NET).
Questo pacchetto va poi inserito nel vostro progetto ed incluso tra le librerie in uso (in Eclipse si fa il tutto da Progetto->Proprietà->Java Build Paths->Librerie->Aggiungi JAR).
A questo punto siete pronti per scrivere codice! Vi servono solo 2 righe, che sono queste:
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:db/miodatabase.sqlite");
dove db/miodatabase.sqlite è il percorso + nome del vostro database, relativo alla root del progetto.
E come lo creo il database?
E qui viene il bello. Con file di testo semplici ci basta Blocco Note. Con file binari ci occorre un editor di qualche tipo, che spesso dobbiamo scrivere noi. Con file xml può andare un qualunque editor di testi, ma per documenti importanti può diventare necessario un editor apposito, ancora una volta custom e a nostre spese.Per SQLite invece è pieno il mondo di programmi di amministrazione. Pensateli come fossero i vostri editor per i dati, perché è proprio quel che sono. C'è ad esempio un plugin per Firefox, SQLite Manager, comodissimo e ben realizzato, che vi fa creare ed editare il vostro database da browser. Check it out!
Un esempio di lettura.
Concludiamo con un piccolo esempio che mostra quanto diventi semplice ottenere i dati (per la loro creazione avrete probabilmente usato un tool come quelli citati qui sopra).List<quest> ret = new ArrayList<quest>();
Connection conn = DriverManager.getConnection("jdbc:sqlite:db/miodatabase.sqlite");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from quests where npc = " + npcId + " and done = 0");
while(rs.next()){
ret.add(new Quest(rs.getInt("id"),
rs.getString("text"),
rs.getString("type"),
rs.getString("onsuccess"),
rs.getString("onwait"),
rs.getInt("reward_gold")));
}
rs.close();
conn.close();Una volta creato il vostro oggetto Connection potrete interrogare la base dati attraverso un oggetto Statement. La query in questo esempio preleva tutte le Quest di un ipotetico gioco di ruolo fornite da un personaggio non giocante con un certo id. Si riempie quindi un oggetto di gioco Quest con i dati prelevati e lo si aggiunge alla lista da restituire. Quando il set di dati finisce (
rs.next() ritorna false quando non trova più nulla da leggere) si chiude la connessione. Abbiamo ora una lista di oggetti Quest pronti per essere gestiti dal motore di gioco!Con questo spero di avere aggiunto un'ulteriore freccia alla faretra dello sviluppatore in erba. Considerate che esistono anche i database e che non è vietato utilizzarli. Specie se se ne restano confinati in un unico, piccolo file binario.
Buon coding!
lunedì 26 settembre 2011
Il gioco indie che forse non conoscete: Whack Your Boss!
Se c'è un giorno della settimana in cui giocare a questo gioco assume gusto e senso del tutto particolari, beh, è proprio il lunedì. Cioè oggi. Quindi non mi dilungherò in verbose esposizioni.
Whack your boss di Tom Winkler ha il gameplay di un trova le differenze da settimana enigmistica, ma con una dose massiccia di splatter e humor sanguinolento. Alcune trovate sono veramente esilaranti, sebbene inadatte ad un pubblico troppo sensibile (e, naturalmente, al vostro capo).
Coraggio dunque: se credete di aver già pensato a tutti i possibili modi per far la festa al vostro superiore, scoprirete di esservi sbagliati alla grande. Scommetto che d'ora in poi guarderete la tazza sulla vostra scivania con occhi diversi...
Whack your boss di Tom Winkler ha il gameplay di un trova le differenze da settimana enigmistica, ma con una dose massiccia di splatter e humor sanguinolento. Alcune trovate sono veramente esilaranti, sebbene inadatte ad un pubblico troppo sensibile (e, naturalmente, al vostro capo).
Coraggio dunque: se credete di aver già pensato a tutti i possibili modi per far la festa al vostro superiore, scoprirete di esservi sbagliati alla grande. Scommetto che d'ora in poi guarderete la tazza sulla vostra scivania con occhi diversi...
lunedì 19 settembre 2011
Tutorial: scriviamo un gioco in C++... Tris! (parte 6)
Nell'ultima puntata, risalente ormai a quasi due mesi fa (vergogna!), eravamo quasi arrivati al gioco completo. Quasi...
Il nostro gioco infatti funziona, ma non è molto interessante poichè il computer non ragiona sulle proprie mosse, ma si limita a posizionare simboli a caso nelle celle vuote. Vincere contro di lui è fin troppo facile.
Quel che ci manca è di fornire il computer di una sorta di intelligenza, o almeno di quella che basta per capire come controbattere alle nostre mosse e magari metterci in difficoltà.
Nel nostro caso specifico non si tratta di una gran difficoltà, e con un po’ di ragionamento si può giungere ad una soluzione casereccia o addirittura scomodare qualche algoritmo famoso come il minimax.
Il punto focale di questo post non è però il come scrivere la logica, ma il come organizzarne la gestione. Quel che faremo sarà creare un meccanismo per cui un tipo di intelligenza artificiale tra molte disponibili venga prelevato ed utilizzato ad ogni partita. Ognuno implementerà la propria logica per gestire le mosse.
Il come scrivere queste logiche dipende dal programmatore, dal suo intuito, il suo gusto, la sua formazione. It's up to you, come dicono quelli là.
Utilizzeremo due design pattern: Strategy e Factory. Strategy ci servirà per implementare le diverse AI (che nel nostro caso saranno due), mentre una factory ci fornirà una implementazione concreta ad ogni partita, secondo una logica random.
Più facile a vedersi che a dirsi. Iniziamo quindi con la classe base astratta
Come vedete è occorso un po’ di refactor: abbiamo spostato qui la definizione dell’enumerativo dei simboli presente nella classe
Una prima classe di esempio è
Assieme alla
Molto più interessante è vedere invece come queste classi vengono usate dalla
Il metodo Reset è ora diventato così:
Come potete vedere c’è ora un nuovo membro,
Piuttosto intuitivo, no?
Non ci resta che dare un’occhiata alla
… e la relativa implementazione:
Banalmente andiamo a scegliere con una probabilità del 50% tra le nostre due
Con questo abbiamo finalmente concluso. TrisLick vuole essere un piccolo esempio di come realizzare qualcosa di piccolo ma concreto, lasciando aperte eventuali possibilità di sviluppo grazie ad una architettura flessibile.
Coraggio dunque, aprite il vostro editor, scaldate il compilatore e iniziate a scrivere il vostro prossimo gioco!
Buon coding!
Il nostro gioco infatti funziona, ma non è molto interessante poichè il computer non ragiona sulle proprie mosse, ma si limita a posizionare simboli a caso nelle celle vuote. Vincere contro di lui è fin troppo facile.
Quel che ci manca è di fornire il computer di una sorta di intelligenza, o almeno di quella che basta per capire come controbattere alle nostre mosse e magari metterci in difficoltà.
Nel nostro caso specifico non si tratta di una gran difficoltà, e con un po’ di ragionamento si può giungere ad una soluzione casereccia o addirittura scomodare qualche algoritmo famoso come il minimax.
Il punto focale di questo post non è però il come scrivere la logica, ma il come organizzarne la gestione. Quel che faremo sarà creare un meccanismo per cui un tipo di intelligenza artificiale tra molte disponibili venga prelevato ed utilizzato ad ogni partita. Ognuno implementerà la propria logica per gestire le mosse.
Il come scrivere queste logiche dipende dal programmatore, dal suo intuito, il suo gusto, la sua formazione. It's up to you, come dicono quelli là.
Utilizzeremo due design pattern: Strategy e Factory. Strategy ci servirà per implementare le diverse AI (che nel nostro caso saranno due), mentre una factory ci fornirà una implementazione concreta ad ogni partita, secondo una logica random.
Più facile a vedersi che a dirsi. Iniziamo quindi con la classe base astratta
StrategyAI.#ifndef STRATEGYAI_H
#define STRATEGYAI_H
enum GridSymbols
{
EGS_X, EGS_O, EGS_NONE
};
class StrategyAI
{
public:
StrategyAI();
virtual ~StrategyAI();
virtual void PlaceSymbol(GridSymbols grid[3][3]) = 0;
protected:
private:
};
#endif // STRATEGYAI_H
Come vedete è occorso un po’ di refactor: abbiamo spostato qui la definizione dell’enumerativo dei simboli presente nella classe
PlayGameState. Per il resto si tratta di una classettina molto semplice; contiene infatti un solo metodo virtuale puro atto a posizionare la mossa del computer all’interno della griglia. Le classi concrete che implementeranno StrategyAI dovranno implementare proprio questo metodo.Una prima classe di esempio è
DummyStrategyAI, che altro non fa che simulare quel che già avevamo, ovvero un riempimento casuale della griglia. Ecco la sua implementazione (ne ometto la dichiarazione)#include "../include/DummyStrategyAI.h"
#include <cstdlib>
//-----------------------------------------------------------------------------
DummyStrategyAI::DummyStrategyAI() : StrategyAI()
{
//ctor
}
//-----------------------------------------------------------------------------
DummyStrategyAI::~DummyStrategyAI()
{
//dtor
}
//-----------------------------------------------------------------------------
void
DummyStrategyAI::PlaceSymbol(GridSymbols grid[3][3])
{
int gridx, gridy;
bool ok = false;
while(!ok)
{
gridx = rand()%3;
gridy = rand()%3;
if(grid[gridy][gridx] == EGS_NONE)
{
ok = true;
grid[gridy][gridx] = EGS_O;
}
}
}
Assieme alla
DummyStrategyAI ho implementato anche una DefenderStrategyAI, una semplice AI che tende a bloccare i tentativi di tris del giocatore umano, pur non giocando d’attacco. Non riporto il codice di questa classe perchè non introduce nulla di nuovo. Molto più interessante è vedere invece come queste classi vengono usate dalla
PlayGameState.Il metodo Reset è ora diventato così:
//-----------------------------------------------------------------------------
void
PlayGameState::Reset()
{
m_SymbolsPlacedCount = 0;
m_PlayerWins = m_ComputerWins = false;
if(m_pWinText)
{
SDL_FreeSurface(m_pWinText);
}
m_pWinText = 0;
for(int r=0; r<3; ++r)
{
for(int c=0; c<3; ++c)
{
m_Grid[r][c] = EGS_NONE;
}
}
if(m_pAI)
{
delete m_pAI;
m_pAI = 0;
}
StrategyAIFactory factory;
m_pAI = factory.CreateStrategyAI();
}
Come potete vedere c’è ora un nuovo membro,
m_AI, che altro non è che un puntatore a StrategyAI. Tramite la factory otteniamo una istanza concreta di StrategyAI ad ogni chiamata della Reset, ovvero ad ogni inizio gioco. Il suo utilizzo poi è molto semplice: nel metodo HandleMouseInput, dove prima eseguivamo la logica random, ora abbiamo una sola riga:m_pAI->PlaceSymbol(m_Grid);
Piuttosto intuitivo, no?
Non ci resta che dare un’occhiata alla
StrategyFactory. La sua definizione:#ifndef STRATEGYAIFACTORY_H
#define STRATEGYAIFACTORY_H
#include "StrategyAI.h"
class StrategyAIFactory
{
public:
StrategyAIFactory();
virtual ~StrategyAIFactory();
StrategyAI* CreateStrategyAI();
protected:
private:
};
#endif // STRATEGYAIFACTORY_H
… e la relativa implementazione:
#include <cstdlib>
#include "../include/StrategyAIFactory.h"
#include "../include/DummyStrategyAI.h"
#include "../include/DefenderStrategyAI.h"
//-----------------------------------------------------------------------------
StrategyAIFactory::StrategyAIFactory()
{
//ctor
}
//-----------------------------------------------------------------------------
StrategyAIFactory::~StrategyAIFactory()
{
//dtor
}
//-----------------------------------------------------------------------------
StrategyAI*
StrategyAIFactory::CreateStrategyAI()
{
int prob = rand() % 100;
if(prob < 50) return new DummyStrategyAI();
else return new DefenderStrategyAI();
}
Banalmente andiamo a scegliere con una probabilità del 50% tra le nostre due
StrategyAI implementate. Ovviamente possiamo scrivere tutte le StrategyAI che vogliamo, arricchendo così il gioco di sfumature diverse e dando l’idea che il computer non si comporti seguendo sempre uno schema predefinito. Volendo, si potrebbe assegnare una faccina ad ogni Strategy e mostrarla nella schermata di gioco, umanizzando ulteriormente il computer e creando una certa aspettativa: il player inizierà a conoscere e distinguerei giocatori “forti” da quelli “scarsi”!Con questo abbiamo finalmente concluso. TrisLick vuole essere un piccolo esempio di come realizzare qualcosa di piccolo ma concreto, lasciando aperte eventuali possibilità di sviluppo grazie ad una architettura flessibile.
Coraggio dunque, aprite il vostro editor, scaldate il compilatore e iniziate a scrivere il vostro prossimo gioco!
Buon coding!
Etichette:
c++,
design-pattern,
factory,
programmazione,
sdl,
sdl_ttf,
strategy,
trislick,
tutorial
venerdì 9 settembre 2011
A proposito di scrittura creativa...
Scrittura creativa?!?
No, non avete sbagliato blog. Sì ma, direte voi, cosa c'entra la scrittura creativa con la programmazione e i videogiochi? Vi rispondo con un'altra domanda. Cosa c'entrano il metal, i giochi di ruolo, i manga e/o la letteratura fantasy con gli argomenti tipicamente presenti in questi post? Nulla. Però chissà perchè finiscono per l'essere, tutti o in parte, presenti nella vita del programmatore medio. Chiamatele sinergie, se volete.
Ad ogni modo fatevene una ragione perchè il post di oggi riguarda proprio la scrittura creativa, l'attività cioè di scrivere per raccontare una storia in modo colorato e interessante. Se proprio volete trovarci un appiglio con la programmazione di videogiochi, pensate ad un game designer che voglia imbastire un plot per il proprio gioco, oppure smettete semplicemente di consumarvi le unghie sugli specchi e continuate a leggere sereni.
La scrittura creativa è alla base del mestiere dello scrittore. Io non sono uno scrittore e non mi permetterei mai di trattare con leggerezza un argomento tanto nobile. Ma, per sinergia, ho provato varie volte a scrivere qualcosa, come scommetto molti di voi. Lo stato d'animo costante con cui mi sono ritrovato dopo tali esperimenti è stato quasi sempre lo stesso: insoddisfazione, con pure una punta di frustrazione. Sì, perchè i miei scritti mi apparivano (appaiono) mosci, statici, poco interessanti.
Mi sono anche documentato, sapete, su come si scrive. Ho diversi libri a casa sull'argomento, che ho sempre trovato di estremo fascino (così come ho molti metodi per chitarra, ma questa è un'altra storia e un altro vagone di frustrazioni). Ogni tanto ne prendo uno e lo rileggo. Concordo sempre su tutto quel che dice l'autore, ma poi, all'atto pratico, cado negli stessi errori.
Ho capito che scrivere è una cosa dannatamente seria e complessa. Ma ho anche capito che uno dei miei errori fondamentali sta nel mancato rispetto di una semplice regola:
Facile, no? Anzichè essere didascalici ed elencare una serie di cose che accadono, ci si dovrebbe sforzare di mostrarle senza esplicitarle. Facciamo un esempio. Dovete parlare di un tizio di nome Mario che sta per uscire di casa quando si accorge che fuori piove. Scena semplice. Ecco come appare dicendo queste cose:
Cosa si nota? Fisicamente è più lungo, il che potrebbe essere tanto un bene quanto un male. Quel che è bene invece è che mostrando le cose si è costretti a visualizzarsele nella mente, ma visualizzarsele per davvero, facendo uno sforzo. Si cercano dettagli. E saltano fuori cose a cui non avevamo pensato. Anna, per esempio, e il suo passato con Mario. Il lettore si pone delle domande. Chi è Anna? Stavano insieme? Erano sposati? Hanno divorziato? E' morta? Giuro che non avevo pensato ad Anna prima di provare a scrivere questo pezzetto, ma quando è stato il momento è saltata fuori con grande spontaneità. Anche la figura di Mario acquista spessore: anzichè il nome più comune in Italia diventa ora un personaggio di cui intuiamo qualcosa del carattere: forse pigro, abitudinario, amaro e un po' pedante. Bisognerebbe leggere il resto per capirlo.
Ci siete arrivati? Ve lo ripeto: bisognerebbe leggere il resto per capirlo. Dico, non è meraviglioso?
La prima versione, quella detta, invoglia a proseguire? Non mi pare. Questa ha forse qualche chance in più, ergo mostrare le cose le rende più vive, più interessanti; e il racconto acquista corpo e immersione, oltre a trascinarci verso soluzioni non programmate.
Ora prendete un buon libro, di un autore che stimate, e provate a leggere qualche passaggio. Dice o mostra? E' un esercizio molto divertente e che, personalmente, mi fa apprezzare ancora di più la lettura. Giusto per farvi un esempio più professionale del mio, ecco come Robert Jordan introduce il personaggio di Rand al'Thor, il suo protagonista, nell'incipit della saga La Ruota del Tempo. Io avrei scritto che Rand avanzava a fatica lungo la strada battuta dal freddo vento che scendeva dai monti, e ne sarei anche stato orgoglioso. Ma ecco come se la cava Jordan, ecco il vento:
Brrr! Che freddo!
No, non avete sbagliato blog. Sì ma, direte voi, cosa c'entra la scrittura creativa con la programmazione e i videogiochi? Vi rispondo con un'altra domanda. Cosa c'entrano il metal, i giochi di ruolo, i manga e/o la letteratura fantasy con gli argomenti tipicamente presenti in questi post? Nulla. Però chissà perchè finiscono per l'essere, tutti o in parte, presenti nella vita del programmatore medio. Chiamatele sinergie, se volete.
Ad ogni modo fatevene una ragione perchè il post di oggi riguarda proprio la scrittura creativa, l'attività cioè di scrivere per raccontare una storia in modo colorato e interessante. Se proprio volete trovarci un appiglio con la programmazione di videogiochi, pensate ad un game designer che voglia imbastire un plot per il proprio gioco, oppure smettete semplicemente di consumarvi le unghie sugli specchi e continuate a leggere sereni.
La scrittura creativa è alla base del mestiere dello scrittore. Io non sono uno scrittore e non mi permetterei mai di trattare con leggerezza un argomento tanto nobile. Ma, per sinergia, ho provato varie volte a scrivere qualcosa, come scommetto molti di voi. Lo stato d'animo costante con cui mi sono ritrovato dopo tali esperimenti è stato quasi sempre lo stesso: insoddisfazione, con pure una punta di frustrazione. Sì, perchè i miei scritti mi apparivano (appaiono) mosci, statici, poco interessanti.
Mi sono anche documentato, sapete, su come si scrive. Ho diversi libri a casa sull'argomento, che ho sempre trovato di estremo fascino (così come ho molti metodi per chitarra, ma questa è un'altra storia e un altro vagone di frustrazioni). Ogni tanto ne prendo uno e lo rileggo. Concordo sempre su tutto quel che dice l'autore, ma poi, all'atto pratico, cado negli stessi errori.
Ho capito che scrivere è una cosa dannatamente seria e complessa. Ma ho anche capito che uno dei miei errori fondamentali sta nel mancato rispetto di una semplice regola:
Mostra, non dire.
Facile, no? Anzichè essere didascalici ed elencare una serie di cose che accadono, ci si dovrebbe sforzare di mostrarle senza esplicitarle. Facciamo un esempio. Dovete parlare di un tizio di nome Mario che sta per uscire di casa quando si accorge che fuori piove. Scena semplice. Ecco come appare dicendo queste cose:
Mario si preparò per uscire di casa. Era già sull'uscio quando si accorse che stava piovendo.Lineare. Grammaticalmente corretto (spero). Abbiamo detto quel che succede. Ora proviamo a mostrarlo:
Mario indossò la giacca blu, il regalo di Anna di un qualche Natale passato, quando ancora si facevano regali tra loro, e si diresse verso la porta d'ingresso. Stava per uscire quando l'odore della pioggia lo colse. Gettò uno sguardo alla finestra in soggiorno, in parte visibile anche da lì, torcendo un po' il collo. Goccioline scivolavano sul vetro, e ora sentiva anche gli schizzi sollevati dalle macchine. Anna avrebbe sbottato, ritta sull'uscio, dicendo che erano solo due gocce e di muoversi, che erano già in ritardo. Ma tanto Anna non c'era più. Mario prese l'ombrello e uscì.Sono sicuro che un vero scrittore farebbe di meglio, ma spero di aver reso l'idea. In questa versione non ho mai detto che stava per uscire di casa, lo si intuisce dal fatto che indossa la giacca e va verso la porta. Non ho detto che stava piovendo, ho mostrato le gocce sul vetro e l'ombrello. L'odore della pioggia è un pò raccontato, lo ammetto, ma fate i conti con i miei limiti, per piacere.
Cosa si nota? Fisicamente è più lungo, il che potrebbe essere tanto un bene quanto un male. Quel che è bene invece è che mostrando le cose si è costretti a visualizzarsele nella mente, ma visualizzarsele per davvero, facendo uno sforzo. Si cercano dettagli. E saltano fuori cose a cui non avevamo pensato. Anna, per esempio, e il suo passato con Mario. Il lettore si pone delle domande. Chi è Anna? Stavano insieme? Erano sposati? Hanno divorziato? E' morta? Giuro che non avevo pensato ad Anna prima di provare a scrivere questo pezzetto, ma quando è stato il momento è saltata fuori con grande spontaneità. Anche la figura di Mario acquista spessore: anzichè il nome più comune in Italia diventa ora un personaggio di cui intuiamo qualcosa del carattere: forse pigro, abitudinario, amaro e un po' pedante. Bisognerebbe leggere il resto per capirlo.
Ci siete arrivati? Ve lo ripeto: bisognerebbe leggere il resto per capirlo. Dico, non è meraviglioso?
La prima versione, quella detta, invoglia a proseguire? Non mi pare. Questa ha forse qualche chance in più, ergo mostrare le cose le rende più vive, più interessanti; e il racconto acquista corpo e immersione, oltre a trascinarci verso soluzioni non programmate.
Ora prendete un buon libro, di un autore che stimate, e provate a leggere qualche passaggio. Dice o mostra? E' un esercizio molto divertente e che, personalmente, mi fa apprezzare ancora di più la lettura. Giusto per farvi un esempio più professionale del mio, ecco come Robert Jordan introduce il personaggio di Rand al'Thor, il suo protagonista, nell'incipit della saga La Ruota del Tempo. Io avrei scritto che Rand avanzava a fatica lungo la strada battuta dal freddo vento che scendeva dai monti, e ne sarei anche stato orgoglioso. Ma ecco come se la cava Jordan, ecco il vento:
[...] Le raffiche incollarono il mantello alla schiena di Rand al'Thor e gli sbatterono contro le gambe la lana color terra, poi la fecero svolazzare dietro di lui. Rand rimpianse di non avere una giubba più pesante o una camicia in più. Quando cercava di stringersi addosso il mantello, finiva quasi sempre per farlo impigliare nella faretra che portava appesa a un fianco; e non serviva a molto neppure provare a tenerlo fermo con una mano sola, dal momento che nell'altra reggeva l'arco, con la freccia già incoccata, pronto all'uso. Una raffica particolarmente violenta gli strappò di mano il mantello. Rand lanciò un'occhiata a Tam, suo padre, che camminava dall'altro lato dell'irsuta giumenta saura, quasi ad assicurarsi che fosse sempre lì. Si sentì un po' sciocco, ma era una di quelle giornate in cui si ha bisogno di conforto. [...]
Brrr! Che freddo!
mercoledì 31 agosto 2011
Il gioco indie che forse non conoscete: Bomber Planet!
Ci sono alcuni indie che è sempre bello seguire, e tra questi quel tizio che risponde al nick di Adamatomic, o Mr.Canabalt per i più.
In occasione della ventunesima edizione del Ludum Dare, il buon Adam ha sfornato uno dei 509 giochi presentati. Bomber Planet non è il migliore nè il peggiore, possiamo anzi dire che si mescola tra i tanti, ma è uno di quelli che ho potuto provare (sì, ho provato anche quello di Notch e no, non ne parlerò) e devo dire che mi ha lasciato quel piacevole senso di deja vù.
Ricorda moltissimo un gioco che ho amato nell'Amiga 500: Bomberman. Il gameplay è pressochè identico e il titolo un chiaro richiamo, oltre alla grafica in pixel art. L'unica differenza è che, anzichè farsi strada livello dopo livello nella vecchia concezione arcade, in Bomber Planet occorre esplorare un complesso di caverne per trovare l'uscita (in tema con il titolo del contest: Escape), sfasciando blocchi di pietra e strane creature mediante bombe ad orologeria.
In definitiva un buon coffeebreak game, che ha avuto il merito di riuscire a rievocare davvero il retrogaming, almeno al sottoscritto.
In occasione della ventunesima edizione del Ludum Dare, il buon Adam ha sfornato uno dei 509 giochi presentati. Bomber Planet non è il migliore nè il peggiore, possiamo anzi dire che si mescola tra i tanti, ma è uno di quelli che ho potuto provare (sì, ho provato anche quello di Notch e no, non ne parlerò) e devo dire che mi ha lasciato quel piacevole senso di deja vù.
Ricorda moltissimo un gioco che ho amato nell'Amiga 500: Bomberman. Il gameplay è pressochè identico e il titolo un chiaro richiamo, oltre alla grafica in pixel art. L'unica differenza è che, anzichè farsi strada livello dopo livello nella vecchia concezione arcade, in Bomber Planet occorre esplorare un complesso di caverne per trovare l'uscita (in tema con il titolo del contest: Escape), sfasciando blocchi di pietra e strane creature mediante bombe ad orologeria.
In definitiva un buon coffeebreak game, che ha avuto il merito di riuscire a rievocare davvero il retrogaming, almeno al sottoscritto.
Etichette:
bomber planet,
canabalt,
indie,
ludum dare,
videogiochi
Iscriviti a:
Post (Atom)

