Introduzione
In questa parte vedremo come aggiungere al gioco creato fino a questo momento, la gestione di un immagine che permetta di gestire l’esplosione.
Prima di tutto, aggiungiamo nella sezione “Content” l’immagine relativa ad un esplosione.
Questa immagine, è formata da 12 immagini, in cui viene simulato un’esplosione.
Qui di seguito si riporta la figura 1.
Figura 1
Dalla finestra “esplora soluzioni”, selezioniamo la sezione “Content”, e tramite il menu di scelta rapida aggiungiamo una risorsa e precisamente l’immagine di figura 1.
Dalla voce di menu “Aggiungi” selezioniamo “Elemento Esistente” selezioniamo il file di nostro interesse
Stesura di codice
Ora passiamo alla classe Game1, nella quale andremo a gestire questo nuovo elemento.
A livello di classe, scriviamo i membri che avranno il compito di gestire queto elemento, come la risorsa ed un oggetto di tipo classe “Animazione”.
Qui di seguito si riporta la dichiarazione di tali operazioni.
//Gestione esplosione
Texture2D TextureEsplosione;
List<Animazione> Esplosioni;
Nell’evento “Initialize” inizializziamo l’oggetto di tipo lista animazione, ossia “Esplosioni”.
Qui di seguito si riporta il codice dell’evento “Initialize”.
protected override void Initialize()
{
// TODO: Add your initialization logic here
// inizializzo la classe
player = new Player();
//imposola velocità
VelocitaSpostamento = 8.0f;
//oggetti per la gestione dello sfondo
sfondo1 = new Sfondo();
sfondo2 = new Sfondo();
//inizializzo l'oggetto degli asteroide
Asteroidi = new List<Asteroide>();
//imposto a zero il tempo per asteroide precendente
TempoAsteroidePrecedente = TimeSpan.Zero;
//imposto i tempi degli asteroide
TempoAsteroide = TimeSpan.FromSeconds(1.0f);
//inizializzo l'oggetto di tipo random
random = new Random();
//inizializzo l'oggetto per la gestione del fuoco, i vari spari
spari = new List<Sparo>();
//imposto il tempo del primo fuoco
TimePrimoFuoco = TimeSpan.FromSeconds(.15f);
//inizializzo l'oggetto esplosioni
Esplosioni = new List<Animazione>();
base.Initialize();
}
Nell’evento “LoadContent” imposto la risorsa all’oggetto TextureEsplosione, creato in precedenza
Qui di seguito si riporta l’evento “LoadContent”
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
//oggetto per la gestione dell'effetto immagini in movimento
Animazione playerAnimazione = new Animazione();
Texture2D playerTexture = Content.Load<Texture2D>("AstronaveMovimento");
playerAnimazione.Initialize(playerTexture, Vector2.Zero, 115, 69, 8, 30, Color.White, 1f, true);
// carico la risorsa (immagine)
Vector2 playerPosizione = new Vector2(GraphicsDevice.Viewport.TitleSafeArea.X, GraphicsDevice.Viewport.TitleSafeArea.Y + GraphicsDevice.Viewport.TitleSafeArea.Height / 2);
//ricambio l'oggetto player
player.Initialize(playerAnimazione, playerPosizione);
// player.Initialize(Content.Load<Texture2D>("Astronave"), playerPosizione);
//carico le immagini
sfondo1.Initialize(Content, "Sfondo1", GraphicsDevice.Viewport.Width, -1);
sfondo2.Initialize(Content, "Sfondo2", GraphicsDevice.Viewport.Width, -2);
SfondoPrincipale = Content.Load<Texture2D>("SfondoPriincipale");
//carico l'immagine asteroide
AsteroideTexture = Content.Load<Texture2D>("asteroide");
//carico l'immagine relativo al fuoco
TextureFuoco = Content.Load<Texture2D>("Fuoco");
//carico la risorsa immagine relativo all'esplosione
TextureEsplosione = Content.Load<Texture2D>("Esplosione");
// TODO: use this.Content to load your game content here
}
Si scrive una funzione che permetta di aggiungere di volta in volta l’immagine esplosione, tramite il metodo “Initialize” dell’oggetto Esplosione, impostiamo la posizione ed il modo di visualizzare l’immagine, visualizzando il singolo frame dell’immagine con i vari fotogrammi.
Qui di seguito si riporta tale funzione.
//metodo che permette di aggiungere l'esplosione e quindi l'animazione tramite le varie immagini, il tutto nel metodo "Initialize"
private void AggiungiEsplosione(Vector2 posizione)
{
Animazione esplosione = new Animazione();
esplosione.Initialize(TextureEsplosione, posizione, 134, 134, 12, 45, Color.White, 1f, false);
Esplosioni.Add(esplosione);
}
Nel metodo aggiorna Asteroidi, impostiamo nella condizione di verificare lo stato dell’oggetto di tipo Asteoride.
Qui di seguito si riporta il codice completo del metodo AggiornaAsteroidi.
/// <summary>
/// funzione che permette di aggiungere o eliminare le risorse da visualizzare a video
/// </summary>
/// <param name="gameTime"></param>
private void AggiornaAsteroidi(GameTime gameTime)
{
//aggiungo un nuovo elemento ogni secondo e mezzo.
if (gameTime.TotalGameTime - TempoAsteroidePrecedente > TempoAsteroide)
{
TempoAsteroidePrecedente = gameTime.TotalGameTime;
//aggiungo la risorsa a video
AggiungiAsteroide();
}
//nel caso che lo stato attivo è false elimino l'asteroide in questione
for (int i = Asteroidi.Count - 1; i >= 0; i--)
{
Asteroidi[i].Update(gameTime);
if (Asteroidi[i].StatoAttivo == false)
{
//imposto l'esplosione in caso che non ha più eneriga
if (Asteroidi[i].Energia <= 0)
{
//eseguo l'esplosione e viene aggiunta
AggiungiEsplosione(Asteroidi[i].Posizione);
}
Asteroidi.RemoveAt(i);
}
}
}
Ora si dovrà scrivere il metodo che permette togliere dall’area del gioco, la risorsa relativa all’esplosione, verificando se lo stato non è più attivo.
Qui di seguito si riporta il metodo delle suddette operazioni.
/// <summary>
/// metodo che permette di eliminaer dall'area di gioco la risorsa esplosione
/// </summary>
/// <param name="gameTime"></param>
private void AggiornaEsplosioni(GameTime gameTime)
{
for (int i = Esplosioni.Count - 1; i >= 0; i--)
{
Esplosioni[i].Update(gameTime);
if (Esplosioni[i].statoAttivo == false)
{
Esplosioni.RemoveAt(i);
}
}
}
Ora nel metodo update, scriviamo il codice che invochi il metodo “AggiornaEsplosioni”, lo scriviamo subito dopo l’invocazione del metodo “AggiornaFuoco” qui si riporta il codice di tale metodo.
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();
//aggiorno il gaming
UpdatePlayer(gameTime);
//aggiorno la posizione delle immagini
sfondo1.Update();
sfondo2.Update();
//aggiungo o elimino gli asteroidi
AggiornaAsteroidi(gameTime);
//per la collisione
Collisione();
//per la visualizzazione
AggiornaFuoco();
//invoco il codice relativo alla risorsa esplosione
AggiornaEsplosioni(gameTime);
base.Update(gameTime);
}
Nel metodo Draw, scriviamo il codice che permette di visualizzare le esplosioni.
Qui di seguito si riporta il codice di tali operazioni.
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
// TODO: Add your drawing code here
//ridisegno il tutto
spriteBatch.Begin();
spriteBatch.Draw(SfondoPrincipale, Vector2.Zero, Color.White);
//visualizzo lo spostamento
sfondo1.Draw(spriteBatch);
sfondo2.Draw(spriteBatch);
//aggiorno la visualizzazione della risorsa di tipo asteroide
for (int i = 0; i < Asteroidi.Count; i++)
{
Asteroidi[i].Draw(spriteBatch);
}
//aggiorno la visualizzazione della risora di tipo fuoco
for (int i = 0; i < spari.Count; i++)
{
spari[i].Draw(spriteBatch);
}
//aggiorno la visualizzazione della risorsa esplosioni.
for (int i = 0; i < Esplosioni.Count; i++)
{
Esplosioni[i].Draw(spriteBatch);
}
//aggiorno la visualizzazione
player.Draw(spriteBatch);
//termine del ridisegno
spriteBatch.End();
base.Draw(gameTime);
}
Si riporta il codice completo di questa sesta parte, relativo alla classe Game1.
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;
//immagine principale
Texture2D SfondoPrincipale;
//gestione delle immagini di sfondo quelle in movimento
Sfondo sfondo1;
Sfondo sfondo2;
//gestione della risorsa asteroide
//oggetto di tipo Asteroide
Texture2D AsteroideTexture;
List<Asteroide> Asteroidi;
//oggetti per gestire i tempi di visualizzare gli asteroidi
TimeSpan TempoAsteroide;
TimeSpan TempoAsteroidePrecedente;
//numero causale per la visualizzazione degli asteroide
Random random;
//per la gestione della risorsa fuoco
Texture2D TextureFuoco;
List<Sparo> spari;
//per la gestione dei tempi tra uno sparo e l'altro
TimeSpan TimePrimoFuoco;
TimeSpan TimeFuocoPrecedente;
//Gestione esplosione
Texture2D TextureEsplosione;
List<Animazione> Esplosioni;
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;
//oggetti per la gestione dello sfondo
sfondo1 = new Sfondo();
sfondo2 = new Sfondo();
//inizializzo l'oggetto degli asteroide
Asteroidi = new List<Asteroide>();
//imposto a zero il tempo per asteroide precendente
TempoAsteroidePrecedente = TimeSpan.Zero;
//imposto i tempi degli asteroide
TempoAsteroide = TimeSpan.FromSeconds(1.0f);
//inizializzo l'oggetto di tipo random
random = new Random();
//inizializzo l'oggetto per la gestione del fuoco, i vari spari
spari = new List<Sparo>();
//imposto il tempo del primo fuoco
TimePrimoFuoco = TimeSpan.FromSeconds(.15f);
//inizializzo l'oggetto esplosioni
Esplosioni = new List<Animazione>();
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);
//oggetto per la gestione dell'effetto immagini in movimento
Animazione playerAnimazione = new Animazione();
Texture2D playerTexture = Content.Load<Texture2D>("AstronaveMovimento");
playerAnimazione.Initialize(playerTexture, Vector2.Zero, 115, 69, 8, 30, Color.White, 1f, true);
// carico la risorsa (immagine)
Vector2 playerPosizione = new Vector2(GraphicsDevice.Viewport.TitleSafeArea.X, GraphicsDevice.Viewport.TitleSafeArea.Y + GraphicsDevice.Viewport.TitleSafeArea.Height / 2);
//ricambio l'oggetto player
player.Initialize(playerAnimazione, playerPosizione);
// player.Initialize(Content.Load<Texture2D>("Astronave"), playerPosizione);
//carico le immagini
sfondo1.Initialize(Content, "Sfondo1", GraphicsDevice.Viewport.Width, -1);
sfondo2.Initialize(Content, "Sfondo2", GraphicsDevice.Viewport.Width, -2);
SfondoPrincipale = Content.Load<Texture2D>("SfondoPriincipale");
//carico l'immagine asteroide
AsteroideTexture = Content.Load<Texture2D>("asteroide");
//carico l'immagine relativo al fuoco
TextureFuoco = Content.Load<Texture2D>("Fuoco");
//carico la risorsa immagine relativo all'esplosione
TextureEsplosione = Content.Load<Texture2D>("Esplosione");
// 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();
//aggiorno il gaming
UpdatePlayer(gameTime);
//aggiorno la posizione delle immagini
sfondo1.Update();
sfondo2.Update();
//aggiungo o elimino gli asteroidi
AggiornaAsteroidi(gameTime);
//per la collisione
Collisione();
//per la visualizzazione
AggiornaFuoco();
//invoco il codice relativo alla risorsa esplosione
AggiornaEsplosioni(gameTime);
base.Update(gameTime);
}
private void UpdatePlayer(GameTime gameTime)
{
//passo l'oggetto gametime
player.Update(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 + 50);
//verifico l'intervallo di tempo tra un fuoco e l'altro
if (gameTime.TotalGameTime - TimeFuocoPrecedente > TimePrimoFuoco)
{
//imposto il tempo
TimeFuocoPrecedente = gameTime.TotalGameTime;
// agguingo una risorsa a video, in questo modo viene inserito un oggetto di tipo fuoco
AggiungiFuoco(player.Posizione + new Vector2(player.Width / 2, 0));
}
}
//permette di togliere gli oggetti in visualizzazione
private void AggiornaFuoco()
{
//se lo stato non è attivo, elimina dall'area di visualizzazione la risorsa
for (int i = spari.Count - 1; i >= 0; i--)
{
spari[i].Update();
if (spari[i].StatoAttivo == false)
{
spari.RemoveAt(i);
}
}
}
//metodo che permette di aggiungere l'esplosione e quindi l'animazione tramite le varie immagini, il tutto nel metodo "Initialize"
private void AggiungiEsplosione(Vector2 posizione)
{
Animazione esplosione = new Animazione();
esplosione.Initialize(TextureEsplosione, posizione, 134, 134, 12, 45, Color.White, 1f, false);
Esplosioni.Add(esplosione);
}
private void AggiungiAsteroide()
{
// Create the animation object
Animazione AsteroideAnimazione = new Animazione();
//Inizializzo l'oggetto per la gestione dell'animazione dell'asteroide - possiamo creare anche un immagini con più immagine animate, cambiando il valore 1 con il totale degli elementi
AsteroideAnimazione.Initialize(AsteroideTexture, Vector2.Zero, 47, 61, 1, 30, Color.White, 1f, true);
//genero in maniera causale la posizione della risorsa nello schermo
Vector2 posizione = new Vector2(GraphicsDevice.Viewport.Width + AsteroideTexture.Width / 2, random.Next(100, GraphicsDevice.Viewport.Height - 100));
//Creo un nuovo asteroide
Asteroide asteroide = new Asteroide();
//inzializzo con l'oggetto animazione e posizione
asteroide.Initialize(AsteroideAnimazione, posizione);
//aggiungo il nuovo oggetto alla lista degli oggetti di tipo asteroidei
Asteroidi.Add(asteroide);
}
//metodo che permette di gestire l'aggiunta di risorse nello area di gioco
private void AggiungiFuoco(Vector2 posizione)
{
Sparo sparo = new Sparo();
sparo.Initialize(GraphicsDevice.Viewport, TextureFuoco, posizione);
spari.Add(sparo);
}
/// <summary>
/// funzione che permette di aggiungere o eliminare le risorse da visualizzare a video
/// </summary>
/// <param name="gameTime"></param>
private void AggiornaAsteroidi(GameTime gameTime)
{
//aggiungo un nuovo elemento ogni secondo e mezzo.
if (gameTime.TotalGameTime - TempoAsteroidePrecedente > TempoAsteroide)
{
TempoAsteroidePrecedente = gameTime.TotalGameTime;
//aggiungo la risorsa a video
AggiungiAsteroide();
}
//nel caso che lo stato attivo è false elimino l'asteroide in questione
for (int i = Asteroidi.Count - 1; i >= 0; i--)
{
Asteroidi[i].Update(gameTime);
if (Asteroidi[i].StatoAttivo == false)
{
//imposto l'esplosione in caso che non ha più eneriga
if (Asteroidi[i].Energia <= 0)
{
//eseguo l'esplosione e viene aggiunta
AggiungiEsplosione(Asteroidi[i].Posizione);
}
Asteroidi.RemoveAt(i);
}
}
}
/// <summary>
/// metodo che permette di eliminaer dall'area di gioco la risorsa esplosione
/// </summary>
/// <param name="gameTime"></param>
private void AggiornaEsplosioni(GameTime gameTime)
{
for (int i = Esplosioni.Count - 1; i >= 0; i--)
{
Esplosioni[i].Update(gameTime);
if (Esplosioni[i].statoAttivo == false)
{
Esplosioni.RemoveAt(i);
}
}
}
//per la gestione della collissione
private void Collisione()
{
// determiniamo l'area degli oggetti
Rectangle rectangleArea1;
Rectangle rectangleArea2;
//area per definire la posizione degli oggetti
rectangleArea1 = new Rectangle((int)player.Posizione.X,
(int)player.Posizione.Y,
player.Width,
player.Height);
//collisione per asteroide e navicella
for (int i = 0; i < Asteroidi.Count; i++)
{
rectangleArea2 = new Rectangle((int)Asteroidi[i].Posizione.X,
(int)Asteroidi[i].Posizione.Y,
Asteroidi[i].Width,
Asteroidi[i].Height);
// Determina la collissione tra i due oggietti
if (rectangleArea1.Intersects(rectangleArea2))
{
//danni all'astronave
player.Carburante -= Asteroidi[i].DanniAstronave;
// energia
Asteroidi[i].Energia = 0;
//cambio lo stato attivo nel caso che ho finito il carburante
if (player.Carburante <= 0)
player.StatoAttivo = false;
}
}
//Collisione tra il fuoco ed asteroide
for (int i = 0; i < spari.Count; i++)
{
for (int j = 0; j < Asteroidi.Count; j++)
{
//Creo e verifico e se le aree sono in collissioni
rectangleArea1 = new Rectangle((int)spari[i].Posizione.X -
spari[i].Width / 2, (int)spari[i].Posizione.Y -
spari[i].Height / 2, spari[i].Width, spari[i].Height);
rectangleArea2 = new Rectangle((int)Asteroidi[j].Posizione.X - Asteroidi[j].Width / 2,
(int)Asteroidi[j].Posizione.Y - Asteroidi[j].Height / 2,
Asteroidi[j].Width, Asteroidi[j].Height);
// Determina la collissione tra i due oggietti
if (rectangleArea1.Intersects(rectangleArea2))
{
Asteroidi[j].Energia -= spari[i].Danno;
spari[i].StatoAttivo = false;
}
}
}
}
/// <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();
spriteBatch.Draw(SfondoPrincipale, Vector2.Zero, Color.White);
//visualizzo lo spostamento
sfondo1.Draw(spriteBatch);
sfondo2.Draw(spriteBatch);
//aggiorno la visualizzazione della risorsa di tipo asteroide
for (int i = 0; i < Asteroidi.Count; i++)
{
Asteroidi[i].Draw(spriteBatch);
}
//aggiorno la visualizzazione della risora di tipo fuoco
for (int i = 0; i < spari.Count; i++)
{
spari[i].Draw(spriteBatch);
}
//aggiorno la visualizzazione della risorsa esplosioni.
for (int i = 0; i < Esplosioni.Count; i++)
{
Esplosioni[i].Draw(spriteBatch);
}
//aggiorno la visualizzazione
player.Draw(spriteBatch);
//termine del ridisegno
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Ora non ci resta che testare, vedremo le esplosioni come in figura 2
Figura 2
Conclusioni
In questa parte si è visto come gestire l’ostacolo e come applicare un determinato effetto, proprio come può essere l’esplosione di un oggetto.
Tramite la parola download potete scaricare il file d’esempio.
Download