Posts tagged input
Gestiamo l’Input. – Creazione di un gioco con SDL.NET
dic 5
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.
Input – Mouse e Tastiera – Guida SDL.NET
nov 21
Ora cambiamo un po argomento. Abbiamo visto tutto (o quasi) ciò che poteva riguardare l’output: abbiamo imparato a caricare un immagine sullo schermo, come renderla trasparente, come caricare un font e scriverci qualcosa ed anche aprire un file audio per usare un effetto sonoro nei nostri programmi.
Sapete bene però che un gioco non è solo Output. Un gioco è interazione, un gioco è anche Input. Per cui, adesso inizieremo a guardare le varie alternative che ci vengono proposte per gestire al meglio il modo in cui l’utente interagisce con il nostro gioco. Vi ricordate il sistema degli eventi, che avevo descritto ed introdotto qualche tempo fa? Inizieremo proprio da lì.
Riprendiamo l’esempio dell’Hello World, apportando però qualche modifica al codice:
[code]]czo3OTg6XCINCnVzaW5nIFN5c3RlbTsNCg0KdXNpbmcgU2RsRG90TmV0LkNvcmU7DQp1c2luZyBTZGxEb3ROZXQuR3JhcGhpY3M7DQp7WyYqJl19DQpuYW1lc3BhY2UgU2RsRG90TmV0RXhhbXBsZXMuU21hbGxEZW1vcw0Kew0KICAgIHB1YmxpYyBjbGFzcyBIZWxsb1dvcmxkDQogIHtbJiomXX0gIHsNCiAgICAgICAgW1NUQVRocmVhZF0NCiAgICAgICAgcHVibGljIHN0YXRpYyB2b2lkIE1haW4oKQ0KICAgICAgICB7DQogICAge1smKiZdfSAgICAgICAgSGVsbG9Xb3JsZCBhcHAgPSBuZXcgSGVsbG9Xb3JsZCgpOw0KICAgICAgICAgICAgYXBwLkdvKCk7DQogICAgICAgIH17WyYqJl19DQoNCiAgICAgICAgcHVibGljIEhlbGxvV29ybGQoKQ0KICAgICAgICB7DQogICAgICAgICAgICBWaWRlby5TZXRWaWRlb01vZGUoNHtbJiomXX0wMCwgMzAwKTsNCiAgICAgICAgICAgIFZpZGVvLldpbmRvd0NhcHRpb24gPSBcIkhlbGxvIFdvcmxkIVwiOw0KICAgICAgICB9DQoNCiB7WyYqJl19ICAgICAgIHB1YmxpYyB2b2lkIEdvKCkNCiAgICAgICAgew0KICAgICAgICAgICAgRXZlbnRzLktleWJvYXJkRG93biArPSBuZXcgRXtbJiomXX12ZW50SGFuZGxlcihFdmVudHNfS2V5Ym9hcmREb3duKTsNCiAgICAgICAgICAgIEV2ZW50cy5SdW4oKTsNCiAgICAgICAgfQ0KDQoge1smKiZdfSAgICAgICB2b2lkIEV2ZW50c19LZXlib2FyZERvd24ob2JqZWN0IHNlbmRlciwgU2RsRG90TmV0LklucHV0LktleWJvYXJkRXZlbnR7WyYqJl19QXJncyBlKQ0KICAgICAgICB7DQogICAgICAgICAgICBpZiAoZS5LZXkgPT0gU2RsRG90TmV0LklucHV0LktleS5Fc2NhcGUpIEV2ZXtbJiomXX1udHMuUXVpdEFwcGxpY2F0aW9uKCk7DQogICAgICAgIH0NCiAgICB9DQp9DQpcIjt7WyYqJl19[[/code]
Dunque, cosa abbiamo di diverso? Sicuramente l'istruzione
Events.KeyboardDown += new EventHandler<SdlDotNet.Input.KeyboardEventArgs>(Events_KeyboardDown);
E... cosa vorrebbe dire?
Semplicemente, che abbiamo gestito l'evento che si verificherà alla pressione di un tasto sulla nostra tastiera.
Ehm... cioè?
Spieghiamoci meglio: ogni volta che il nostro giocatore premerà un pulsante sulla tastiera, verrà eseguito il metodo Events_KeyboardDown. Ecco quindi che troviamo il codice del metodo:
void Events_KeyboardDown(object sender, SdlDotNet.Input.KeyboardEventArgs e)
{
if (e.Key == SdlDotNet.Input.Key.Escape) Events.QuitApplication();
}
Come parametri in ingresso passeremo un oggetto sender e un KeyboardEventArgs chiamato “e”. Soprattutto questo sarà importantissimo, come vedremo tra poco. Ed infatti ecco l'istruzione chiave che spiega questo nuovo concetto:
if (e.Key == SdlDotNet.Input.Key.Escape) Events.QuitApplication();
Non è molto difficile da capire: in poche parole qui si dice al nostro caro programma che ogni volta che l'utente premerà il tasto Escape (ESC) il programma dovrà terminare, tramite la chiamata al metodo QuitApplication, già menzionato precedentemente.
Avviando il nostro programma di prova premendo F5, potremo subito verificare i risultati. Premendo Esc, infatti, l'applicazione terminerà facendoci tornare alla schermata del nostro IDE (ho scritto F5 perchè do per scontato l'uso del Visual C# Express, che agevola di molto le cose).
L'oggetto "e" che passiamo, inoltre, offre svariate possibilità grazie alle sue proprietà: la booleana Down, che restituisce true se un tasto è stato premuto. Oppure ancora Unicode ed UnicodeCharacter, che forniscono informazioni sul carattere Unicode rappresentato dal tasto appena premuto. Ciò, quindi, lascia spazio per un buon numero di possibilità e personalizzazioni.
Passiamo ora a dare un occhiata al Mouse: anche in questo caso abbiamo un buon numero di eventi da gestire e metodi pronti da usare per facilitare il nostro lavoro. Un esempio pratico è rappresentato dal codice di seguito.
[code]]czoxNjg0OlwiDQp1c2luZyBTeXN0ZW07DQoNCnVzaW5nIFNkbERvdE5ldC5Db3JlOw0KdXNpbmcgU2RsRG90TmV0LkdyYXBoaWNzOw17WyYqJl19Cg0KbmFtZXNwYWNlIFNkbERvdE5ldEV4YW1wbGVzLlNtYWxsRGVtb3MNCnsNCnB1YmxpYyBjbGFzcyBIZWxsb1dvcmxkDQp7DQpGb3tbJiomXX1udCBmMSA9IG5ldyBGb250KFwiQ2FsaWJyaS50dGZcIiwgMTIpOw0KDQp1c2luZyBTeXN0ZW07DQoNCnVzaW5nIFNkbERvdE5ldC5Db3J7WyYqJl19ZTsNCnVzaW5nIFNkbERvdE5ldC5HcmFwaGljczsNCg0KbmFtZXNwYWNlIFNkbERvdE5ldEV4YW1wbGVzLlNtYWxsRGVtb3MNCnsNCntbJiomXX0gICAgcHVibGljIGNsYXNzIEhlbGxvV29ybGQNCiAgICB7DQogICAgICAgIEZvbnQgZjEgPSBuZXcgRm9udChcIkNhbGlicmkudHRmXCJ7WyYqJl19LCAxMik7DQoNCiAgICAgICAgc3RyaW5nIHBvc2l6aW9uZSA9IFwiXCI7DQoNCiAgICAgICAgW1NUQVRocmVhZF0NCiAgICAgICAgcHVie1smKiZdfWxpYyBzdGF0aWMgdm9pZCBNYWluKCkNCiAgICAgICAgew0KICAgICAgICAgICAgSGVsbG9Xb3JsZCBhcHAgPSBuZXcgSGVsbG9Xb3J7WyYqJl19bGQoKTsNCiAgICAgICAgICAgIGFwcC5HbygpOw0KICAgICAgICB9DQoNCiAgICAgICAgcHVibGljIEhlbGxvV29ybGQoKQ0KICAgIHtbJiomXX0gICAgew0KICAgICAgICAgICAgVmlkZW8uU2V0VmlkZW9Nb2RlKDQwMCwgMzAwKTsNCiAgICAgICAgICAgIFZpZGVvLldpbmRvd0Nhe1smKiZdfXB0aW9uID0gXCJIZWxsbyBXb3JsZCFcIjsNCiAgICAgICAgfQ0KICAgICAgICBwdWJsaWMgdm9pZCBHbygpDQogICAgICAgIHsNCiAgIHtbJiomXX0gICAgICAgICBFdmVudHMuS2V5Ym9hcmREb3duICs9IG5ldyBFdmVudEhhbmRsZXIoRXZlbnRzX0tleWJvYXJkRG93bik7DQogICAge1smKiZdfSAgICAgICAgRXZlbnRzLk1vdXNlTW90aW9uICs9IG5ldyBFdmVudEhhbmRsZXIoRXZlbnRzX01vdXNlTW90aW9uKTsNCiAgICAgICB7WyYqJl19ICAgICBFdmVudHMuVGljayArPSBuZXcgRXZlbnRIYW5kbGVyKEV2ZW50c19UaWNrKTsNCiAgICAgICAgICAgIEV2ZW50cy5SdW4oKXtbJiomXX07DQogICAgICAgIH0NCg0KICAgICAgICB2b2lkIEV2ZW50c19UaWNrKG9iamVjdCBzZW5kZXIsIFRpY2tFdmVudEFyZ3MgZSkNCiAge1smKiZdfSAgICAgIHsNCiAgICAgICAgICAgIFZpZGVvLlNjcmVlbi5GaWxsKFN5c3RlbS5EcmF3aW5nLkNvbG9yLkJsYWNrKTsNCiAgICAgICB7WyYqJl19ICAgICBWaWRlby5TY3JlZW4uQmxpdChmMS5SZW5kZXIocG9zaXppb25lLCBTeXN0ZW0uRHJhd2luZy5Db2xvci5XaGl0ZSksIG5ld3tbJiomXX0gU3lzdGVtLkRyYXdpbmcuUG9pbnQoMjAsIDIwKSk7DQogICAgICAgICAgICBWaWRlby5TY3JlZW4uVXBkYXRlKCk7DQogICAgICAge1smKiZdfSB9DQoNCiAgICAgICAgdm9pZCBFdmVudHNfTW91c2VNb3Rpb24ob2JqZWN0IHNlbmRlciwgU2RsRG90TmV0LklucHV0Lk1vdXNlTW97WyYqJl19dGlvbkV2ZW50QXJncyBlKQ0KICAgICAgICB7DQogICAgICAgICAgICBwb3NpemlvbmUgPSBcIk1vdXNlIC0gWDogXCIgKyBlLlkuVG9Te1smKiZdfXRyaW5nKCkgKyBcIiwgWTogXCIgKyBlLlguVG9TdHJpbmcoKTsNCiAgICAgICAgfQ0KDQogICAgICAgIHZvaWQgRXZlbnRzX0tleWJvYXtbJiomXX1yZERvd24ob2JqZWN0IHNlbmRlciwgU2RsRG90TmV0LklucHV0LktleWJvYXJkRXZlbnRBcmdzIGUpDQogICAgICAgIHsNCiAgICAge1smKiZdfSAgICAgICBpZiAoZS5LZXkgPT0gU2RsRG90TmV0LklucHV0LktleS5Fc2NhcGUpIEV2ZW50cy5RdWl0QXBwbGljYXRpb24oKTsNCiB7WyYqJl19ICAgICAgIH0NCiAgICB9DQp9DQpcIjt7WyYqJl19[[/code]
Qui cosa abbiamo fatto? Andiamo con ordine. L'obiettivo di questo programma non è niente di eccezionale: leggendo ogni spostamento del mouse, riportiamo a schermo le sue coordinate. Queste saranno memorizzate in una stringa che verrà utilizzata con un font.
Ecco che dichiariamo la nostra stringa (inizialmente vuota) “posizione” e il nostro font f1(ricordate che il file del carattere da utilizzare dovrà essere ubicato nella stessa cartella dell'eseguibile che compileremo):
Font f1 = new Font("Calibri.ttf", 12);
string posizione = "";
Adesso andiamo a gestire l'evento relativo al movimento del mouse, che si chiama MouseMotion:
public void Go()
{
Events.KeyboardDown += new EventHandler<SdlDotNet.Input.KeyboardEventArgs>(Events_KeyboardDown);
Events.MouseMotion += new EventHandler<SdlDotNet.Input.MouseMotionEventArgs>(Events_MouseMotion);
Events.Tick += new EventHandler<TickEventArgs>(Events_Tick);
Events.Run();
}
Il metodo che lanceremo per gestire la procedura sarà Events_MouseMotion. Il nome è creato automaticamente dal sistema, ma potete crearne uno direttamente voi. L'ho fatto per comodità e per il fatto che viene generato al volo dall'Intellisense del Visual Studio, alla semplice pressione del tasto Tab. Comunque, ecco il nostro codice:
void Events_MouseMotion(object sender, SdlDotNet.Input.MouseMotionEventArgs e)
{
posizione = "Mouse - X: " + e.X.ToString() + ", Y: " + e.Y.ToString();
}
Anche stavolta abbiamo un oggetto sender ed uno “e”, stavolta però di tipo MouseMotionEventArgs. Quindi, cosa fa questo metodo? Semplicemente, ogni volta che il sistema rileva uno spostamento del mouse assegneremo alla stringa “posizione” i valori di X ed Y che il mouse assume in quel momento. Finchè il mouse non verrà mosso, i valori non cambieranno ulteriormente.

Una schermata del programma di Prova.
Occorre anche in questo caso fare una bella scarrellata di proprietà che ci vengono messe a disposizione dall'oggetto “e”. Non le riporto tutte ovviamente, ma solo alcune:
- X ed Y: due proprietà che indicano la posizione sull'asse X ed Y del mouse allo stato attuale del sistema;
- Button: restituisce il nome del pulsante del mouse attualmente premuto usando come valori possibili l'enumerazione Input.MouseButton;
- ButtonPressed: booleana che restituisce True nel caso un pulsante sia stato premuto.
Questi strumenti permettono di gestire al meglio l'input da parte dell'utente, sfruttando le potenzialità del classico metodo “mouse più tastiera” tipico della grande maggioranza di giochi in circolazione negli ultimi anni.
Spero di essere stato chiaro in queste spiegazioni. Vi consiglio assolutamente di fare molte prove e, come già detto precedentemente, sperimentare per bene il sistema ad eventi se non lo si è capito bene. Specialmente adesso, forti di queste nuove piccole nozioni. Con queste basi, molto presto saremo pronti ad affrontare la creazione di un piccolo gioco vero e proprio.
Alla prossima!



Ultimi Commenti