Posts tagged guida

Ridimensionare una Sprite – Grafica – XNA Tutorials

Ridimensionare una sprite, al pari della rotazione, è un’operazione molto semplice, nonostante sia molto comune in tantissimi giochi. Comunque sia, chiacchiere a parte, in questo articolo affronteremo due metodi di ridimensionamento: prima quello “fisso”, ovvero il disegno della texture ridimensionata, e successivamente quello “variabile” tramite input da tastiera.

  • Ridimensionamento “fisso”

Il nocciolo della questione, come potete immaginare, si trova nel metodo Draw, che come abbiamo detto prima è il punto in cui i contenuti vengono disegnati su schermo. A fare la parte importante, nel nostro caso, è il rettangolo che noi diamo come parametro nel metodo Draw dello SpriteBatch da noi utilizzato. Nello specifico, di questo rettangolo modificheremo larghezza ed altezza.

Ecco il metodo Draw:

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();

            spriteBatch.Draw(immagine, new Rectangle(10, 10, immagine.Width * 2, immagine.Height * 2), Color.White);

            spriteBatch.End();

            base.Draw(gameTime);
        }

Stavolta ho semplicemente dato come dimensione del rettangolo una larghezza pari al doppio della rispettiva nell’immagine e un’altezza calcolata in egual modo. Il risultato? Eccolo.

asd

(Click per ingrandire)

Adesso passiamo all’ingrandimento dato dall’input dell’utente. Anche questo è molto semplice da gestire: tuttavia, richiederà qualche variabile in più in quanto abbiamo dei problemi a livello di tipo di variabili.

Senza titolo-2

Mi spiego meglio: come potete vedere dall’intellisense, la proprietà Width e Height di una texture sono di tipo Int. Questo vuol dire che, per ottenere un’ingrandimento di, toh, una volta e mezzo (x1.5) avremo dei problemi  rimanendo ad usare gli interi. Per cui, ecco cosa faremo.

  1. Creiamo una variabile di tipo float, chiamata moltiplicatore. Qui memorizzeremo il valore da usare per la moltiplicazione nel ridimensionamento.
  2. Modifichiamo il metodo Update in modo da gestire l’input da tastiera.
  3. Modifichiamo il metodo Draw in modo da disegnare bene la nostra immagine.

Ecco la nostra variabile:

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Texture2D immagine;

        float moltiplicatore = 1.0f;

In fase di disegno moltiplicheremo le dimensioni dell’immagine per questo valore. Ponendo come valore iniziale 1.0, inizialmente la nostra immagine verrà disegnata nella sua grandezza naturale.

Ora gestiamo l’input da parte dell’utente: stavolta i tasti che useremo saranno il “+” per ingrandire ed il “-” per rimpicciolire. Il metodo Update verrà riscritto così:

        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Add))
            {
                if (moltiplicatore < 2.0f)
                {
                    moltiplicatore += 0.05f;
                }
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Subtract))
            {
                if (moltiplicatore > 0.5f)
                {
                    moltiplicatore -= 0.05f;
                }
            }

            base.Update(gameTime);
        }

Per evitare problemi nel mostrare l’immagine (dimensioni negative e così via) ho limitato il ridimensionamento in modo tale che vada da un minimo di 0.5 (la metà della grandezza originale) a 2.0 (il doppio ;) ). I valori “Keys.Add” e “Keys.Subtract” sono i corrispettivi del “+” e del “-”.

(nel caso togliate i limiti del ridimensionamento, andando in negativo si ottiene l’immagine capovolta, quando la variabile moltiplicatore è diversa da zero)

Infine ecco il metodo Draw riscritto:

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();

            spriteBatch.Draw(immagine, new Rectangle(10, 10, (int)(immagine.Width * moltiplicatore), (int)(immagine.Height * moltiplicatore)), Color.White);

            spriteBatch.End();

            base.Draw(gameTime);
        }

Ogni dimensione viene moltiplicata per il moltiplicatore (gioco di parole non voluto) e successivamente visto come int tramite l’aggiunta di “(int)” dietro l’espressione da usare. Potete provare voi stessi il tutto senza ulteriori spiegazioni :D

  • Share/Bookmark

Ruotare una Sprite – Grafica – XNA Tutorials

Dunque, ora vediamo un pò, dopo aver imparato a disegnare una sprite su schermo, come ruotarla e disegnare quindi questo effetto. Questo articolo sarà suddiviso in due parti: nella prima osserveremo da vicino il metodo che utilizzeremo. Successivamente, creeremo un metodo che richiamato ad ogni frame darà l’effetto di movimento nella rotazione.

  • Il Metodo

Ecco qui il metodo da noi utilizzato: lo riporto qui di seguito e successivamente spiegherò ogni parametro. Per provare l’esempio vi basterà copiare il codice qui di seguito (adattandolo con i nomi degli oggetti che voi avete deciso)  sull’esempio dell’articolo precedente, senza cambiare altro.

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();

            spriteBatch.Draw(
                immagine,
                new Rectangle(400,200,immagine.Width,immagine.Height),
                null,
                Color.White,
                40,
                new Vector2(immagine.Width/2,immagine.Height/2),
                SpriteEffects.None,
                0
                );

            spriteBatch.End();

            base.Draw(gameTime);
        }

Il primo parametro, la Texture2D immagine, è semplicemente la texture che abbiamo caricato precedentemente in memoria e che vogliamo utilizzare.

Il secondo parametro, invece, è un oggetto Rectangle nel quale specifico la posizione nella quale voglio disegnare la texture e le dimensioni di questa.

Il terzo parametro, che dovrebbe rappresentare un’altro rettangolo, è stavolta definito come null. Potrebbe non significare niente, ma questo metodo Draw consente di disegnare anche delle parti di texture. Più avanti magari vedremo come funziona meglio questo discorso.

Il quarto parametro è il classico colore visto anche precedentemente. Ho specificato il White come nell’esempio precedente.

Il quinto parametro è invece proprio ciò che serve a noi: l’angolo della rotazione che vogliamo ottenere. Stavolta ho messo quaranta come primo valore che mi è venuto in mente, per fare l’esempio.

Il sesto parametro è un vettore che serve a definire quale sarà il centro della rotazione. E’ importantissimo e, dato che noi vogliamo far ruotare l’oggetto intorno a se stesso, il punto che prenderemo in considerazione sarà il centro preciso, ovvero la metà della lunghezza e la metà dell’altezza.

Gli altri due parametri finali per ora non ci interessano molto, lasciamoli così.

Et voilà, ecco il risultato:

5466545462

(Click per Ingrandire)

La nostra sprite è stata ruotata e il risultato è visibile su schermo.

  • Il Movimento

Wow, ad essere ruotata la nostra immagine è effettivamente ruotata. Ma se vogliamo farla muovere? L’effetto di rotazione può avvenire in tanti modi. Vi farò vedere due possibili casi: in base ad un fattore fisso (ad ogni frame ruoteremo di un tot la nostra immagine) oppure in base all’input dell’utente.

Vediamo come ruotare l’immagine in base ad un fattore fisso. Per rendere le cose semplici, ho dichiarato una variabile che rappresenterà l’angolo di rotazione.

public class Game1 : Microsoft.Xna.Framework.Game
{
   GraphicsDeviceManager graphics;
   SpriteBatch spriteBatch;

   Texture2D immagine;

   //ecco la nostra variabile, impostata inizialmente a zero.
   float rot = 0f;

Una volta creata questa variabile, la andiamo ad inserire nel contesto. Per prima cosa dobbiamo contare che la rotazione può avvenire (dato che parliamo in gradi) da 0° a 360°. Per questo ho deciso di scrivere in questo modo il metodo Update:

        protected override void Update(GameTime gameTime)
        {
            if (rot != 360) rot += 0.1f; else rot = 0f;

            base.Update(gameTime);
        }

L’operazione è veramente semplice da capire: ad ogni frame aggiungo 0.1 al al valore della rotazione. Appena verrà raggiunto il valore 360, la variabile verrà reimpostata a zero, in modo tale che il ciclo rinizi nuovamente. A questo punto basterà modificare il parametro in input nel metodo Draw:

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();

            spriteBatch.Draw(
                immagine,
                new Rectangle(400,200,immagine.Width,immagine.Height),
                null,
                Color.White,
                rot,
                new Vector2(immagine.Width/2,immagine.Height/2),
                SpriteEffects.None,
                0
                );

            spriteBatch.End();

            base.Draw(gameTime);
        }

Testiamo tutto premendo F5. Vi renderete conto da soli del risultato. Potete inoltre modificare il centro di rotazione per vedere le differenze: provate per esempio a togliere il “diviso due” dai valori dati in input, e vedrete l’immagine ruotare intorno al punto in basso a destra ;)

Adesso invece scopriremo come ruotare un’immagine in base all’input dell’utente. Qui inserirò solo delle istruzioni basilari e facili da capire, in modo tale da non complicare le cose. Il nostro obiettivo è il seguente: alla pressione della freccia destra sulla tastiera, la nostra immagine ruoterà.

Lasciamo immutato il metodo Draw, concentriamoci solamente sull’Update. Come potrete facilmente intuire, quello che faremo sarà veramente semplice: aumenteremo il valore della variabile rot solo quando il tasto sarà premuto. Per fare questo cambieremo il metodo Update in:

        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Right))
            {
                if (rot != 360) rot += 0.1f; else rot = 0f;
            }

            base.Update(gameTime);
        }

In questo caso ho semplicemente controllato, con istruzioni tra l’altro comprensibili (IsKeyDown(Keys.Right), per esempio) la pressione del tasto da noi desiderato.

Provate il risultato, alla prossima! ;)

  • Share/Bookmark

Disegnare una Sprite su schermo – Grafica – XNA Tutorials

In questo articolo scopriremo come si può disegnare su schermo una sprite con XNA. Come prima cosa avviamo l’ambiente di sviluppo e creiamo un nuovo progetto (Come si fa?). Ora, quello che noi dobbiamo fare essenzialmente è innanzitutto caricare in memoria la nostra sprite. Successivamente, andare a modificare il codice del metodo Draw per poter disegnare sullo schermo quello che vogliamo.

Ecco l’immagine che disegneremo su schermo:

Autostima alle stelle, eh?

  • Importiamo l’immagine nel progetto.

Come prima cosa, dobbiamo importare la nostra immagine in modo tale da essere riconosciuta. Le possibilità, in questo caso, sono due:

  1. Importare l’immagine con il ContentManager;
  2. Caricare l’immagine direttamente da file;

Ovviamente, spiegherò sia un metodo che l’altro.

Per caricare un’immagine con il ContentManager, importiamo il file cliccando con il pulsante destro su Content, nella scheda Esplora Soluzioni, selezionando quindi Aggiungi -> Elemento Esistente.

123

La voce Content evidenziata nella scheda Esplora Soluzioni.

Si aprirà una classica finestra di apertura file: selezioniamo il file da importare e confermiamo. Ora ecco come appare la voce Content:

asd

Attenzione: quando importerete l’immagine (se usate la mia immagine di esempio) il nome non è lo stesso. Ho modificato il nome direttamente da Esplora Soluzioni per rendere l’uso del file più agevole.

Bene, adesso dobbiamo aggiungere il codice: innanzitutto facciamo le prime modifiche subito dopo la dichiarazione dell’oggetto SpriteBatch.

public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        // Ecco la nostra texture.
        Texture2D immagine;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

Come potete vedere, ho dichiarato un nuovo oggetto di tipo Texture2D: rappresenta esattamente la nostra immagine. Ora dobbiamo dire a quest’oggetto di prendere come immagine di riferimento la nostra. Il codice da utilizzare, posto nel metodo LoadContent, è il seguente:

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            immagine = Content.Load<Texture2D>("texture");
        }

In parole povere abbiamo usato il metodo Load del ContentManager (con tipo Texture2D) e abbiamo passato come parametro una stringa contenente il nome del file importato senza estensione.

Con questa istruzione abbiamo completato questo tipo di caricamento. Spesso, tuttavia, per alcune scelte è possibile evitare tutto questo procedimento, caricando la nostra Texture in modo differente. Nello specifico, il metodo che sto per illustrare permette di caricare la texture specificando il percorso della nostra immagine.

Supponiamo che nella cartella dell’eseguibile del gioco ci sia un’altra cartella, che chiameremo Graphics. In questa cartella vi sarà la nostra immagine. Ecco un’immagine per farvi capire meglio.

Senza titolo-6

(Click per Ingrandire)

Stavolta, per caricare la nostra texture, ecco cosa dovremo fare:

Senza aggiungere con il ContentManager il nostro file, basterà cambiare il metodo LoadContent come riportato qui di seguito:

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            immagine = Texture2D.FromFile(GraphicsDevice, "Graphics/texture.jpg");
        }

Stavolta abbiamo utilizzato il metodo FromFile della classe Texture2D. Come parametri del metodo passiamo l’oggetto GraphicDevice e una stringa che contiene il percorso del file. Nulla di più, e anche in questo modo la nostra texture è pronta per essere utilizzata!

  • Disegnamo la Sprite su schermo

La fase di disegno è ancora più semplice.

Come prima cosa passiamo dal metodo LoadContent al metodo Draw: basterà aggiungere queste tre righe di codice per disegnare la nostra Sprite.

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();

            spriteBatch.Draw(immagine, new Vector2(0, 0), Color.White);

            spriteBatch.End();

            // TODO: Add your drawing code here
            base.Draw(gameTime);
        }

Per prima cosa abbiamo avviato lo SpriteBatch, l’oggetto che si occupa delle operazioni di disegno. Ricordatevi, il metodo Begin() deve essere sempre chiamato prima di qualsiasi disegno, altrimenti vi verrà restituito un errore.

Successivamente chiamiamo il metodo Draw, al quale passiamo i seguenti parametri:

  • nome dell’oggetto Texture2D da disegnare,
  • la posizione dell’oggetto sullo schermo,
  • il colore da usare per il channel modulation (vi basti sapere per ora che usare Color.White è più che sufficiente, in seguito vedremo cosa succede variando questo valore)

Infine richiamiamo il metodo End() dello SpriteBatch. Ed ecco il risultato sullo schermo:

Senza titol654

(Click per Ingrandire)

Come vedete, basta veramente poco a disegnare qualcosa su schermo. Nei prossimi articoli vedremo un pò come realizzare animazioni, ruotare queste texture ed ingrandirle o rimpicciolirle.

Bye :D

  • Share/Bookmark

Download dei files necessari – Inizio e Preparazione – XNA Tutorials

Il titolo dice tutto: come prima cosa dobbiamo prendere tutti i programmi di cui avremo bisogno, installarli e quindi iniziare a lavorare. Il download dei files a noi necessari è veramente semplice e non richiede operazioni complicate. Come prima cosa, andiamo su

http://creators.xna.com/it-IT/downloads

la pagina di download ufficiale di tutti i programmi (e relativi prerequisiti) che utilizzeremo nello sviluppo del nostro gioco.  Al momento in cui scrivo, questi sono i downloads messi a disposizione nella pagina:

  • XNA Game Studio 3.1 (che utilizzeremo durante i nostri tutorials)
  • XNA Game Studio 3.1 Documentation
  • Visual C# Express Edition
  • DirectX SDK
  • DirectX Runtime Web Installer

cco_resources_downloads_downloadItemImage_XNAGS3.1

Cliccando sulla voce di download di XNA Game Studio, verremo indirizzati alla pagina del download vera e propria, su microsoft.com/downloads. La schermata che vi dovreste trovare davanti è questa:

111

(Click per ingrandire)

basterà cliccare sul pulsante “Download” per iniziare immediatamente il download di questo primo componente. Ma proseguiamo, le cose non finiscono qui.

cco_dwnld_msdn

Le librerie e i file della guida in linea saranno essenziali per lo sviluppo del vostro gioco o programma con XNA Game Studio. Molto spesso infatti sarà necessario andare a cercare informazioni per un metodo, una proprietà oppure una classe messa a disposizione dal Framework. Qui c’è poco da dire e nulla da installare, la documentazione è tranquillamente accessibile da internet.

Una copia della guida, inoltre, sarà installata sul proprio pc in modo tale da essere consultabile anche in assenza di collegamento ad internet.

cco_dwnld_visualc2008

Visual C# 2008 Express Edition è la versione gratuita dell’ide Microsoft dedicato al C#. Non c’è bisogno che ve ne parli in quanto penso che un minimo lo conosciate già. Ma vediamo come scaricarlo. Quando cliccheremo sul link riportato, verremo redirezionati sulla home page delle versioni Express di Visual Studio. Scorriamo la pagina, nella quale potremo dare un’occhiata ai vari prodotti della suite. Una volta che troverete la voce relativa al Visual C# (come nell’immagine sotto), basterà selezionare l’Italiano come lingua e poi cliccare su Download.

Senza titolo-2

Una volta che avvierete il file scaricato, non vi preoccupate di eseguire altre operazioni, in quanto l’installer si occuperà di installare tutti i prerequisiti necessari. Probabilmente, nel caso non sia presente sulla macchina, verrà installato anche il .NET Framework più recente.

Ora, già con questi componenti installati non dovreste avere molti problemi: in molti casi i runtime directx sono già installati e nel caso non lo siano vi verranno richiesti.

  • Share/Bookmark

Mettiamo tutto insieme (Conclusioni) – Creazione di un gioco con SDL.NET

In realtà sotto questo punto di vista c’è tanto da scrivere ma anche poco da scrivere: tanto perchè ci sarebbe innanzitutto da compilare il nostro codice. Una volta ottenuti gli eseguibili funzionanti dobbiamo avere una precisa struttura della cartella del nostro programma. Ed a questo, come avete visto, ci abbiamo pensato in precedenza.

Dobbiamo testare a fondo il gioco, in modo tale da notare rallentamenti (non in questo caso ovviamente). Nel caso ci sia qualcosa che non va, si riprende il codice e lo si modifica, si cercano degli errori. Certo, questo è facile da dire ma spesso è assolutamente stancante da fare nella pratica. Nonostante abbia fatto questo gioco in due giorni scarsi c’è da dire che non era tutto perfetto da subito: man mano che andavo avanti ho fatto prove, compilato, ricompilato e modificato per poi compilare nuovamente.

Niente perchè, appunto, è facile da scrivere ma difficile da fare.

Una grande fortuna, devo ammetterlo, è stato quello di poter lavorare con un linguaggio managed come il C#, eliminando in questo modo tutta una serie di problemi che si potevano presentare con un linguaggio si più efficace, ma altrettanto complesso come il C++.

Adesso che abbiamo la nostra struttura pronta, non dobbiamo fare altro che creare un programma di installazione per il nostro gioco: potrete scoprire come si fa leggendo l’articolo dedicato a questo scopo su questo stesso blog.

Grazie per l’ascolto!

  • Share/Bookmark

Gestiamo l’Input. – Creazione di un gioco con SDL.NET

Il gioco che stiamo creando, ovviamente, non va mica avanti da solo. Qualcuno deve far muovere le cose, fare in modo che determinati eventi e determinati spostamenti avvengano. Quel qualcuno è il nostro giocatore. Come già spiegato nella “guida base” l’input è gestito facilmente dalle librerie SDL e applicare questi concetti alla pratica sarà ancora più facile.

In tutta la struttura del gioco c’è solo un metodo che si occupa di prendere tutto l’input ed elaborarlo: il metodo Events_KeyboardDown. Ecco il codice, riproposto qui di seguito, che verrà successivamente commentato in modo da essere compreso in tutto e per tutto.

[code]]czoyNDcwOlwiDQpwcml2YXRlIHZvaWQgRXZlbnRzX0tleWJvYXJkRG93bihvYmplY3Qgc2VuZGVyLCBLZXlib2FyZEV2ZW50QXJncyB7WyYqJl19ZSkNCiAgICAgICAgew0KICAgICAgICAgICAgc3dpdGNoIChzdGF0bykNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBjYXtbJiomXX1zZSBHYW1lU3RhdGUuSW50cm86DQogICAgICAgICAgICAgICAgICAgIGlmIChlLktleSA9PSBLZXkuUmV0dXJuKSBzdGF0byA9IEdhe1smKiZdfW1lU3RhdGUuR2FtZTsNCiAgICAgICAgICAgICAgICAgICAgaWYgKGUuS2V5ID09IEtleS5Fc2NhcGUpIHN0YXRvID0gR2FtZVN0YXR7WyYqJl19ZS5FeGl0Ow0KICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgIGNhc2UgR2FtZVN0YXRlLkdhbWU6DXtbJiomXX0KICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHN0YXRvX3ApDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAge1smKiZdfSAgICAgICAgICBjYXNlIFN0YXRvUGFydGl0YS5QcmltYToNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGUuS2V7WyYqJl19eSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgS2V5LntbJiomXX1SZXR1cm46DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0b19wID0gU3RhdG9QYXJ0aXRhLkluQ29yc287e1smKiZdfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUmVzZXRHYW1lKCk7DQoNCiAgICAgICAgICAgICAgICAgICAgICB7WyYqJl19ICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEtleS5Fc2NhcGU6DQogIHtbJiomXX0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdG8gPSBHYW1lU3RhdGUuRXhpdDsNCiAgICAgICAgICAgICAgICAge1smKiZdfSAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICB7WyYqJl19ICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFN0YXRvUGFydGl0YS5JbkNvcnNvOg0KICAgIHtbJiomXX0gICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGUuS2V5KQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAge1smKiZdfSAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgS2V5LkxlZnRBcnJvdzoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7WyYqJl19ICAgICAgICBpZiAocG9zaXppb25lX2dpb2NhdG9yZSA+IDApIHBvc2l6aW9uZV9naW9jYXRvcmUtLTsNCiAgICAgICAgICAgICAgIHtbJiomXX0gICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEtleS5SaWdoe1smKiZdfXRBcnJvdzoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwb3NpemlvbmVfZ2lvY2F0b3JlIDwgcG9zaXp7WyYqJl19aW9uaV9naW9jYXRvcmUuQ291bnQgLSAxKSBwb3NpemlvbmVfZ2lvY2F0b3JlKys7DQogICAgICAgICAgICAgICAgICAgICAgICAgIHtbJiomXX0gICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBLZXkuRXNjYXBlOg0KICAgICAge1smKiZdfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlc2V0R2FtZSgpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7WyYqJl19ICAgIHN0YXRvX3AgPSBTdGF0b1BhcnRpdGEuUHJpbWE7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3tbJiomXX07DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAge1smKiZdfSAgICAgICAgICAgICAgICAgICAgY2FzZSBTdGF0b1BhcnRpdGEuRmluZToNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN7WyYqJl19d2l0Y2ggKGUuS2V5KQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtbJiomXX0gIGNhc2UgS2V5LlJldHVybjoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRvX3AgPSBTdGF0b1BhcnRpe1smKiZdfXRhLlByaW1hOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICB7WyYqJl19ICAgICAgICAgICAgIGNhc2UgS2V5LkVzY2FwZToNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRvID0gR3tbJiomXX1hbWVTdGF0ZS5FeGl0Ow0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAge1smKiZdfSAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICB7WyYqJl19ICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICBjYXNlIEdhbWVTdGF0ZS5FeGl0Og0KDQogICAgICAgIHtbJiomXX0gICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KXCI7e1smKiZdfQ==[[/code]

Innanzitutto diamo uno sguardo ai parametri in input: c'è il sender, di tipo generico object, e la variabile “e” di tipo KeyboardEventArgs. Proprio quest'ultima variabile sarà il perno di tutto il metodo.

Prima di dare uno sguardo al codice, inoltre, ricordatevi sempre che stiamo ragionando in base agli stati: diverso è lo stato in cui il gioco si trova, diverse saranno le necessità a cui dovremo far fronte. In parole povere: ci troviamo nella schermata d'introduzione? Non ci sarà bisogno di gestire lo spostamento del personaggio. E così via discorrendo.

Di conseguenza opereremo in questo modo: creando prima uno switch che comprenda i casi di tutti gli stati, e per ognuno di essi effettuare operazioni diverse. Partiamo dal primo caso:

[code]]czoxOTM6XCINCmNhc2UgR2FtZVN0YXRlLkludHJvOg0KICAgICAgICAgICAgICAgICAgICBpZiAoZS5LZXkgPT0gS2V5LlJldHVybil7WyYqJl19IHN0YXRvID0gR2FtZVN0YXRlLkdhbWU7DQogICAgICAgICAgICAgICAgICAgIGlmIChlLktleSA9PSBLZXkuRXNjYXBlKSBzdGF0b3tbJiomXX0gPSBHYW1lU3RhdGUuRXhpdDsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQpcIjt7WyYqJl19[[/code]

Questo è sicuramente il caso più semplice. Fin quando il gioco si troverà nello stato Intro, verrà mostrato a schermo il background con le istruzioni del gioco, oltre ad un invito a premere invio per continuare. Dunque, sono due le cose che possiamo fare: o passiamo alla schermata di gioco oppure ce ne usciamo.

Qui arriva in nostro aiuto il parametro “e”. La proprietà e.Key, infatti, permette di sapere se in quel momento un determinato pulsante sulla tastiera è stato premuto. Il controllo, nella sua maniera più semplice, avviene con questa sintassi:

if (e.Key == Key.codice_chiave) // qui vanno le operazioni da eseguire.

Come potete vedere dall'intellisense, Key (e non e.Key, che è una proprietà) è un enumerazione comprendente tutti i caratteri della tastiera. Quindi ci basterà confrontare e.Key con un valore di Key per sapere se quel determinato pulsante è stato premuto.

Tornando al nostro codice, quindi, nella prima riga verifichiamo che il tasto invio venga premuto. Nel caso viene premuto (e l'uguaglianza ritorna true) allora lo stato viene modificato in GameState.Game. Se invece la condizione non è verificata tutto rimane come prima.

Nella seconda istruzione le cose sono simili: verifichiamo che il pulsante ESC venga premuto. Se si allora passeremo allo stato GameState.Exit, che provvederà a farci uscire dal programma. Altrimenti tutto rimarrà invariato e la schermata continuerà ad essere mostrata. Andiamo avanti col nostro codice.

[code]]czoyMDI2OlwiDQogY2FzZSBHYW1lU3RhdGUuR2FtZToNCiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChzdGF0b19wKQ0KICAgICB7WyYqJl19ICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTdGF0b1BhcnRpdGEuUHJpbWE6DQogICAgICAgIHtbJiomXX0gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZS5LZXkpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAge1smKiZdfSAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBLZXkuUmV0dXJuOg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7WyYqJl19IHN0YXRvX3AgPSBTdGF0b1BhcnRpdGEuSW5Db3JzbzsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlc2V0R3tbJiomXX1hbWUoKTsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAge1smKiZdfSAgICAgICAgICAgIGNhc2UgS2V5LkVzY2FwZToNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRvID0gR2F7WyYqJl19bWVTdGF0ZS5FeGl0Ow0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgIHtbJiomXX0gICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAge1smKiZdfWNhc2UgU3RhdG9QYXJ0aXRhLkluQ29yc286DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlLktleSkNCiAgICB7WyYqJl19ICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEtleS5MZWZ0QXJyb3tbJiomXX13Og0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBvc2l6aW9uZV9naW9jYXRvcmUgPiAwKSBwb3Npemlve1smKiZdfW5lX2dpb2NhdG9yZS0tOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICB7WyYqJl19ICAgICAgICAgICAgICAgICAgIGNhc2UgS2V5LlJpZ2h0QXJyb3c6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtbJiomXX0gaWYgKHBvc2l6aW9uZV9naW9jYXRvcmUgPCBwb3NpemlvbmlfZ2lvY2F0b3JlLkNvdW50IC0gMSkgcG9zaXppb25lX2dpb2NhdG9ye1smKiZdfWUrKzsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICB7WyYqJl19ICAgICAgICBjYXNlIEtleS5Fc2NhcGU6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZXNldEdhbWUoKTsNCntbJiomXX0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0b19wID0gU3RhdG9QYXJ0aXRhLlByaW1hOw0KICAgICAgICAge1smKiZdfSAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICB7WyYqJl19ICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU3RhdG9QYXJ0aXRhLkZpbmU6DXtbJiomXX0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlLktleSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e1smKiZdfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEtleS5SZXR1cm46DQogICAgICAgICAgICAgICAgICAgICAgICB7WyYqJl19ICAgICAgICAgICAgc3RhdG9fcCA9IFN0YXRvUGFydGl0YS5QcmltYTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtbJiomXX0gICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEtleS5Fc2NhcGU6DQogICAgICAgICAgICAge1smKiZdfSAgICAgICAgICAgICAgICAgICAgICAgc3RhdG8gPSBHYW1lU3RhdGUuRXhpdDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7WyYqJl19ICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYntbJiomXX1yZWFrOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KXCI7e1smKiZdfQ==[[/code]

Dunque, in questa parte di codice stiamo gestendo il caso dello stato GameState.Game. Ci troviamo nella schermata di gioco vera e propria e, quindi, è da qui che dobbiamo partire per gestire i vari stati in cui si trova la partita (la variabile stato_p).

Per questo apriamo un nuovo switch, stavolta prendendo in esame il valore della variabile, appunto, stato_p.

Nel primo caso il discorso è semplice: ci troviamo nella schermata in cui il gioco non ancora inizia e possiamo fare solo due cose: o premere invio per iniziare la partita, oppure premere esc per uscire dal gioco. In codice, ciò si traduce in:

[code]]czo1NDI6XCINCmNhc2UgU3RhdG9QYXJ0aXRhLlByaW1hOg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZS5LZXl7WyYqJl19KQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBLZXkuUntbJiomXX1ldHVybjoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRvX3AgPSBTdGF0b1BhcnRpdGEuSW5Db3JzbzsNe1smKiZdfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZXNldEdhbWUoKTsNCg0KICAgICAgICAgICAgICAgICAgICAgICB7WyYqJl19ICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgS2V5LkVzY2FwZToNCiAgIHtbJiomXX0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0byA9IEdhbWVTdGF0ZS5FeGl0Ow0KICAgICAgICAgICAgICAgICAge1smKiZdfSAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICB7WyYqJl19ICAgICAgICAgYnJlYWs7DQpcIjt7WyYqJl19[[/code]

Come potete vedere, al posto di fare più if ho fatto un altro blocco switch con i casi corrispondenti ai pulsanti che volevo gestire. Se premiamo invio lo stato della partita passa da "Prima" a "InCorso" e le statistiche di gioco vengono resettate tramite ResetGame(). Nel caso in cui venga premuto Esc, invece, c'è poco da dire: la variabile "stato" passa a GameState.Exit e usciremo dal gioco dopo gli opportuni passaggi.

Per il caso della partita in corso, invece, le cose da gestire sono giusto un paio in più.

[code]]czo3ODg6XCINCmNhc2UgU3RhdG9QYXJ0aXRhLkluQ29yc286DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlLkt7WyYqJl19ZXkpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEtleXtbJiomXX0uTGVmdEFycm93Og0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBvc2l6aW9uZV9naW9jYXRvcmUgPiAwe1smKiZdfSkgcG9zaXppb25lX2dpb2NhdG9yZS0tOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICB7WyYqJl19ICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgS2V5LlJpZ2h0QXJyb3c6DQogICAgICAgICAgICAgICAgICAgICAgICAgIHtbJiomXX0gICAgICAgICAgaWYgKHBvc2l6aW9uZV9naW9jYXRvcmUgPCBwb3NpemlvbmlfZ2lvY2F0b3JlLkNvdW50IC0gMSkgcG9zaXppb25le1smKiZdfV9naW9jYXRvcmUrKzsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICB7WyYqJl19ICAgICAgICAgICAgICAgICBjYXNlIEtleS5Fc2NhcGU6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZXNldHtbJiomXX1HYW1lKCk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0b19wID0gU3RhdG9QYXJ0aXRhLlByaW1hOw0Ke1smKiZdfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiB7WyYqJl19ICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQpcIjt7WyYqJl19[[/code]

Si fa il classico switch per vedere qualche tasto è stato premuto e ora i tasti da gestire sono tre: la freccia sinistra (Key.LeftArrow nella nostra enumerazione Key), la freccia destra (corrispondente a RightArrow) e il tasto Esc per uscire dalla partita in corso. Non è stata prevista una pausa durante il gioco.

E per ultimo gestiamo il caso della partita terminata:

[code]]czo0ODk6XCINCmNhc2UgU3RhdG9QYXJ0aXRhLkZpbmU6DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGUuS2V7WyYqJl19eSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgS2V5LntbJiomXX1SZXR1cm46DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0b19wID0gU3RhdG9QYXJ0aXRhLlByaW1hOw0Ke1smKiZdfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7WyYqJl19ICBjYXNlIEtleS5Fc2NhcGU6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0byA9IEdhbWVTdGF0ZS5FeHtbJiomXX1pdDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAge1smKiZdfSB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQpcIjt7WyYqJl19[[/code]

Non credo serva spiegare davvero quello che ho fatto, è lo stesso identico procedimento che ho adoperato per i due casi precedenti.

Bene, anche per l'input ci siamo e, a meno che non ci siamo scordati qualcosa in precedenza, il nostro gioco è praticamente completo a livello di codice. Adesso ci prepareremo per la compilazione, concludendo così l'ultimo articolo di questa serie di tutorials.

  • Share/Bookmark

Disegnamo la moglie. – Creazione di un gioco con SDL.NET

Torniamo ad esaminare il codice di prima, facendo una piccola aggiunta in grassetto:

[code]]czoyMjQzOlwiDQpwcml2YXRlIHZvaWQgVXBkYXRlUGFydGl0YSgpDQogICAgICAgIHsNCiAgICAgICAgICAgIHN3aXRjaCAoc3RhdG97WyYqJl19X3ApDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgY2FzZSBTdGF0b1BhcnRpdGEuUHJpbWE6DQogICAgICAgICAgICAgIHtbJiomXX0gICAgICBWaWRlby5TY3JlZW4uQmxpdChiYWNrZyk7DQogICAgICAgICAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5CbGl0KGYxLlJle1smKiZdfW5kZXIoXCJQdW50ZWdnaW86IDBcIiwgU3lzdGVtLkRyYXdpbmcuQ29sb3IuQmxhY2spLCBuZXcgU3lzdGVtLkRyYXdpbmcuUG9pbnQoNntbJiomXX0wLCAyKSk7DQogICAgICAgICAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5CbGl0KGYxLlJlbmRlcihcIlByZW1pIEludmlvIHBlciBpbntbJiomXX1pemlhcmUgbGEgcGFydGl0YS4uLlwiLCBTeXN0ZW0uRHJhd2luZy5Db2xvci5CbGFjayksIG5ldyBTeXN0ZW0uRHJhd2luZy5Qb2ludHtbJiomXX0oNjAsIDE3KSk7DQogICAgICAgICAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5CbGl0KGYxLlJlbmRlcihcIlZpdGU6IDBcIiwgU3lzdGV7WyYqJl19bS5EcmF3aW5nLkNvbG9yLkJsYWNrKSwgbmV3IFN5c3RlbS5EcmF3aW5nLlBvaW50KDQwMCwgMikpOw0KICAgICAgICAgICAgICAgIHtbJiomXX0gICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICBjYXNlIFN0YXRvUGFydGl0YS5JbkNvcnNvOg0KICAgICAgICAgICAgICAgICAge1smKiZdfSAgVmlkZW8uU2NyZWVuLkJsaXQoYmFja2cpOw0KICAgICAgICAgICAgICAgICAgICBWaWRlby5TY3JlZW4uQmxpdChmMS5SZW5kZXJ7WyYqJl19KFwiUHVudGVnZ2lvOiBcIiArIHB1bnRlZ2dpby5Ub1N0cmluZygpLCBTeXN0ZW0uRHJhd2luZy5Db2xvci5CbGFjayksIG5ldyBTeXN0e1smKiZdfWVtLkRyYXdpbmcuUG9pbnQoNjAsIDIpKTsNCiAgICAgICAgICAgICAgICAgICAgVmlkZW8uU2NyZWVuLkJsaXQoZjEuUmVuZGVyKFwie1smKiZdfVZpdGU6IFwiICsgdml0ZS5Ub1N0cmluZygpLCBTeXN0ZW0uRHJhd2luZy5Db2xvci5CbGFjayksIG5ldyBTeXN0ZW0uRHJhd2luZy5Qe1smKiZdfW9pbnQoNDAwLCAyKSk7DQoNCgkgICAgIHN3aXRjaCAocG9zaXppb25lX2dpb2NhdG9yZSkNCiAgICAgICAgICAgICAgICAgICAgew17WyYqJl19CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMDoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBWaWRlby5TY3JlZW4uQntbJiomXX1saXQoZ2lvYzEsIHBvc2l6aW9uaV9naW9jYXRvcmVbcG9zaXppb25lX2dpb2NhdG9yZV0pOw0KICAgICAgICAgICAgICAgICAgICAge1smKiZdfSAgICAgICBicmVhazsNCg0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAxOg0KICAgICAgICAgICAgICAgICAgICAgICAgICB7WyYqJl19ICBWaWRlby5TY3JlZW4uQmxpdChnaW9jMiwgcG9zaXppb25pX2dpb2NhdG9yZVtwb3NpemlvbmVfZ2lvY2F0b3JlXSk7DQogICAgIHtbJiomXX0gICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI6DQogICAgICAgICAge1smKiZdfSAgICAgICAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5CbGl0KGdpb2MzLCBwb3NpemlvbmlfZ2lvY2F0b3JlW3Bvc2l6aW9uZV9naW97WyYqJl19Y2F0b3JlXSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgIH0NCg0KCSAgIHtbJiomXX0gICBWaWRlby5TY3JlZW4uQmxpdCh3aWZlLCBwb3NpemlvbmlfbW9nbGllW3Bvc2l6aW9uZV9tb2dsaWVdKTsNCiAgICAgICAgICAge1smKiZdfSAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgY2FzZSBTdGF0b1BhcnRpdGEuRmluZToNCiAgICAgICAgICAgICAgICB7WyYqJl19ICAgIFZpZGVvLlNjcmVlbi5CbGl0KGJhY2tnKTsNCiAgICAgICAgICAgICAgICAgICAgVmlkZW8uU2NyZWVuLkJsaXQoZjEuUmVuZHtbJiomXX1lcihcIlB1bnRlZ2dpbzogXCIgKyBwdW50ZWdnaW8uVG9TdHJpbmcoKSwgU3lzdGVtLkRyYXdpbmcuQ29sb3IuQmxhY2spLCBuZXcgU3l7WyYqJl19c3RlbS5EcmF3aW5nLlBvaW50KDYwLCAyKSk7DQogICAgICAgICAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5CbGl0KGYxLlJlbmRlcntbJiomXX0oXCJQYXJ0aXRhIFRlcm1pbmF0YSwgcHJlbWVyZSBJbnZpby4uLlwiLCBTeXN0ZW0uRHJhd2luZy5Db2xvci5CbGFjayksIG5ldyBTeXN7WyYqJl19dGVtLkRyYXdpbmcuUG9pbnQoNjAsIDE3KSk7DQogICAgICAgICAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5CbGl0KGYxLlJlbmRlcntbJiomXX0oXCJWaXRlOiAwXCIsIFN5c3RlbS5EcmF3aW5nLkNvbG9yLkJsYWNrKSwgbmV3IFN5c3RlbS5EcmF3aW5nLlBvaW50KDQwMCwgMikpOw17WyYqJl19CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICB9DQp9DQpcIjt7WyYqJl19[[/code]

L'istruzione evidenziata serve a disegnare la moglie nella posizione scelta dal sistema. Spieghiamola meglio:
La moglie può essere disegnata in tre posizioni differenti:

  1. alla finestra 1,
  2. alla finestra 2,
  3. alla finestra 3.

Queste tre posizioni sono identificabili come dei punti. Nel nostro caso, i punti sono:

  • x = 151 – y = 71;
  • x = 351 – y = 71;
  • x = 551 – y = 71;

Abbiamo quindi creato una lista di punti (List, precisamente ;) ): la lista “posizioni_moglie”. Ovviamente la moglie non può essere in tre luoghi contemporaneamente: la sua posizione attuale è regolata dalla variabile “posizione_moglie”, un intero che viene passato come indice della lista. Riguardate e capirete per bene:

Video.Screen.Blit(wife, posizioni_moglie[posizione_moglie]);

Con questa sola riga di codice disegneremo senza problemi la moglie.

  • Share/Bookmark

Disegnamo il Background. – Creazione di un gioco con SDL.NET

Un esempio di disegno già l’abbiamo visto nell’articolo precedente, con l’istruzione “Video.Screen.Blit(intro);”, disegnando appunto la schermata di intro del gioco. Le cose ovviamente non sono così semplici per quanto riguarda il disegno della schermata di gioco vero e proprio. Iniziamo quindi ad analizzare la funzione UpdatePartita(). Il codice completo sarà scaricabile a parte, qui invece inserirò solo le parti man mano necessarie.

Partiamo con:

[code]]czoxNTg2OlwiDQpwcml2YXRlIHZvaWQgVXBkYXRlUGFydGl0YSgpDQogICAgICAgIHsNCiAgICAgICAgICAgIHN3aXRjaCAoc3RhdG97WyYqJl19X3ApDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgY2FzZSBTdGF0b1BhcnRpdGEuUHJpbWE6DQogICAgICAgICAgICAgIHtbJiomXX0gICAgICBWaWRlby5TY3JlZW4uQmxpdChiYWNrZyk7DQogICAgICAgICAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5CbGl0KGYxLlJle1smKiZdfW5kZXIoXCJQdW50ZWdnaW86IDBcIiwgU3lzdGVtLkRyYXdpbmcuQ29sb3IuQmxhY2spLCBuZXcgU3lzdGVtLkRyYXdpbmcuUG9pbnQoNntbJiomXX0wLCAyKSk7DQogICAgICAgICAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5CbGl0KGYxLlJlbmRlcihcIlByZW1pIEludmlvIHBlciBpbntbJiomXX1pemlhcmUgbGEgcGFydGl0YS4uLlwiLCBTeXN0ZW0uRHJhd2luZy5Db2xvci5CbGFjayksIG5ldyBTeXN0ZW0uRHJhd2luZy5Qb2ludHtbJiomXX0oNjAsIDE3KSk7DQogICAgICAgICAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5CbGl0KGYxLlJlbmRlcihcIlZpdGU6IDBcIiwgU3lzdGV7WyYqJl19bS5EcmF3aW5nLkNvbG9yLkJsYWNrKSwgbmV3IFN5c3RlbS5EcmF3aW5nLlBvaW50KDQwMCwgMikpOw0KICAgICAgICAgICAgICAgIHtbJiomXX0gICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICBjYXNlIFN0YXRvUGFydGl0YS5JbkNvcnNvOg0KICAgICAgICAgICAgICAgICAge1smKiZdfSAgVmlkZW8uU2NyZWVuLkJsaXQoYmFja2cpOw0KICAgICAgICAgICAgICAgICAgICBWaWRlby5TY3JlZW4uQmxpdChmMS5SZW5kZXJ7WyYqJl19KFwiUHVudGVnZ2lvOiBcIiArIHB1bnRlZ2dpby5Ub1N0cmluZygpLCBTeXN0ZW0uRHJhd2luZy5Db2xvci5CbGFjayksIG5ldyBTeXN0e1smKiZdfWVtLkRyYXdpbmcuUG9pbnQoNjAsIDIpKTsNCiAgICAgICAgICAgICAgICAgICAgVmlkZW8uU2NyZWVuLkJsaXQoZjEuUmVuZGVyKFwie1smKiZdfVZpdGU6IFwiICsgdml0ZS5Ub1N0cmluZygpLCBTeXN0ZW0uRHJhd2luZy5Db2xvci5CbGFjayksIG5ldyBTeXN0ZW0uRHJhd2luZy5Qe1smKiZdfW9pbnQoNDAwLCAyKSk7DQogICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICAgICAgY2FzZSBTdGF0b1BhcnR7WyYqJl19aXRhLkZpbmU6DQogICAgICAgICAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5CbGl0KGJhY2tnKTsNCiAgICAgICAgICAgICAgICAgIHtbJiomXX0gIFZpZGVvLlNjcmVlbi5CbGl0KGYxLlJlbmRlcihcIlB1bnRlZ2dpbzogXCIgKyBwdW50ZWdnaW8uVG9TdHJpbmcoKSwgU3lzdGVtLkR7WyYqJl19cmF3aW5nLkNvbG9yLkJsYWNrKSwgbmV3IFN5c3RlbS5EcmF3aW5nLlBvaW50KDYwLCAyKSk7DQogICAgICAgICAgICAgICAgICAgIHtbJiomXX1WaWRlby5TY3JlZW4uQmxpdChmMS5SZW5kZXIoXCJQYXJ0aXRhIFRlcm1pbmF0YSwgcHJlbWVyZSBJbnZpby4uLlwiLCBTeXN0ZW0uRHJ7WyYqJl19YXdpbmcuQ29sb3IuQmxhY2spLCBuZXcgU3lzdGVtLkRyYXdpbmcuUG9pbnQoNjAsIDE3KSk7DQogICAgICAgICAgICAgICAgICAgIHtbJiomXX1WaWRlby5TY3JlZW4uQmxpdChmMS5SZW5kZXIoXCJWaXRlOiAwXCIsIFN5c3RlbS5EcmF3aW5nLkNvbG9yLkJsYWNrKSwgbmV3IFN5c3R7WyYqJl19ZW0uRHJhd2luZy5Qb2ludCg0MDAsIDIpKTsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICB9DQp9DQpcIjt7WyYqJl19[[/code]

Come potete vedere qui gestiamo ogni possibile caso per la variabile stato_p. Come ben sappiamo può assumere tre valori: Prima, InCorso (precedentemente detto Durante) e Fine. All'inizio, infatti, il gioco è fermo: dovremo premere invio per iniziare la nostra partita.

[code]]czo1MTA6XCINCmNhc2UgU3RhdG9QYXJ0aXRhLlByaW1hOg0KICAgICAgICAgICAgICAgICAgICBWaWRlby5TY3JlZW4uQmxpdChiYWN7WyYqJl19a2cpOw0KICAgICAgICAgICAgICAgICAgICBWaWRlby5TY3JlZW4uQmxpdChmMS5SZW5kZXIoXCJQdW50ZWdnaW86IDBcIiwgU3lzdGVte1smKiZdfS5EcmF3aW5nLkNvbG9yLkJsYWNrKSwgbmV3IFN5c3RlbS5EcmF3aW5nLlBvaW50KDYwLCAyKSk7DQogICAgICAgICAgICAgICAgICB7WyYqJl19ICBWaWRlby5TY3JlZW4uQmxpdChmMS5SZW5kZXIoXCJQcmVtaSBJbnZpbyBwZXIgaW5pemlhcmUgbGEgcGFydGl0YS4uLlwiLCBTeXN0e1smKiZdfWVtLkRyYXdpbmcuQ29sb3IuQmxhY2spLCBuZXcgU3lzdGVtLkRyYXdpbmcuUG9pbnQoNjAsIDE3KSk7DQogICAgICAgICAgICAgICB7WyYqJl19ICAgICBWaWRlby5TY3JlZW4uQmxpdChmMS5SZW5kZXIoXCJWaXRlOiAwXCIsIFN5c3RlbS5EcmF3aW5nLkNvbG9yLkJsYWNrKSwgbmV3e1smKiZdfSBTeXN0ZW0uRHJhd2luZy5Qb2ludCg0MDAsIDIpKTsNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQpcIjt7WyYqJl19[[/code]

Ecco cosa facciamo in ordine:

Disegnamo il nostro background, contenuto nella variabile backg;

  • Scriviamo a schermo il punteggio, uguale a zero. L'istruzione che usiamo è Video.Screen.Blit che prende come parametro la funzione Render dell'oggetto font f1 precendetemente istanziato.

Domanda: perchè queste funzioni annidate?
Risposta: Innanzitutto, tramite l'intellisense scorri le varie proprietà e metodi dell'oggetto f1. Scoprirai che Render() restituisce una Surface ;) Per questo motivo è tranquillamente disegnabile tramite Blit().

Con lo stesso metodo del punto precedente disegnamo una scritta per invitare il giocatore a premere invio.
In egual modo scriviamo a schermo il numero delle vite, attualmente pari a 0 in quanto il gioco non ancora inizia.

Dovrebbe essere di facile comprensione :) Ma andiamo avanti e leggiamo il codice scritto successivamente:

[code]]czozOTg6XCINCmNhc2UgU3RhdG9QYXJ0aXRhLkluQ29yc286DQogICAgICAgICAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5CbGl0KGJ7WyYqJl19YWNrZyk7DQogICAgICAgICAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5CbGl0KGYxLlJlbmRlcihcIlB1bnRlZ2dpbzogXCIgKyBwdW50e1smKiZdfWVnZ2lvLlRvU3RyaW5nKCksIFN5c3RlbS5EcmF3aW5nLkNvbG9yLkJsYWNrKSwgbmV3IFN5c3RlbS5EcmF3aW5nLlBvaW50KDYwLCB7WyYqJl19MikpOw0KICAgICAgICAgICAgICAgICAgICBWaWRlby5TY3JlZW4uQmxpdChmMS5SZW5kZXIoXCJWaXRlOiBcIiArIHZpdGUuVG9TdHJpe1smKiZdfW5nKCksIFN5c3RlbS5EcmF3aW5nLkNvbG9yLkJsYWNrKSwgbmV3IFN5c3RlbS5EcmF3aW5nLlBvaW50KDQwMCwgMikpOw0KICAgICB7WyYqJl19ICAgICAgICAgICAgICAgYnJlYWs7DQoNClwiO3tbJiomXX0=[[/code]

Dato che per adesso disegnamo solo il nostro background, la struttura del codice è simile al caso precedente. L'unica differenza è che non ci sarà, ovviamente, la scritta “Premi Invio per iniziare la partita...” e del punteggio e delle vite scriveremo il valore attuale, contenuto nelle variabili intere “punteggio” e “vite”.

Dopo aver spiegato questi due casi il codice del caso StatoPartita.Fine è di facilissima comprensione, per cui non mi dilungherò ulteriormente.

  • Share/Bookmark

Che struttura avrà il codice? – Creazione di un gioco con SDL.NET

Andando a scrivere il codice, dobbiamo ragionare sul modo in cui lo scriviamo. Come ho già spiegato precedentemente, il metodo che viene eseguito ad ogni frame è quello associato all’evento Tick. Inoltre, analizzando il file Template.Cs (file che ho usato come scheletro per il progetto) abbiamo visto due metodi private:

  • AddHandlers()
  • RemoveHandlers()

Questi due metodi, rispettivamente, aggiungono e rimuovono gli handlers al programma. La loro utilità è indubbia, specie in casi magari un pò più complicati di questo. Ecco il codice dei due metodi:

[code]]czo1Nzk6XCINCnByaXZhdGUgdm9pZCBBZGRIYW5kbGVycygpDQp7DQogICAgICAgICAgICBFdmVudHMuUXVpdCArPSBuZXcgRXZlbnR7WyYqJl19SGFuZGxlcjxRdWl0RXZlbnRBcmdzPih0aGlzLkV2ZW50c19RdWl0KTsNCiAgICAgICAgICAgIEV2ZW50cy5LZXlib2FyZERvd24gK3tbJiomXX09IG5ldyBFdmVudEhhbmRsZXI8S2V5Ym9hcmRFdmVudEFyZ3M+KEV2ZW50c19LZXlib2FyZERvd24pOw0KICAgICAgICAgICAgRXZle1smKiZdfW50cy5UaWNrICs9IG5ldyBFdmVudEhhbmRsZXI8VGlja0V2ZW50QXJncz4odGhpcy5FdmVudHNfVGljayk7DQp9DQoNCnByaXZhdGV7WyYqJl19IHZvaWQgUmVtb3ZlSGFuZGxlcnMoKQ0Kew0KICAgICAgICAgICAgRXZlbnRzLlF1aXQgLT0gbmV3IEV2ZW50SGFuZGxlcjxRdWl0RXtbJiomXX12ZW50QXJncz4odGhpcy5FdmVudHNfUXVpdCk7DQogICAgICAgICAgICBFdmVudHMuS2V5Ym9hcmREb3duIC09IG5ldyBFdmVudEhhe1smKiZdfW5kbGVyPEtleWJvYXJkRXZlbnRBcmdzPihFdmVudHNfS2V5Ym9hcmREb3duKTsNCiAgICAgICAgICAgIEV2ZW50cy5UaWNrIC09IG57WyYqJl19ZXcgRXZlbnRIYW5kbGVyPFRpY2tFdmVudEFyZ3M+KHRoaXMuRXZlbnRzX1RpY2spOw0KfQ0KXCI7e1smKiZdfQ==[[/code]

Pensate per esempio ad un insieme di menù o di schermate di gioco. Passando un parametro ad un ipotetico metodo di gestione degli handlers sarà possibile rimuoverli ed aggiungerli in base alle necessità, cosa decisamente ordinata.

Ma torniamo a noi, non complichiamoci la vita. Rimaniamo sul semplice. Come prima cosa analizziamo il costruttore della classe Template, quella principale.

[code]]czoxMTQ5OlwiDQpwdWJsaWMgVGVtcGxhdGUoKQ0KICAgICAgICB7DQogICAgICAgICAgICBwb3NpemlvbmlfZ2lvY2F0b3JlLkFkZCh7WyYqJl19bmV3IFN5c3RlbS5EcmF3aW5nLlBvaW50KDE1MCwgNDUwKSk7DQogICAgICAgICAgICBwb3NpemlvbmlfZ2lvY2F0b3JlLkFkZChuZXtbJiomXX13IFN5c3RlbS5EcmF3aW5nLlBvaW50KDM1MCwgNDUwKSk7DQogICAgICAgICAgICBwb3NpemlvbmlfZ2lvY2F0b3JlLkFkZChuZXcge1smKiZdfVN5c3RlbS5EcmF3aW5nLlBvaW50KDU1MCwgNDUwKSk7DQoNCiAgICAgICAgICAgIHBvc2l6aW9uaV9tb2dsaWUuQWRkKG5ldyBTeXN7WyYqJl19dGVtLkRyYXdpbmcuUG9pbnQoMTUxLCA3MSkpOw0KICAgICAgICAgICAgcG9zaXppb25pX21vZ2xpZS5BZGQobmV3IFN5c3RlbS5EcntbJiomXX1hd2luZy5Qb2ludCgzNTEsIDcxKSk7DQogICAgICAgICAgICBwb3NpemlvbmlfbW9nbGllLkFkZChuZXcgU3lzdGVtLkRyYXdpbmcue1smKiZdfVBvaW50KDU1MSwgNzEpKTsNCg0KICAgICAgICAgICAgcG9zaXppb25pX2ZpbmVzdHJhMS5BZGQobmV3IFN5c3RlbS5EcmF3aW5nLlB7WyYqJl19b2ludCgxNTEsIDE2MSkpOw0KICAgICAgICAgICAgcG9zaXppb25pX2ZpbmVzdHJhMS5BZGQobmV3IFN5c3RlbS5EcmF3aW5nLlBvaXtbJiomXX1udCgxNTEsIDI1NSkpOw0KICAgICAgICAgICAgcG9zaXppb25pX2ZpbmVzdHJhMS5BZGQobmV3IFN5c3RlbS5EcmF3aW5nLlBvaW50e1smKiZdfSgxNTEsIDM1MSkpOw0KDQogICAgICAgICAgICBwb3NpemlvbmlfZmluZXN0cmEyLkFkZChuZXcgU3lzdGVtLkRyYXdpbmcuUG9pbnR7WyYqJl19KDM1MSwgMTYxKSk7DQogICAgICAgICAgICBwb3NpemlvbmlfZmluZXN0cmEyLkFkZChuZXcgU3lzdGVtLkRyYXdpbmcuUG9pbnQoM3tbJiomXX01MSwgMjU1KSk7DQogICAgICAgICAgICBwb3NpemlvbmlfZmluZXN0cmEyLkFkZChuZXcgU3lzdGVtLkRyYXdpbmcuUG9pbnQoMzUxe1smKiZdfSwgMzUxKSk7DQoNCiAgICAgICAgICAgIHBvc2l6aW9uaV9maW5lc3RyYTMuQWRkKG5ldyBTeXN0ZW0uRHJhd2luZy5Qb2ludCg1NTF7WyYqJl19LCAxNjEpKTsNCiAgICAgICAgICAgIHBvc2l6aW9uaV9maW5lc3RyYTMuQWRkKG5ldyBTeXN0ZW0uRHJhd2luZy5Qb2ludCg1NTEsIHtbJiomXX0yNTUpKTsNCiAgICAgICAgICAgIHBvc2l6aW9uaV9maW5lc3RyYTMuQWRkKG5ldyBTeXN0ZW0uRHJhd2luZy5Qb2ludCg1NTEsIDM1e1smKiZdfTEpKTsNCiAgICAgICAgfQ0KXCI7e1smKiZdfQ==[[/code]

Che diamine vuol dire tutto questo compendio di numeri e punti? E' presto detto: vi ricordate quando vi ho spiegato che marito, moglie ed oggetti sarebbero stati sempre disegnati in punti ben precisi, proprio come i vecchi giochini?

Pensate agli insiemi. Per quanto riguarda "posizione_giocatore" stiamo aggiungendo alla lista tutte le posizioni possibili che egli può assumere durante il gioco. Ad intuito è facile capire che lo spostamento avviene solo sull'asse X e non su Y, che rimane fissa a 450. Idem per quanto riguarda la moglie, che si sposta da 151 a 551 ma rimanendo sempre ad Y = 71.

Il discorso inverso invece viene fatto per gli oggetti: come potete vedere la X rimane uguale per ogni finestra (la finestra 1 avrà un x pari a 151, la finestra 2 invece pari a 351 e.c.c). Se ci fate caso, ovviamente la x delle finestre è uguale a alle x della moglie: questo perchè disegneremo i nostri oggetti sotto la moglie, in quanto lanciati da lei.

Dopo aver assegnato i punti proseguiamo con lo studio del nostro codice: adesso soffermiamoci un minuto sul metodo Main:

[code]]czo5NTpcIg0KW1NUQVRocmVhZF0NCnB1YmxpYyBzdGF0aWMgdm9pZCBNYWluKCkNCnsNCglUZW1wbGF0ZSBnYW1lID0gbmV3IFRlbXB7WyYqJl19bGF0ZSgpOw0KCWdhbWUuR28oKTsNCn0NClwiO3tbJiomXX0=[[/code]

Questo metodo fa due cose, e anche molto semplici: crea un'istanza della classe Template (quella che stiamo scrivendo) ed avvia il metodo Go() di questa. Il “[STAThread]” prima del metodo specifica il modello di Threading da utilizzare. Il metodo Main in se, comunque, è molto importante perchè è il punto d'ingresso della nostra applicazione: tutto parte da qua.

Adesso passiamo a Go():

[code]]czozNzI6XCINCnB1YmxpYyB2b2lkIEdvKCkNCnsNCiAgICAgICAgICAgIFZpZGVvLldpbmRvd0NhcHRpb24gPSBcIkEgR2FtZSBBYm91e1smKiZdfXQgV2lmZVwncyBGdXJ5LlwiOw0KICAgICAgICAgICAgVmlkZW8uU2V0VmlkZW9Nb2RlKDgwMCwgNjAwKTsNCiAgICAgICAgICAgIEV2ZXtbJiomXX1udHMuRnBzID0gNjA7DQoNCiAgICAgICAgICAgIHNvdHRvZm9uZG8uVm9sdW1lID0gMTA7DQogICAgICAgICAgICBzMS5Wb2x1bWUge1smKiZdfT0gMTA7DQogICAgICAgICAgICBzMi5Wb2x1bWUgPSAxMDsNCg0KICAgICAgICAgICAgc290dG9mb25kby5QbGF5KHRydWUpOw0KICB7WyYqJl19ICAgICAgICAgIA0KICAgICAgICAgICAgdGhpcy5BZGRIYW5kbGVycygpOw0KICAgICAgICAgICAgRXZlbnRzLlJ1bigpOw0KfQ0KXCJ7WyYqJl19O3tbJiomXX0=[[/code]

Bene, qui troviamo un po di cosette da analizzare: innanzitutto parliamo delle prime due istruzioni, dedicate all'oggetto Video: nella prima impostiamo il valore della proprietà WindowCaption, ovvero il titolo. Fin qui dovrebbe essere tranquillo. Altrettanto tranquillo per la seconda istruzione: con SetVideoMode impostiamo la risoluzione ad 800 x 600, passando come parametro i due interi che ci interessano.

Ecco un'istruzione importantissima:

Events.Fps = 60;

Mi raccomando, è indispensabile che gli Fps siano impostati a 60, dato che in precedenza abbiamo fatto tutto il discorso sulle variabili frames e framelimit. Assegnando il valore 60 a questa proprietà faremo in modo che il sistema generi precisamente 60 frames al secondo, proprio quello di cui abbiamo bisogno.

Dopo ciò troviamo tre istruzioni dedicate al sonoro: in questo caso ho impostato a 10 il valore sia della musica di sottofondo che delle variabili s1 ed s2, quelle che mantengono le informazioni dei suoni del bip e del bip più basso, usato in caso di perdita di una vita.

Domanda forse lecita: se avevi problemi con il volume della musica e non hai utilizzato una variabile di tipo Music, perchè mai ora hai impostato tutto a 10 e bon?

Risposta: semplicemente perchè a mio parere mi sembrava tutto troppo alto e quindi fastidioso ;) una volta provata la seconda strada, ovvero l'usare Sound anziché Music, il livello del volume era accettabile :)

Andando avanti, incontriamo l'istruzione “sottofondo.Play(true);”. Qui abbiamo semplicemente detto al programma di avviare la riproduzione della musica, in quanto verrà utilizzata in tutto il gioco fino alla sua chiusura. Il “true” passato come parametro indica che il loop del suono sarà infinito. E' la nostra unica musica, quindi la useremo sempre e senza complicarci la vita.

Dopo aver impostato tutti questi “piccoli” aspetti, possiamo procedere all'esecuzione di due metodi molto importanti. Con AddHandlers() gestiremo tutti gli eventi e con Run() daremo il via al main loop del sistema. In questo preciso istante il gioco è partito.

Tra gli altri metodi degni di nota troviamo ResetGame():

[code]]czoxNjk6XCINCnByaXZhdGUgdm9pZCBSZXNldEdhbWUoKQ0KICAgICAgICB7DQogICAgICAgICAgICBwb3NpemlvbmVfZ2lvY2F0b3J7WyYqJl19ZSA9IDA7DQogICAgICAgICAgICB2aXRlID0gMzsNCiAgICAgICAgICAgIHB1bnRlZ2dpbyA9IDA7DQogICAgICAgICAgICBmcmFtZXtbJiomXX1saW1pdCA9IDYwOw0KICAgICAgICB9DQpcIjt7WyYqJl19[[/code]

questo codice, di facile comprensione, verrà eseguito ogni volta che l'utente vorrà iniziare una nuova partita, reimpostando i punti a 0 e le vite a 3.

  • Share/Bookmark

Raccogliamo le Idee – Creazione del primo gioco con SDL.NET

Prima ancora di sedersi al pc e scrivere a caso delle cose, è opportuno pensare bene a quello che si deve fare: come ogni cosa che riguarda la programmazione è sempre meglio concentrarsi su ogni minimo aspetto di ciò che si vuole andare a creare.

L’ispirazione per l’idea del gioco è arrivata per puro caso… una mattina riguardavo con nostalgia dei video musicali (dei muse mi pare) in formato 8-bit, come se i pezzi fossero suonati da una NES dei bei tempi che furono. Poi ho rivisto anche dei video dei cari vecchi Game & Watch, e lì mi si è accesa la lampadina.

La botta finale è arrivata quando ho visto un marito e una moglie litigare. Certo, quei due litigavano in piedi e uno di fronte all’altro, ma dovendola adattare nello stile dei vecchi Game & Watch ho pensato: e se la moglie gli buttasse degli oggetti dalla finestra?

Tutto è iniziato così, in realtà, nulla di eccezionale. Così, per un paio d’ore, mi sono messo a pensare e a ripensare se le cose potevano andare e filare nel modo giusto, cosa dovevo usare e cosa dovevo evitare. Ho anche pensato, ad un certo punto, di creare questo gioco in funzione di guide successive (ovvero queste pagine che state leggendo). E così è stato.

Ho immaginato un pò il funzionamento del gioco e, volendo descriverlo in poche righe, consiste in questo: c’è la moglie che butta degli oggetti, il marito li deve raccogliere. Ne butta uno al secondo e successivamente, man mano che il punteggio sale (ogni 300 punti) la frequenza della caduta degli oggetti aumenta. Non c’è una vera e propria fine del gioco, in quanto ad un certo punto si arriva ad una frequenza praticamente impossibile da sostenere per ognuno. Ah, certo, dimenticavo di dire che ogni oggetto raccolto vale 10 punti.

Poi ho iniziato ad immaginare i vari dettagli della scena, cercando però di non andare oltre i miei limiti: purtroppo le mie doti di disegnatore sono praticamente inesistenti, per cui il massimo a cui potevo puntare era qualche vettore in photoshop. Inizialmente, per fare le prime prove, avevo concepito qualche schifezza veramente di base, in bianco e nero ed orrendo da vedere.

the-palace

Abbastanza una schifezza, vero? :)

Dopo ciò allora ho riflettuto un po su cosa potevo usare e ho cercato in giro su internet qualcosa di valido. La risposta è arrivata, almeno per il background, quando ho trovato su Vecteezy (http://www.vecteezy.com/) un set di immagini vettoriali dedicate al Game Boy Color. Ho così rimosso dei dettagli per fare spazio a quella che sarebbe stata la scena di gioco successiva. E così, ecco qui qualcosa di fattibile (perlomeno, rispetto alla grafica precedente).

GB

Qui di seguito, invece, trovate le varie grafiche che ho realizzato (o utilizzato) per il marito, la moglie ed i vari oggetti in caduta libera. Come potete vedere sono delle cose veramente elementari, realizzate in photoshop.

gioc1 wifegioc2

Ok, abbiamo dato un occhiata basilare alla grafica. Cosa dobbiamo ancora vedere? Beh, senza dubbio l’input e l’audio! Partiamo proprio da quest’ultimo. L’audio è molto importante ed in questo caso dovevo risolvere due quesiti fondamentali:

  1. Che musica usare?
  2. Per l’audio, devo utilizzare le librerie SDL.NET oppure puntare a qualcosa di esterno?

Per scegliere la musica una mezza idea già ce l’avevo. Avevo pensato a qualcosa dalla sonorità old e retrò, con quell’effetto 8-Bit tipico delle vecchie console. Un esempio? Lo potete ascoltare sul canale di Florio003 (http://www.youtube.com/user/Florio003). Ho cercato un pò, volendo una musica che si adattasse al contesto, ed ecco che ho trovato quello che cercavo. The Entertainer, vecchia leggenda di Scott Joplin, reperibile qui http://www.youtube.com/watch?v=NF7dasQtVXM.

La musica è decisa. Sarà l’unico pezzo musicale dato che il gioco non è un granchè complicato. Ed ora il secondo quesito, puramente tecnico ed influente a livello di realizzazione. Qualche tempo fa, realizzando un altro giochillo con XNA, avevo usato IrrKlang, una libreria audio con il supporto per gli mp3. Non volendo complicare le cose anche stavolta, però, ho scelto una strada diversa:

Anzichè usare gli mp3 come si fa in genere, infatti, ho convertito la canzone in file .ogg, tranquillamente leggibile dato che SDL.NET supporta Ogg Vorbis.

Infine l’input. Il giocatore si muoverà con il solo ausilio delle frecce direzionali destra e sinistra, usando Esc per uscire dal gioco e Invio (Return) per iniziarlo. Facile e veloce. Come potete vedere, stiamo iniziando a delineare qualcosa, ma i dettagli di quello che uscirà alla fine sono molto sfocati.

Nel prossimo articolo daremo una forma a tutto, mettendo su carta le idee e scrivendo gli appunti.

  • Share/Bookmark