- Introduzione a XNA Game Studio -
|
|||
COSA SERVE PER QUESTO TUTORIAL | |||
Download | Chiedi sul FORUM | Glossario | cognizioni basiche di C# | ||
Il primo videogioco con XNA | |||
COME È STRUTTURATO UN GIOCO PER XNA Update, Draw, caricamento delle risorse e gestione dell'interazione.
In questo primo tutorial ci occuperemo di XNA, un
framework per la creazione
di videogiochi in linguaggi .Net (C# primo fra tutti) che si basa sulle
DirectX. Vediamo prima di tutto quali sono gli strumenti necessari per
creare il nostro primo, semplice, videogioco. L'ambiente di sviluppo
preferibile per servirsi delle librerie XNA è XNA Game Studio, un IDE basato
su Visual Studio che offre alcune facilitazioni, principalmente per i
template di tipi di file già pronti. Se non avete una versione di Visual
Studio già installata potete procurarvi l'edizione Express (ovvero
gratuita) di
Visual C#; in questo articolo verrà presa in considerazione l'ultima versione correntemente
disponibile di XNA, ovvero la 3.1, che supporta Visual Studio 2005 e
Visual Studio 2008. Installato Visual Studio, scaricate ed installate
XNA Game Studio 3.1 e siamo pronti per iniziare.
Nel gioco di esempio vogliamo creare un semplice personaggio che sia
in grado di muoversi nell'area di gioco (tramite le frecce direzionali
della tastiera) e di variare la propria velocità e dimensione. Avremo bisogno di due risorse: un'immagine per lo sfondo
e un'immagine per il nostro personaggio (non troppo grande, 16
per 16 pixel sarebbe l'ideale). Per aggiungerle al progetto fare click destro su
Content
in Solution Explorer, Add Existing Item e selezionare le due immagini
dalla macchina locale, quindi rinominate lo sfondo in sfondo.jpg (o
sfondo.png nel caso abbiate scelto una PNG) e il personaggio in
spidey.jpg (o spidey.png). public class PallinaGame : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D pallina, bg; Vector2 posizionePallina = new Vector2(0); int speed = 1; int size = 1; public PallinaGame() { // Permettiamo il ridimensionamento della finestra this.Window.AllowUserResizing = true; // Inizializziamo il GraphicsDeviceManager e impostiamo le dimensioni // desiderate dell'area di disegno graphics = new GraphicsDeviceManager(this); graphics.PreferredBackBufferWidth = 800; graphics.PreferredBackBufferHeight = 600; // Impostiamo la sottocartella con le risorse this.Content.RootDirectory = "Content"; } Per prima cosa notiamo che la classe eredita da
Microsoft.Xna.Framework.Game, infatti ogni gioco XNA deve avere una
classe simile che costituisce la base del gioco; esso permette ad
esempio di terminare il gioco con il metodo Exit, oppure di
abilitare il ridimensionamento della finestra del gioco tramite la
proprietà Window.AllowUserResizing. Game espone inoltre la proprietà
Content, tramite la quale è possibile interagire con le risorse
contenute nella cartella Content di cui si parlava poco fa.
Content.RootDirectory imposta la sottocartella (rispetto all'eseguibile)
che contiene le risorse, in questo caso sarà dunque la sottocartella "Content". // Carichiamo le risorse in memoria protected override void LoadContent() { // Inizializziamo lo SpriteBatch spriteBatch = new SpriteBatch(this.GraphicsDevice); // Carichiamo sfondo e personaggio bg = this.Content.Load<Texture2D>("sfondo"); pallina = this.Content.Load<Texture2D>("pallina"); } In LoadContent prima di tutto creiamo una nuova istanza di spriteBatch relativo al GraphicsDevice del nostro gioco, quindi inizializziamo le variabili bg e pallina caricando le risorse sfondo e pallina. Si noti che l'identificativo della risorsa è il nome del file privato dell'estensione. A questo punto abbiamo concluso la parte preparatoria del nostro gioco e possiamo iniziare a vedere le due funzioni che gestiscono la logica e l'output grafico: Update e Draw. Esse vengono in sostanza chiamate di continuo in successione in modo che tramite Update si possa rilevare ad esempio la pressione di un tasto, cambiare le variabili di gioco e lasciare che poi il metodo Draw ridisegni l'area di gioco di conseguenza. Ma vediamole in dettaglio: // Gestiamo la logica di gioco protected override void Update(GameTime gameTime) { if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Escape)) this.Exit(); if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Delete)) { speed = 1; size = 1; posizionePallina.X = 0; posizionePallina.Y = 0; } if (speed >= 1 && Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.PageDown)) speed--; if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.PageUp)) speed++; Rectangle gameArea = new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height); if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.F11) && size >= 1) size--; if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.F12) && gameArea.Contains(this.GetPallinaRectangle(0, 0, 1, 1))) size++; if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Up)) if (gameArea.Contains(this.GetPallinaRectangle(0, -speed, 0, 0))) posizionePallina.Y -= speed; else posizionePallina.Y = 0; // [...] // Gestione delle altre direzioni // [...] base.Update(gameTime); } Il metodo Update è in questo caso completamente dedicato alla
gestione degli input dell'utente, infatti tramite Keyboard.GetState
possiamo controllare se un tasto è stato premuto o meno ed
agire di conseguenza. Il tasto Esc causa la chiusura del
gioco, il tasto Canc la reimpostazione della variabili di gioco,
Pagina
Su e Pagina Giù regolano la velocità, F11 e
F12 la dimensione e le
frecce direzionali il movimento. Il movimento consiste sostanzialmente
nel verificare che non si stia uscendo dall'area di gioco e quindi
incrementare o decrementare la coordinata X o Y (a seconda del tasto
premuto) della pallina di un valore pari alla variabile della velocità. // Gestiamo l'output grafico istante per istante protected override void Draw(GameTime gameTime) { // Puliamo l'area di disegno GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); // Disegnamo lo sfondo spriteBatch.Draw(bg, new Rectangle(0, 0, this.GraphicsDevice.Viewport.Width, this.GraphicsDevice.Viewport.Height), Color.White); // Disegnamo il personaggio spriteBatch.Draw(pallina, this.GetPallinaRectangle(), Color.White); spriteBatch.End(); base.Draw(gameTime); } In sostanza nel metodo di disegno puliamo l'area di disegno e iniziamo a disegnare lo sprite. Prima chiamiamo il metodo Draw di SpriteBatch passandogli l'oggetto in cui avevamo caricato la sfondo (bg) e il rettangolo su cui estenderlo, da in alto a sinistra per tutta la larghezza dell'area di disegno. Quindi disegniamo il personaggio nella posizione indicata dal vettore posizionePallina e con le dimensioni pari a size-volte quella originale: private Rectangle GetPallinaRectangle(int dx, int dy, int dw, int dh) { return new Rectangle((int)posizionePallina.X + dx, (int)posizionePallina.Y + dy, pallina.Width * (size + dw), pallina.Height * (size + dh)); } private Rectangle GetPallinaRectangle() { return GetPallinaRectangle(0, 0, 0, 0); } Nel progetto allegato è anche presente un componente (vedremo prossimamente di cosa si tratta e come crearne) che mostra in alto a sinistra il numero di chiamate a Update e Draw per secondo.
|
|||
<< INDIETRO | by VeNoM00 |