domenica 13 maggio 2012

Tutorial XNA creazione di un gioco completo

Riporto l'articolo scritto per il sito http://www.iprogrammatori.it/articoli/programmazione/art_tutorial-xna-creazione-gioco-completo-pa_1164.aspx

Introduzione

In questa serie di articoli vedremo come creare un gioco completo in XNA, in cui verranno forniti indicazioni di un ciclo completo di un gioco,  come la stesura di un gioco, ambiente, punteggio,  e collisione.
L’esempio sarà un’astronave che deve evitare degli ostacoli nello spazio, che sono degli astereoidi inoltre può sparare per distruggere tali oggetti.

Creazione del video gioco

Si deve creare un nuovo progetto XNA, questo progetto, nel corso del tutorial, verrà implementato con classi, progetti ed oggetti. Il nome è a scelta libera (nel nostro caso è XNATutorial)
Aggiungiamo alla sezione “Content” un immagine che riguarda una navicella spaziale, per esempio simile a quella illustrata in figura 1.


Figura 1

Creazione della classe player

Si aggiunge al progetto una nuova classe (tasto destro sul progetto in esplora soluzione) e selezioniamo la voce di menu “Aggiungi” e successivamente “Classe”.
La classe la chiameremo “Player” il nome del file sarà “Player.cs”.
Questa classe, avrà il compito di gestire le informazioni del nostro oggetto “immagine” come posizione, lo stato, il carburante e tanto altro.
Qui di seguito si riporta il codice completo di tale classe.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//per la classe texture2d
using Microsoft.Xna.Framework.Graphics;
//per la classe Vector2
using Microsoft.Xna.Framework;

namespace XNATutorial
{
    class Player
    {
        // per gestire l'oggetto
        public Texture2D PlayerTexture;

        // per la posizione
        public Vector2 Posizione;

        // stato
        public bool StatoAttivo;

        // totale carburante
        public int Carburante;

        //larghezza per il posizionamento
        public int Width
        {
            get { return PlayerTexture.Width; }
        }

        //altezza per il posizionamento
        public int Height
        {
            get { return PlayerTexture.Height; }
        }


        public void Initialize(Texture2D texture, Vector2 posizione)
        {
            PlayerTexture = texture;

            // imposto la posizione
            Posizione = posizione;

            //imposto lo stato in true quindi attivo
            StatoAttivo = true;

            //imposto il punteggio
            Carburante = 100;
        }

        public void Update()
        {
        }
        /// <summary>
        /// Funzione che permette di visualizzare a video il risultato
        /// </summary>
        /// <param name="spriteBatch"></param>
        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(PlayerTexture, Posizione, null, Color.White, 0f, Vector2.Zero, 1f, SpriteEffects.None, 0f);
        }



    }
}

La classe contiene tre metodi, initialize, che imposta i parametri della classe, il metodo draw, che ridisegna il nostro oggetto a video, e update (che vedremo più avanti), inoltre avremmo vari oggetti, per gestire la posizione, il carburante, il disegno e tanto altro.
Passiamo alla classe, game1, per impostare il nostro gioco.

Impostare la classe Game1

Si creano a livello di classe, gli oggetti che permettono di gestire le informazioni del gioco, come un oggetto della classe creata precedentemente, la velocità, la gestione della tastiera, qui di seguito si riporta tali dichiarazioni.


//oggetto della classe Player
        Player player;
        //Per la gestioe della tastiera
        KeyboardState StatoCorrenteTastiera;
        KeyboardState StatoPrecedenteTastiera;

        // la velocità di spostamento
        float VelocitaSpostamento;

Nell’evento initialize, inizializziamo l’oggetto player ed impostiamo la velocità di spostamento, il tutto come illustrato qui di seguito.
protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            // inizializzo la classe
            player = new Player();
            //imposola velocità
            VelocitaSpostamento = 8.0f;

            base.Initialize();
        }

Passiamo all’evento loadContent, in cui andremo a rilevare la risorsa (immagine dell’astronave) da visualizzare a video e la relativa posizione.
In questo evento, utilizziamo il metodo Initialize, creato precedentemente nella classe player, in cui andremo ad inserire la risorsa (immagine) e la posizione.
Qui di seguito si riporta il codice completo delle suddette operazioni.
protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            // carico la risorsa (immagine)
            Vector2 playerPosizione = new Vector2(GraphicsDevice.Viewport.TitleSafeArea.X, GraphicsDevice.Viewport.TitleSafeArea.Y + GraphicsDevice.Viewport.TitleSafeArea.Height / 2);
            player.Initialize(Content.Load<Texture2D>("Astronave"), playerPosizione);
            // TODO: use this.Content to load your game content here
        }

Si crea un metodo che permette di gestire l’input della tastiera, come la pressione dei tasti di freccia di direzione (freccette) per lo spostamento della nostra immagine,  il metodo denominato UpdatePlayer, viene riportato qui di seguito.
private void UpdatePlayer(GameTime gameTime)
        {

            //nel caso che digito il pulsante esc esco dal gioco
            if (StatoCorrenteTastiera.IsKeyDown(Keys.Escape))
                base.Exit();
           

            //in riferimento alle freccie della tastiera sposto l'astronave
            if (StatoCorrenteTastiera.IsKeyDown(Keys.Left) )
            {
                player.Posizione.X -= VelocitaSpostamento;
            }
            if (StatoCorrenteTastiera.IsKeyDown(Keys.Right) )
            {
                player.Posizione.X += VelocitaSpostamento;
            }
            if (StatoCorrenteTastiera.IsKeyDown(Keys.Up) )
            {
                player.Posizione.Y -= VelocitaSpostamento;
            }
            if (StatoCorrenteTastiera.IsKeyDown(Keys.Down) )
            {
                player.Posizione.Y += VelocitaSpostamento;
            }


            //imposto la posizione della navicella
            player.Posizione.X = MathHelper.Clamp(player.Posizione.X, 0, GraphicsDevice.Viewport.Width - player.Width);
            player.Posizione.Y = MathHelper.Clamp(player.Posizione.Y, 0, GraphicsDevice.Viewport.Height - player.Height);

        }
Nel metodo update, della classe game1,  rileviamo lo stato della tastiera precedente e quello in cui si è appena fatto click, per poi eseguire il metodo “UpdatePlayer” creato poco fa.
Qui di seguito si riporta il codice dell’evento update.
/// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here
            //tasto precedente prima di questa modifica          
            StatoPrecedenteTastiera = StatoCorrenteTastiera;

            //rilevo l'ultimo pulsante digitato
            StatoCorrenteTastiera = Keyboard.GetState();
          


            //Update the player
            UpdatePlayer(gameTime);

            base.Update(gameTime);
        }

L’evento Draw, permette di ridisegnare a video le varie “attività”,  in particolare, utilizziamo il metodo Draw, per ridisegnare il gioco, il metdo beging abilita la modifica a video, mentre end la chiusura
Qui di seguito si riporta il codice dell’evento Draw.

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

            // TODO: Add your drawing code here
            //ridisegno il tutto
            spriteBatch.Begin();
            //aggiorno la visualizzazione
            player.Draw(spriteBatch);
            //termine del ridisegno
            spriteBatch.End();
            base.Draw(gameTime);
        }

Qui di seguito si riporta il codice completo della classe Game1.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace XNATutorial
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        //oggetto della classe Player
        Player player;
        //Per la gestione della tastiera
        KeyboardState StatoCorrenteTastiera;
        KeyboardState StatoPrecedenteTastiera;

        // la velocità di spostamento
        float VelocitaSpostamento;



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

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            // inizializzo la classe
            player = new Player();
            //imposola velocità
            VelocitaSpostamento = 8.0f;

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            // carico la risorsa (immagine)
            Vector2 playerPosizione = new Vector2(GraphicsDevice.Viewport.TitleSafeArea.X, GraphicsDevice.Viewport.TitleSafeArea.Y + GraphicsDevice.Viewport.TitleSafeArea.Height / 2);
            player.Initialize(Content.Load<Texture2D>("Astronave"), playerPosizione);
            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here
            //tasto precedente prima di questa modifica          
            StatoPrecedenteTastiera = StatoCorrenteTastiera;

            //rilevo l'ultimo pulsante digitato
            StatoCorrenteTastiera = Keyboard.GetState();
          


            //Update the player
            UpdatePlayer(gameTime);

            base.Update(gameTime);
        }


        private void UpdatePlayer(GameTime gameTime)
        {

            //nel caso che digito il pulsante esc esco dal gioco
            if (StatoCorrenteTastiera.IsKeyDown(Keys.Escape))
                base.Exit();
           

            //in riferimento alle freccie della tastiera sposto l'astronave
            if (StatoCorrenteTastiera.IsKeyDown(Keys.Left) )
            {
                player.Posizione.X -= VelocitaSpostamento;
            }
            if (StatoCorrenteTastiera.IsKeyDown(Keys.Right) )
            {
                player.Posizione.X += VelocitaSpostamento;
            }
            if (StatoCorrenteTastiera.IsKeyDown(Keys.Up) )
            {
                player.Posizione.Y -= VelocitaSpostamento;
            }
            if (StatoCorrenteTastiera.IsKeyDown(Keys.Down) )
            {
                player.Posizione.Y += VelocitaSpostamento;
            }


            //imposto la posizione della navicella
            player.Posizione.X = MathHelper.Clamp(player.Posizione.X, 0, GraphicsDevice.Viewport.Width - player.Width);
            player.Posizione.Y = MathHelper.Clamp(player.Posizione.Y, 0, GraphicsDevice.Viewport.Height - player.Height);

        }



        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.White);

            // TODO: Add your drawing code here
            //ridisegno il tutto
            spriteBatch.Begin();
            //aggiorno la visualizzazione
            player.Draw(spriteBatch);
            //termine del ridisegno
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}



Figura 2

Conclusioni

Ora non ci resta che compilare il nostro gioco ed una volta avviata l’applicazione, utilizzando le frecce della tastiere, vedremo la nostra astronave spostarsi il tutto come mostrato in figura 2.
Questa prima parte del tutorial ha voluto fornire le basi per la gestione delle risorse (immagine) ed il relativo spostamento.

Nessun commento: