giovedì 12 marzo 2009

6) XNA videogame tutorial: Keyboard Input

Nello scorso post vi ho raccontato come utilizzare i GameComponents e come scrivere una classe per gestire degli oggetti sprites.
Oggi invece vi mostrerò come pilotare un'astronave attraverso la tastiera!
Come sorgente iniziale potete utilizzare quello della lezione precedente, alla quale aggiungeremo una classe ( a fondo lezione trovere il sorgente finale) .
Cercherò di non tirarla alle lunghe questa volta perchè l'argomento è veramente semplice, come già detto sopra lo scopo è quello di far si che tramite l'utilizzo della tastiera si possa decidere il posizionamento della nostra astronave, se ricordate abbiamo usato una classe astratta "Sprite" che poi abbiamo derivato con una classe "AutoSprite" che permetteva alle astronavi di muoversi autonomamente. Oggi creeremo la classe "Controlled Sprite" controllata dall'utente, naturalmente derivando la classe Sprite come per AutoSprite.

Video Anteprima



La classe si dovrà in poche parole occupare di intercettare il nostro input (useremo le frecce direzionali) e in base a questo modificare i parametri X e Y del vettore posizione dell'astronave.
Ecco il codice completo della nuova classe e di seguito la spiegazione:

CONTROLLED SPRITE
using System;

using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
Microsoft.Xna.Framework;
using
Microsoft.Xna.Framework.Graphics;
using
Microsoft.Xna.Framework.Input;

namespace
input
{

class
ControlledSprite : Sprite
{


public
ControlledSprite(Texture2D new_texture, Vector2 new_position,Vector2 new_speed)
:
base(new_texture, new_position, new_speed)
{

}


public
override void Update(GameTime gameTime)
{

position += direction;
base.Update(gameTime);
}


//Controlla gli input da tastiera (volendo qui si possono aggiungere
//altri device, come mouse e pad)
//E restituisce info sulla direzione
public Vector2 direction {
get {
Vector2 inputDirection = Vector2.Zero;
//Movimento destra
if (Keyboard.GetState().IsKeyDown(Keys.Left)) {
inputDirection.X -= 1;
}

//Movimento sinistra
if (Keyboard.GetState().IsKeyDown(Keys.Right))
{

inputDirection.X += 1;
}

//Movimento su
if (Keyboard.GetState().IsKeyDown(Keys.Up))
{

inputDirection.Y -= 1;
}

//Movimento giù
if (Keyboard.GetState().IsKeyDown(Keys.Down))
{

inputDirection.Y += 1;
}


return
inputDirection * speed;
}
}
}
}



(Vi ricordo che il namespace che vedete qui dipende da come ho chiamato il mio progetto.. per evitare problemi utilizzate il vostro namespace (oppure partite dal codice che vi allego sotto :P )
Vediamo come viene creata questa classe..... Prima di tutto nella definizione di classe Ereditate le info della classe Sprite con ": Sprite"
Il costruttore è identico a quello proposto nella Sprite e fino a qui niente di nuovo.... Ora entriamo nella Update, qui andiamo a modificare il valore di position utilizzando la proprietà direction definita sotto, notate che tramite get andiamo a chiamare una funziona che vi suonerà nuova :
Keyboard.GetState().IsKeyDown(Keys.Left)
Non stiamo facendo altro che controllare se la freccia sinistra è premuta...sfruttando la funzione GetState dell'oggetto Keyboard, appositamente creato per XNA :D. Notate ceh in testa alla classe abbiamo definito che utilizzeremo il namespace input di XNA:
using Microsoft.Xna.Framework.Input;

Questo oggetto ha parecchie funzioni interessanti (utili per gestire altri device come Pad e mouse) vi rimando a questo link per scoprirle meglio.

Tornando alla nostra funzione update noterete che verifichiamo con un blocco di IF se una delle frecce è premuta, in tal caso decrementiamo o incrementiamo le chiavi X o Y dell'oggetto inputDirection.
E come ultimo passaggio moltiplichiamo il valore per la Velocità dell'astronave, il valore verrà dunque sommato all'attuale position e quindi alla chiamata della Draw (che se vi ricordate, parte dal foreach dentro la Draw dello spritemanager..... scrorre tutti gli elementi della lista sprite e chiama per questi elementi le rispettive funzioni Draw) .
In questo caso come potete notare non abbiamo una Draw, quindi utilizzeremo quella della classe Padre (Sprite.cs) che va più che bene per i nostri scopi.

Aggiungiamo l'astronave controllabile nello spritemanager:
Nella classe SpriteManager.cs aggiungete le informazioni che ho inserito qui in neretto nella funzione LoadContent.
        protected override void LoadContent()

{

tex1 = Game.Content.Load<Texture2D>("enemy");
tex2 = Game.Content.Load<Texture2D>("enemy2");
texp = Game.Content.Load<Texture2D>("spaceship");
spriteBatch = new SpriteBatch(Game.GraphicsDevice);
spriteList.Add(new ControlledSprite(texp, new Vector2(0.0f, 0.0f),new Vector2(3.0f,3.0f)));
spriteList.Add(new AutoSprite(tex1,pos1,spd1));
spriteList.Add(new AutoSprite(tex1, pos2, spd2));
spriteList.Add(new AutoSprite(tex2, new Vector2(300.0f,0.0f), new Vector2 (1.0f,3.0f)));
base.LoadContent();
}
Come potete notare andiamo semplicemente ad aggiungere un elemento alla lista SpriteList (e nel caso non ci fosse già creiamo una texture per questo elemento... attenzione! ricordatevi di aggiungere la texture ai contenuti Add->existing Item .... la vostra texture) .

Vi faccio notare che la lista spriteList è stata definita come :
List spriteList = new List();

Quindi una lista di oggetti Sprite.... eppure noi nella lista abbiamo aggiunto oggetti ControlledSprite e AutoSprite....l'operazione è comunque valida proprio perchè questi oggetti sono specializzazioni della classe Sprite. Se volete avere qualche info in più sulla sintassi sopra leggete questo articolo sulle classi generiche in C#.

Allinea a sinistraA questo punto compilando, dovreste vedere una nuova astronave in alto a sinistra, ferma immobile...
bhe muovetela con la vostra tastiera! :D

Codici Sorgenti Finali:
3.input.zip




1 commenti:

Anonimo ha detto...

Funziona! XD

Posta un commento