Posts tagged programmare giochi

Definiamo le nostre variabili. – Creazione di un gioco con SDL.NET

Per la prima volta in questa guida iniziamo a vedere un pò di codice. Era pure ora. Per prima cosa apriamo il nostro ambiente di sviluppo e, se usiamo il caro Visual C# Express, possiamo anche utilizzare il comodo template di progetto che ho caricato sul sito qualche giorno fa.

Con la nostra finestra aperta e il sistema pronto, possiamo iniziare ad aggiungere queste righe di codice appena dopo l’inizio della classe principale, ovvero:

[code]]czoyMjU6XCINCnVzaW5nIFN5c3RlbTsNCnVzaW5nIFN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljOw0KDQp1c2luZyBTZGxEb3ROZXR7WyYqJl19LkNvcmU7DQp1c2luZyBTZGxEb3ROZXQuR3JhcGhpY3M7DQp1c2luZyBTZGxEb3ROZXQuSW5wdXQ7DQp1c2luZyBTZGxEb3ROZXQuQXtbJiomXX11ZGlvOw0KDQpuYW1lc3BhY2UgQUdBV0YNCnsNCiAgICBwdWJsaWMgY2xhc3MgVGVtcGxhdGUNCiAgICB7DQoJU0NSSVZJQU1PIFFVe1smKiZdfUkhDQpcIjt7WyYqJl19[[/code]

Ecco le nostre prime istruzioni:

GameState stato = GameState.Intro;

StatoPartita stato_p = StatoPartita.Prima;

Surface intro = new Surface("immagini/intro.jpg");

Surface backg = new Surface("immagini/back.jpg");

Surface gioc1 = new Surface("immagini/gioc1.png");

Surface gioc2 = new Surface("immagini/gioc2.png");

Surface gioc3 = new Surface("immagini/gioc3.png");

Surface wife = new Surface("immagini/wife.png");

Sound sottofondo = new Sound("musica/music1.ogg");

Sound s1 = new Sound("suoni/s1.wav");

Sound s2 = new Sound("suoni/s2.wav");

int frames = 0;

int framelimit = 60;

Font f1 = new Font("fonts/font1.ttf", 12);

int vite, punteggio;

List<System.Drawing.Point> posizioni_giocatore = new List<System.Drawing.Point>();

int posizione_giocatore = 0;

List<System.Drawing.Point> posizioni_moglie = new List<System.Drawing.Point>();

int posizione_moglie = 0;

List<System.Drawing.Point> posizioni_finestra1 = new List<System.Drawing.Point>();

List<System.Drawing.Point> posizioni_finestra2 = new List<System.Drawing.Point>();

List<System.Drawing.Point> posizioni_finestra3 = new List<System.Drawing.Point>();

List<OggettoCadente> oggetti = new List<OggettoCadente>();

Random r1 = new Random();

Non vi preoccupate se non capite qualcosa! Piano piano analizzeremo riga per riga e vedremo a cosa serve. Iniziamo dalle prime due: abbiamo le variabili stato e stato_p, che come specificato precedentemente serviranno a visualizzare e ad impostare lo stato attuale del gioco e della partita. Le due variabili sono di tipo GameState e StatoPartita: dopo questo articolo daremo un occhiata per bene all'utilità di queste enumerazioni.

Dopodichè abbiamo le seguenti istruzioni:

Surface intro = new Surface("immagini/intro.jpg");

Surface backg = new Surface("immagini/back.jpg");

Surface gioc1 = new Surface("immagini/gioc1.png");

Surface gioc2 = new Surface("immagini/gioc2.png");

Surface gioc3 = new Surface("immagini/gioc3.png");

Surface wife = new Surface("immagini/wife.png");


In questo blocco ho messo tutte le immagini che mi potevano servire per il gioco. La prima, intro, si collega ad intro.jpg nella cartella immagini. Lo stesso ragionamento vale per le altre ed in questo modo abbiamo in memoria tutti i files grafici che ci servono. Due parole vanno spese per le variabili gioc1, gioc2, gioc3. In realtà avrei potuto usare altri metodi per gestire il giocatore. Magari usare una sola variabile e ad ogni spostamento caricare il file corrispondente. Stavolta, però, ho voluto “sprecare” spazio ed utilizzare tre variabili distinte.

Si noti inoltre che a volte (non in questo caso ovviamente) caricare un memoria un file grafico può essere pesante. Non tutti i files grafici dei giochi, infatti, sono leggeri come questi!

Ora dobbiamo caricare in memoria i suoni: ecco le istruzioni che ci servono per rendere ciò possibile:

Sound sottofondo = new Sound("musica/music1.ogg");

Sound s1 = new Sound("suoni/s1.wav");

Sound s2 = new Sound("suoni/s2.wav");

In sottofondo abbiamo messo la musichetta di sottofondo e in s1 ed s2 i due effetti sonori, il bip e il bip del personaggio che perde una vita. Può sorgere spontanea una domanda: perchè, se esiste la classe Music, ho messo un file musicale come Sound? Semplicemente perchè possiamo deciderne il volume.

Nelle prime prove, infatti, avevo usato la classe Music, ma ben presto mi ero accorto che il volume della musica sovrastava il suono del bip di troppo e diventava quasi fastidioso. Usando invece la classe Sound potevo gestire il volume a mio piacimento. A domanda risposta :)

int frames = 0;

int framelimit = 60;


Queste due variabili di tipo Int sono il cuore del “timer” che avevo anticipato negli appunti. La variabile “frames” provvederà a contare il numero di frames passati e “framelimit”, come suggerisce il nome, rappresenta il valore numerico che la variabile “frames” deve raggiungere. A quel punto scateneremo gli eventi rispettivi.

Ma di questo parleremo più avanti: per adesso vediamo il codice delle definizioni delle variabili.

Per questo c'è bisogno di poche presentazioni:

Font f1 = new Font("fonts/font1.ttf", 12);


Abbiamo già visto nella guida base che questa è una semplice istruzione per caricare in memoria un Font chiamato f1, situato nella cartella fonts. La grandezza del carattere è specificata nel secondo parametro del costruttore (nel nostro caso 12).

Le variabili:

int vite, punteggio;

sono, rispettivamente, il numero delle vite del personaggio (che avranno un valore possibile da 3 a 0) e il punteggio del giocatore.

List<System.Drawing.Point> posizioni_giocatore = new List<System.Drawing.Point>();

int posizione_giocatore = 0;

Come detto in fase di “appunti” i personaggi che disegneremo verranno disegnati su punti dalle coordinate ben precise. A questo serve la nostra List “posizioni_giocatore”. In questo modo potremo memorizzare le coordinate che ci servono e, usando una variabile indice (guarda caso l'intero “posizione_giocatore”) disegneremo di volta in volta il giocatore in base alla sua posizione.

Stesso discorso, ovviamente, vale per la moglie: anche in questo caso infatti abbiamo dichiarato le variabili

List<System.Drawing.Point> posizioni_moglie = new List<System.Drawing.Point>();

int posizione_moglie = 0;

La prima consentirà di specificare tutte le posizioni della moglie (ambigua questa) mentre la seconda ci permetterà di volta in volta di disegnare in modo preciso la Surface. Il come tutto ciò avviene ve lo spiegherò dopo: guardate innanzitutto per bene il tipo di variabili che utilizziamo.

Abbiamo ancora alcuni punti da definire, e per questo motivo definiamo altre tre liste che ci accompagneranno nello sviluppo del gioco:

List<System.Drawing.Point> posizioni_finestra1 = new List<System.Drawing.Point>();

List<System.Drawing.Point> posizioni_finestra2 = new List<System.Drawing.Point>();

List<System.Drawing.Point> posizioni_finestra3 = new List<System.Drawing.Point>();

queste variabili servono a definire tutte le possibili posizioni che ogni oggetto cadente potrà assumere nel gioco. “posizioni_finestra1”, per esempio, servirà a specificare tutti i possibili punti che verranno utilizzati per disegnare un oggetto in caduta sotto la finestra numero uno (quella più a sinistra, per intenderci). Lo stesso discorso ovviamente vale per le altre finestre.

Infine, dobbiamo pure mettere da qualche parte i nostri oggetti. Ecco quindi che in soccorso arriva un'altra lista:

List<OggettoCadente> oggetti = new List<OggettoCadente>();

Come potete vedere in questo caso non abbiamo un tipo già definito di oggetto, in questa lista. Per l'oggetto che cade, infatti, avevamo deciso di utilizzare una classe a parte, chiamata OggettoCadente. Avevamo dato un occhiata ad una struttura generica di come poteva essere, ora vi mostro il codice per intero.

[code]]czo0NTk6XCINCnVzaW5nIFN5c3RlbTsNCnVzaW5nIFN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljOw0KDQp1c2luZyBTZGxEb3ROZXR7WyYqJl19LkNvcmU7DQp1c2luZyBTZGxEb3ROZXQuR3JhcGhpY3M7DQoNCm5hbWVzcGFjZSBBR0FXRg0Kew0KICAgIGNsYXNzIE9nZ2V0dG9DYXtbJiomXX1kZW50ZQ0KICAgIHsNCiAgICAgICAgcHVibGljIFN1cmZhY2UgQ2FudmFzOw0KDQogICAgICAgIHB1YmxpYyBpbnQgcG9zaXppb25le1smKiZdfTsNCiAgICAgICAgcHVibGljIGludCBmaW5lc3RyYTsNCg0KICAgICAgICBwdWJsaWMgT2dnZXR0b0NhZGVudGUoaW50IGYsaW50IHR7WyYqJl19KQ0KICAgICAgICB7DQogICAgICAgICAgICBDYW52YXMgPSBuZXcgU3VyZmFjZShcImltbWFnaW5pL1wiICsgdC5Ub1N0cmluZygpICsge1smKiZdfVwiLnBuZ1wiKTsNCiAgICAgICAgICAgIHBvc2l6aW9uZSA9IDA7DQogICAgICAgICAgICBmaW5lc3RyYSA9IGY7DQogICAgICAgIH0NCntbJiomXX0gICAgfQ0KfQ0KXCI7e1smKiZdfQ==[[/code]

Com'è facile notare non c'è molto di complicato, in realtà. Ogni istanza di questa classe avrà una propria Surface (che sarà quello che disegneremo), una finestra (in questo modo sapremo sotto quale finestra dovremo disegnare l'oggetto) e la posizione (in modo tale da gestire la caduta).

Il metodo costruttore, infine, che prende come parametri sia il tipo che il numero della finestra, esegue poche e semplici operazioni: carica in memoria il file corrispondente partendo dal tipo, assegna il valore 0 alla variabile posizione (l'oggetto sempre dall'alto dovrà partire) ed infine il numero della finestra.

Nota: il codice di OggettoCadente si trova in un file a parte, OggettoCadente.cs.

Infine, ecco l'ultima variabile che ci si presenta:

Random r1 = new Random();

Come ben sappiamo, la finestra da cui ogni oggetto dovrà cadere sarà decisa a caso di volta in volta. Per questo motivo ci è molto utile (per non dire indispensabile) una variabile di tipo Random.

Detto questo abbiamo terminato il nostro discorso sulle variabili. Come abbiamo visto, alcune volte potevamo fare delle ottimizzazioni: non c'è bisogno che vi dica di effettuare sempre scelte oculate in termini di variabili.

Certo, in un caso come questo una variabile in più o in meno non fa mai tutta questa differenza. Ma pensate ad un grande progetto, in cui centinaia e centiniaia di variabili vengono cambiate ogni millisecondo. Lì bisogna stare attentissimi a ciò che si fa.

Con ciò vi saluto e... al prossimo articolo!

  • Share/Bookmark

Appunti e Controappunti – Creazione di un gioco con SDL.NET

Il tempo di pensare è finito… abbiamo un’idea vaga di quello che vogliamo fare, abbiamo pensato un po a qualche particolare. Nulla di sicuro però. Questo vuol dire che è tempo di mettere tutto per iscritto o perlomeno iniziare a capire l’importanza degli appunti!

Iniziamo, allora, a stilare un elenco di aspetti del nostro gioco.

  • Il gioco parla di una moglie incazzata che lancia degli oggetti al marito. Il marito deve raccoglierli e questo permette di guadagnare 10 punti per ogni oggetto raccolto.
  • Gli oggetti che cadono seguono il percorso di una griglia 3×3. Nel disegno a seguire è spiegato tutto meglio.

Senza titolo-25555555

Come potete vedere in quest’immagine, l’area in cui gli oggetti cadranno sarà la sopracitata griglia 3×3. Dove leggete il testo “finestra 1″, “finestra 2″, “finestra 3″ c’è l’indicazione per la finestra rispettiva.

La moglie infatti getterà, ogni secondo, un oggetto da una a caso di queste finestre. Il giocatore starà invece sotto la griglia, dove dovrà prenderla. Da questo sappiamo per certo che:

  1. La moglie potrà assumere tre posizioni (finestra 1, 2 o 3)
  2. Il giocatore potrà spostarsi in tre posizioni (sotto la finestra 1, 2 o 3)

E’ scontato ma lo dico per maggiore comprensione: l’oggetto fulmine si trova sotto la finestra tre, in prima posizione (partiremo dall’alto). Per comodità diremo (3,1). La forbice si trova in (2,2).

Ma torniamo ai nostri punti.

  • Gli oggetti cadranno ad intervalli regolari, la cui durata però inizierà pian piano a diminuire. In questo modo si può aumentare la difficoltà del gioco con il raggiungimento di un numero maggiore di punti. Questo evita anche che il gioco sia tremendamente piatto.

Nello specifico, gli oggetti inizieranno a cadere con un intervallo di un secondo. Ogni secondo la moglie si affaccerà da una delle tre finestre e lancerà l’oggetto. Come si può fare ad aumentare la velocità degli oggetti in caduta?

Io ho usato il seguente metodo, che penso possa essere sicuramente affinato.

Innanzitutto, si deve pensare che il gioco ha un’ammontare di Frames per Secondo. Do per scontato che sappiate cosa sono, per cui vi dico subito che è possibile gestire questo aspetto tramite la variabile Events.Fps. Per cui, per prima cosa, le assegneremo il valore 60.

Successivamente, useremo due altre variabili:

  • frames
  • framelimit

“frames” verrà usato come contatore del frame attuale in cui ci si trova, mentre “framelimit” sarà il limite dell’intervallo di cui ho parlato sopra.

Ora facciamo un esempio pratico, non scriverò codice ma comunque in un modo comprensibile.

  • “frames” è inizialmente settata a 0;
  • “framelimit” è inizialmente settata a 60;
  1. Se frames < framelimit
  2. frames = frames + 1;
  3. altrimenti
  4. (qui viene creato un nuovo oggetto da far cadere e viene scelta una nuova posizione per la moglie);
  5. frames = 0;

Dopodichè controlliamo il punteggio: ogni volta che avanzeremo di 300 punti (quindi 300, 600, 900 e così via) diminuiremo di un tot il framelimit (nel mio esempio è 5). Quindi, a 300 punti avremo un framelimit di 55, a 600 di 50 e così via.

Spero di essere stato chiaro. Torniamo ai punti:

  • Il giocatore non giocherà in eterno, ma avrà 3 vite. Una vita viene persa quando non riesce a prendere un oggetto e quando le vite saranno pari a 0 il gioco terminerà.
  • All’inizio, inoltre, mostreremo una piccola schermata che precederà il gioco vero e proprio, illustrando la trama e gli obiettivi.

Ciò ci porta a spendere due parole sulle varie situazioni di gioco. Appena avvieremo il gioco, infatti, non avremo subito a che fare con la moglie incazzata. Ci verrà mostrata la schermata delle istruzioni finchè non premeremo Invio. Dopodichè verremo portati nella scena di gioco: adesso dovremo premere ancora invio per iniziare e solo allora giocheremo veramente. Una sorta di schermata in cui si dice “press start to play”… dovreste averla presente ;)
Per questo motivo ho suddiviso in “stati” le varie situazioni di gioco. Inoltre, ho voluto identificare in modo distinto gli stati del gioco e gli stati della partita (dato che possiamo avere più partite prima che l’utente si scocci ed esca):

Stati del Gioco:

  1. Schermata Iniziale
  2. Schermata di Gioco
  3. Uscita dal Gioco

Stati della Partita:

  1. Prima
  2. Durante
  3. Fine

Passeremo da uno stato all’altro seguendo delle condizioni ben determinate. Eccole qui di seguito.

  • Schermata Iniziale:
  1. Premendo Invio andremo in “Schermata di Gioco”
  2. Premendo Esc andremo in “Uscita dal Gioco”
  • Schermata di Gioco: (qui iniziamo a gestire i vari stati della partita)
  • Stati della Partita:

    Prima:

    • Premendo Esc andremo in “Uscita dal Gioco”
    • Premendo Invio andremo in “Durante”

    Durante:

    • Premendo le Frecce Direzionali muoviamo il personaggio
    • Premendo Esc andremo in “Prima”
    • Finendo le vite del personaggio andremo in “Fine”

    Fine:

    • Premendo Esc andremo in “Uscita dal Gioco”
    • Premendo Invio andremo in “Prima”

    Tranne per quello che riguarda lo stato “Durante” della Partita, potete vedere che tutti i passaggi di stato sono causati dall’input dell’utente.

    Ora che abbiamo tutto pronto e chiaro in mente, possiamo iniziare a guardare il lato del codice vero e proprio… è tempo di sedersi al pc!

    • 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

    Introduzione – Creazione del primo gioco con SDL.NET

    Qualche giorno fa ho finito di pubblicare la guida base per l’SDL.NET sul mio blog personale. In questa guida ho trattato tutti gli aspetti base di questa libreria, decisamente utile e veloce da gestire. Unita ad un linguaggio come il C#, poi, la prototipizzazione di un qualcosa di tangibile è praticamente immediata.

    Nella pagine che seguiranno, invece, ripercorrerò l’iter che ho percorso per creare quello che potrebbe definirsi “un primo esperimento” con questa libreria. Il “gioco” in questione si chiama A Game About Wife’s Fury.

    Protagonista del gioco è un marito condannato da una moglie arrabbiata, che deve prendere al volo tutti gli oggetti che questa gli lancerà dalla finestra di casa. Per rendere il tutto più difficile man mano che si va avanti, il gioco andrà più veloce e sarà difficile prendere tutti gli oggetti.

    Dopo questa breve infarinatura vi saluto e vi lascio allo “studio”, sperando che sia comprensibile e senza troppi problemi di comprensione :)

    P.S: come al solito le mie non sono le parole di un esperto, bensì di uno studente autodidatta :) per cui il codice che vedrete sicuramente non sarà il top del top. Per alcuni però potrà essere utile per comprendere alcuni concetti.

    Buona Lettura!

    • Share/Bookmark