Space shooter : Aron & The Aliens

Chapitre 25 : Les collisions (4ème partie) !

 

Tutoriel présenté par : Robert Gillard (Gondulzak)
Date d'écriture : 9 novembre 2014

Dernière mise à jour : 22 novembre 2015

 

      Préliminaires

   Dans notre précédent chapitre, nous avons implémenté les collisions astronef / astéroïdes, super fireballs / astéroïdes ainsi que la gestion de nos satellites et leurs collisions avec l'ennemi, et plus précisément les collisions missiles ennemis / astéroïdes. wink

   Nous nous sommes penchés sur les effets dévastateurs de la rencontre de l'astronef avec un astéroïde mais aussi sur la puissance de feu des super fireballs capables de désintégrer ces dangers flottants. cheeky Nous avons également pu nous apercevoir des conséquences de la destruction d'un satellite. Et ceci terminait donc tout ce qui était en rapport avec les déplacements de notre astronef dans la fenêtre de combat. angel

   Auparavant encore, nous avions créé les classes «SpaceForce» et «FarEnemy» qui ajoutaient des astronefs verts de la MSF et des ovnis ennemis, mais qui ne faisaient que se croiser dans la fenêtre de combat. Or j'ai estimé que si ces intrus apparaissaient dans la fenêtre de combat, c'était pour combattre ou alors ils n'avaient rien à y faire ! angry

   Ceci étant dit, nous allons donc les faire combattre entre eux ! indecision Mais je vous signale de suite qu'ils ne seront pas mis en interaction avec les autres éléments du jeu et l'astronef n'aura pas à s'en préoccuper du tout, pour autant que le joueur puisse faire abstraction de ce combat d'arrière-plan. laugh

   Dans ce nouveau chapitre, nous allons donc armer ces nouveaux intervenants en implémentant deux nouvelles classes, les classes «Laser» et «MsfFireball» (les lasers seront tirés par les ovnis et les fireballs par la MSF).

   Nous commencerons en premier par la classe «Laser». wink  

Le projet « AronAndTheAliens15 »

 

   Reprenez votre projet précédent ou créez-en un nouveau que vous nommerez «AronAndTheAliens15» (reportez-vous aux chapitres précédents en ce qui concerne les manipulations à réaliser).

 

 

     1 – La classe Laser : Le code

     Nous allons maintenant créer une nouvelle classe, la classe «Laser». Remplacez le code existant par le code suivant :

 
#region Description
//MERUVIA XNA TUTORIALS
//AronAndTheAliens15
//Jeu : Aron and the aliens
//Les collisions (partie V) - Ovnis VS Msf
//Collisions lasers / msf et fireballs / ovnis
//Fichier : Laser.cs
//Last update : 07/11/2014
#endregion
 
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
 
namespace AronAndTheAliens15
{
class Laser
{
#region Déclaration des variables de la classe Laser
// Largeur de la fenêtre de jeu
public int gameWidth;
 
// La texture qui représente le laser
public Texture2D Texture;
 
// Position du laser par rapport au coin supérieur gauche de l'écran
public Vector2 Position;
 
//Points de santé d'un laser
public int Health;
 
// Etat du laser
public bool Active;
 
// Dommages causés par le laser à la Space Force
public int Damage;
 
// Vitesse du laser
float laserMoveSpeed;
#endregion Déclaration des variables de la classe Laser
 
 
#region Propriétés
// Retourne la largeur du laser
public int frameWidth
{
get { return Texture.Width; }
}
 
// Retourne la hauteur du laser
public int frameHeight
{
get { return Texture.Height; }
}
#endregion Propriétés
 
 
#region Fonction d'initialisation
public void Initialize(Texture2D texture, Vector2 position)
{
Texture = texture;
Position = position;
 
// Actif en début de jeu
Active = true;
 
// dommages causées par le laser au space force
// Un laser désintègre un Appareil MSF
Damage = 100;
 
// la fenêtre de jeu est large de 800 pixels
gameWidth = 800;
 
//Les points de santé d'un laser déterminent sa résistance au choc
Health = 5;
 
// Vitesse du laser
laserMoveSpeed = 25.0f;
}
#endregion Fonction d'initialisation
 
 
#region Fonction de mise à jour
public void Update()
 
// Un laser se déplace toujours vers la droite
{
 
Position.X += laserMoveSpeed;
 
// On désactive le laser s'il sort de l'écran ou s'il a frappé un MSF
if ((Position.X > gameWidth + frameWidth) || (Health <= 0))
Active = false;
}
#endregion Fonction de mise à jour
 
 
#region Fonction de dessin
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position, null, Color.White, 0f,
new Vector2(frameWidth, frameHeight), 0.5f, SpriteEffects.None, 0f);
}
#endregion Fonction de dessin
}
} 

 

   Cette classe ne présente pas de difficultés. Remarquez simplement la grande vitesse donnée à la variable laserMoveSpeed (25.0f) et l'échelle 1/2 appliquée à la texture du laser dans la fonction Draw().

   Les combats se déroulant en arrière-plan il est normal de diminuer la surface des textures. wink

   La classe «MsfFireball» étant pratiquement identique à la classe «Laser», nous allons l'écrire de suite.

   Comme cela nous pourrons faire les ajouts dans le fichier AronAndTheAliens15 pour nos deux classes en même temps. angel

 

       2 – La Classe MsfFireball : le code 

 
#region Description
//MERUVIA XNA TUTORIALS
//AronAndTheAliens15
//Jeu : Aron and the aliens
//Les collisions (partie V) - Ovnis VS Msf
//Collisions lasers / msf et fireballs / ovnis
//Fichier : MsfFireball.cs
//Last update : 07/11/2014
#endregion
 
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
 
namespace AronAndTheAliens15
{
class MsfFireball
{
#region Déclarations des variables de la classe msfFireballs
// Image représentant le fireball
public Texture2D Texture;
 
// Position du fireball relatif au coin supérieur gauche de l'écran
public Vector2 Position;
 
// Points de santé d'un MSF fireball
public int Health;
 
// Etat du fireball
public bool Active;
 
// Dommage que peut infliger le MSF fireball à un ennemi
public int Damage;
 
// Vitesse du fireball
float msfFireballMoveSpeed;
#endregion Déclarations des variables de la classe msfFireballs
 
 
#region Propriétés
// Retourne la largeur du fireball
public int frameWidth
{
get { return Texture.Width; }
}
 
// Retourne la hauteur du fireball
public int frameHeight
{
get { return Texture.Height; }
}
#endregion Propriétés
 
 
 
 
#region Fonction d'initialisation
public void Initialize(Texture2D texture, Vector2 position)
{
Texture = texture;
Position = position;
 
// Actif au départ du jeu
Active = true;
 
//Les points de santé d'un MSF fireball déterminent sa résistance au choc
Health = 5;
 
// Quantité de dommages causés par un MSF fireball à l'ennemi
// Les PV d'un ovni étant de 75, 1 MSF fireball détruit un ennemi
Damage = 75;
 
// Vitesse d'un fireball
msfFireballMoveSpeed = 3.0f;
 
}
#endregion Fonction d'initialisation
 
 
#region Fonction de mise à jour
public void Update()
{
// Un MSF fireball se déplace toujours de la droite vers la gauche
Position.X -= msfFireballMoveSpeed;
 
// On désactive le fireball s'il sort de l'écran
// ou s'il s'est écrasé sur un ovni
if ((Position.X + Texture.Width < 0) || (Health <= 0))
Active = false;
}
#endregion Fonction de mise à jour
 
 
#region Fonction de dessin
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position, null, Color.White, 0f,
new Vector2(frameWidth / 2, (frameHeight / 2) - 10), 0.5f,
SpriteEffects.None, 0f);
}
#endregion Fonction de dessin
}
} 
 

   Et là non plus, il n'y a rien de spécial dans cette classe que vous n'ayez déjà vu, donc nous pouvons maintenant compléter notre fichier AronAndTheAliens15.cs. angel


   3 – Fichier AronAndTheAliens15.cs

  Dans notre classe «AronAnTheAliens15», en dessous de la région SATELLITE DECLARATIONS DATA'S, entrez les deux régions suivantes :

 

#region LASERS DECLARATIONS DATA'S
 
Texture2D laserTexture; //Texture lasers
 
List<Laser> lasers; //Les lasers seront gérés dans une liste
 
// La fréquence à laquelle apparait un laser
TimeSpan laserSpawnTime;
TimeSpan previouslaserSpawnTime;
 
#endregion LASERS DECLARATIONS DATA'S
 
 
#region MSF FIREBALL DECLARATIONS DATA'S
 
/* Inutile de déclarer une texture pour les MsfFireballs,
nous utiliserons la texture2D superFireballTexture */
List<MsfFireball> msfFireballs; //Les SF fireballs seront gérés dans une liste
 
// La fréquence à laquelle apparait un MSF fireball
TimeSpan msfFireballSpawnTime;
TimeSpan previousMsfFireballSpawnTime;
 
#endregion MSF FIREBALL DECLARATIONS DATA'S 

 

   Ensuite, dans la région HITBOX COLLISIONS DECLARATIONS, ajoutez les lignes suivantes où nous déclarons les hitboxes pour les collisions d'arrière-plan :

 

Rectangle laserBox; //hitbox pour laser
Rectangle msfFireballBox; //hitbox pour MSF fireball
Rectangle msfBox; //hitbox MSF
Rectangle ovniBox; //hitbox far Enemy 

 

   Nous nous rendons maintenant dans la fonction Initialize(). Et dans celle-ci, juste en dessous de :

 

En-dessous de :
satellit = new Satellite();
Ajoutez :
//Instanciation de la liste Laser
lasers = new List<Laser>();
 
//Instanciation de la liste MSF fireball
msfFireballs = new List<MsfFireball>(); 

 

   Et à la suite des lignes qui initialisent les différents Timers à 0, ajoutez les lignes suivantes :

 
previouslaserSpawnTime = TimeSpan.Zero;
previousMsfFireballSpawnTime = TimeSpan.Zero; 

 

  On continue à l'intérieur de la fonction Initialize(). En dessous de la ligne :

 
En-dessous de :
satelliteSpawnTime = TimeSpan.FromSeconds(60.0f);
Ajoutez :
//Détermine à quelle fréquence un laser sera tiré
laserSpawnTime = TimeSpan.FromSeconds(1.5);
 
//Détermine à quelle fréquence un MSF fireball sera tiré
msfFireballSpawnTime = TimeSpan.FromSeconds(1.0);

 

   Nous passons maintenant à la fonction LoadContent(). A la suites des lignes de la région TEXTURES (Textures sprites), ajoutez :


laserTexture = Content.Load<Texture2D>("Textures/Laser38x11"); 

 

   Texture que vous n'oublierez pas d'ajouter dans votre dossier «Textures» si ce n'est déjà fait (vous pouvez la télécharger avec le projet ci-dessus, pour rappel). cheeky Et pour ce qui est de la texture du MSF fireball, j'ai signalé un peu plus haut que nous utiliserions la texture SuperFireball qui existe déjà dans notre dossier. wink

   Maintenant, à la suite de SATELLITE UPDATE LIST FUNCTION, entrez les quatre régions suivantes :

 
#region ADD LASER TO LIST
private void AddLaser(Vector2 position)
{
Laser laser = new Laser();
laser.Initialize(laserTexture, position);
 
lasers.Add(laser);
}
#endregion ADD LASER TO LIST
 
 
#region LASER UPDATE LIST FUNCTION
private void UpdateLasers(GameTime gameTime)
{
// Mise à jour des lasers
for (int i = lasers.Count - 1; i >= 0; i--)
{
lasers[i].Update();
 
if (lasers[i].Active == false)
{
// Si inactif et PV <= 0
if (lasers[i].Health <= 0)
lasers.RemoveAt(i);
}
}
}
#endregion LASER UPDATE LIST FUNCTION
 
 
#region ADD MSF FIREBALL TO LIST
private void AddMsfFireball(Vector2 position)
{
MsfFireball msfFireball = new MsfFireball();
msfFireball.Initialize(superFireballTexture, position);
 
msfFireballs.Add(msfFireball);
}
#endregion ADD MSF FIREBALL TO LIST
 
 
 
#region MSF FIREBALL UPDATE LIST FUNCTION
private void UpdateMsfFireballs(GameTime gameTime)
{
// Mise à jour des fireballs
for (int i = msfFireballs.Count - 1; i >= 0; i--)
{
msfFireballs[i].Update();
 
if (msfFireballs[i].Active == false)
{
// Si inactif et PV <= 0
if (msfFireballs[i].Health <= 0)
msfFireballs.RemoveAt(i);
}
}
}
#endregion MSF FIREBALL UPDATE LIST FUNCTION 

 

   Il s'agit simplement des fonctions d'ajout et de mise à jour des lasers et des MSF fireballs. wink

   Et nous allons maintenant implémenter les collisions entre les tirs des ovnis et de la MSF.


      Collisions laser / MSF et MSF fireball / ovni

   A la suite de la région COLLISIONS SATELLITE / MISSILS, entrez les deux régions suivantes :

 
#region COLLISIONS LASER / MSF
// Collisions Laser - Msf
for (int i = 0; i < lasers.Count; i++)
{
for (int j = 0; j < spaceforce.Count; j++)
{
// Creation des hitboxes pour déterminer une collision laser / msf
laserBox = new Rectangle((int)lasers[i].Position.X -
lasers[i].frameWidth / 2, (int)lasers[i].Position.Y -
lasers[i].frameHeight / 2, lasers[i].frameWidth, lasers[i].frameHeight);
 
msfBox = new Rectangle((int)spaceforce[j].Position.X -
spaceforce[j].frameWidth / 2,
(int)spaceforce[j].Position.Y - spaceforce[j].frameHeight / 2,
spaceforce[j].frameWidth, spaceforce[j].frameHeight);
 
// Determine si un MSF est entré en collision avec un laser
if (msfBox.Intersects(laserBox))
{
lasers[i].Active = false;
// Ajout d'une animation explosion
AddExplosion(spaceforce[j].Position, gameTime);
spaceforce[j].Health = 0;
}
 
}
}
#endregion COLLISIONS LASER / MSF
 
 
 
 
#region COLLISIONS MSF FIREBALL / OVNI
// Collisions msfFireball - ovnis
for (int i = 0; i < msfFireballs.Count; i++)
{
for (int j = 0; j < farEnemies.Count; j++)
{
// Creation des hitboxes pour déterminer une collision
// msfFireball / ovnis
msfFireballBox = new Rectangle((int)msfFireballs[i].Position.X -
msfFireballs[i].frameWidth / 2, (int)msfFireballs[i].Position.Y -
msfFireballs[i].frameHeight / 2, msfFireballs[i].frameWidth,
msfFireballs[i].frameHeight);
 
ovniBox = new Rectangle((int)farEnemies[j].Position.X -
farEnemies[j].frameWidth / 2,
(int)farEnemies[j].Position.Y - farEnemies[j].frameHeight / 2,
farEnemies[j].frameWidth, farEnemies[j].frameHeight);
 
// Determine si un ovni est entré en collision avec un msfFireball
if (ovniBox.Intersects(msfFireballBox))
{
msfFireballs[i].Active = false;
farEnemies[j].Health = 0;
// Ajout d'une animation explosion
AddExplosion(farEnemies[j].Position, gameTime);
}
 
}
}
#endregion COLLISIONS MSF FIREBALL / OVNI 

 

   Ces deux régions sont simples à comprendre. Dans la région COLLISIONS LASER / MSF, nous créons les hitboxes des lasers et des astronefs de la MSF et pour chaque laser tiré, on vérifie s'il est entré en collision avec un astronef et si oui, on enlève le laser de la liste en mettant sa variable Active à false et en enlevant tous les points de santé de l' astronef de la MSF, celui-ci étant immédiatement détruit. cheeky

   Et nous voyons que l'on utilise la même logique en ce qui concerne les collisions MSF fireball / ovnis. wink

Remarque : Pour ce qui est des tirs entre la MSF et les ovnis j'ai suivi une approche quelque peu différente de celle effectuée entre Aron et les sorcières. En effet, les ovnis et les astronefs de la MSF effectuent des tirs en continu, ceux-ci étant cadencés par les valeurs contenues dans les variables laserSpawnTime et msfFireballSpawnTime, initialisées dans la fonction Initialize()

   Rendons-nous maintenant dans la région FAR ENEMIES UPDATE LIST FUNCTION, où, dans la mise à jour des ennemis lointains, et en dessous de la ligne : 

 
En-dessous de :
farEnemies[i].Update(gameTime);
Ajoutez :
// Ne tire que dans l'intervalle de temps accordé
if (gameTime.TotalGameTime - previouslaserSpawnTime > laserSpawnTime)
{
//Réinitialisation du temps
previouslaserSpawnTime = gameTime.TotalGameTime;
 
//Tir d'un laser
AddLaser(farEnemies[i].Position + new Vector2(farEnemies[i].frameWidth,
farEnemies[i].frameHeight / 3 - 5));
}

 

    Ensuite, dans la région SPACE FORCE UPDATE LIST FUNCTION, où, dans la mise à jour des space force, et en dessous de la ligne :

 

En-dessous de :
spaceforce[i].Update(gameTime);
Ajoutez :
// Ne tire que dans l'intervalle de temps accordé
if (gameTime.TotalGameTime - previousMsfFireballSpawnTime >
msfFireballSpawnTime)
{
//Réinitialisation du temps
previousMsfFireballSpawnTime = gameTime.TotalGameTime;
 
//Tir d'un fireball
AddMsfFireball(spaceforce[i].Position - new
Vector2(spaceforce[i].frameWidth / 2, 0));
}
 

   Il nous faut maintenant compléter la fonction Update(). Et dans cette fonction, en dessous de la ligne :

 
En-dessous de :
UpdateSatellite(gameTime);
Ajoutez :
//Mise à jour des lasers
UpdateLasers(gameTime);
 
//Mise à jour des MSF fireballs
UpdateMsfFireballs(gameTime);
 
   Et il ne nous reste plus qu'à compléter notre fonction Draw() pour terminer ce chapitre. En dessous du code qui dessine les ennemis lointains (ovnis), entrez les lignes suivantes :
 
// Dessine les lasers
for (int i = 0; i < lasers.Count; i++)
{
lasers[i].Draw(spriteBatch);
}

 

   Et en-dessous du code qui dessine la space force, entrez les lignes suivantes :

 

// Dessine les MSF fireballs
for (int i = 0; i < msfFireballs.Count; i++)
{
msfFireballs[i].Draw(spriteBatch);
} 

 

   Voilà, ce chapitre est terminé. angel

   Si vous compilez le projet, vous pourrez voir la MSF combattre les ovnis à l'arrière plan et je vous en montre d'ailleurs un screenshot ci-dessous. wink

   Dans le prochain chapitre (et le dernier de notre jeu ! angel), j'ajouterai la musique et les sons, ce qui va rendre le projet bien plus vivant. cool

  J'implémenterai également une gestion des statistiques de combat qui seront affichées lors de chaque crash de l'astronef. Je procéderai également à quelques améliorations au niveau du code et permettrai le téléchargement du projet complet en français, ce qui devrait en réjouir plus d'un ! laugh

A l'arrière-plan : lasers VS fireballs

   A bientôt pour le chapitre 26 (Musique et Sounds Fx). wink

         Gondulzak.

 

 

 

Connexion

CoalaWeb Traffic

Today236
Yesterday297
This week1033
This month4707
Total1743914

26/04/24