Mon premier jeu Part 3
Désole pour l’attente, mais j’ai commencé mon stage il y a deux semaines et j’ai eu pas mal de taff. Nous voila donc parti pour la troisième partie de ce tutorial, et nous allons maintenant implémenter un élément oh combien important dans un jeu vidéo : les méchants ^^. Dans le cas du froger ce sont juste des ennemis qui déboulent de chaque cote de l’écran pour essayer de vous écraser, mais nous allons essayer de faire en sorte de varier leur vitesse afin de ne pas faire un jeu trop ennuyant.
C’est parti, tout d’abord créer votre classe ennemie, je ne vous réexplique pas comment faire, je pense que vous avez compris (et sinon retournez bosser les tutos précédant petit garnement ^^). Les principales nouveautés vont être tout d’abord que les ennemis se déplaceront d’eux-mêmes et oui ce sont des sales bêtes ^^.
Commençons par nous attaquer au constructeur de notre classe ennemy il sera de la forme suivante :
public Ennemy(Froger game, GraphicsDeviceManager graphics, ContentManager content, int coordx, int coordy, float vit, string dir)
: base(game)
{
this.game = game;
this.m_graphics = graphics;
this.m_content = content;
pospers.Y = coordy;
pospers.X = coordx;
direction = dir;
vitesse = vit / 2;
if (dir == "g")
{
posInit.X = m_graphics.PreferredBackBufferWidth;
}
if (dir == "d")
{
vitesse = (-vitesse);
posInit.X = 0;
}
}
Les principales différences avec le constructeur de notre classe héros sont les suivantes. Tout d’abord, nous appelons notre classe avec deux coordonnées qui seront les coordonnées de départ de notre ennemi ainsi nous pourrons créer une multitude d’ennemis avec un seul constructeur de classes sans qu’ils partent tous du même endroit, ensuite nous avons un entier représentant la vitesse avec laquelle se déplacera l’ennemi et enfin une chaine de caractère permettant de savoir si notre ennemi se déplacera vers la gauche ou vers la droite.
Passons maintenant au déplacement de nos ennemis, comme nous avons vu précédemment la méthode update est la méthode qui nous permet de mettre a jour nos variables en fonction du temps, ainsi nous allons faire en sorte que les coordonnées soit mise a jour en fonction de la vitesse que nous avons choisie. Nous allons aussi tester si nos ennemis sortent de l’écran, si c’est le cas nous les renvoyons a leur position de départ ainsi il y aura toujours des ennemis pour vous barrez le chemin niark niark ^^. Voici comment faire :
pospers.X = pospers.X - (vitesse);
if (direction == "g")
{
if (pospers.X < 0 - SpriteWidth)
pospers.X = posInit.X;
}
if (direction == "d")
{
if (pospers.X > m_graphics.PreferredBackBufferWidth + SpriteWidth)
pospers.X = posInit.X;
}
Nous allons aussi animer nos ennemis, mais comme la méthode est la même que précédemment je ne vais pas vous réexpliquer au pire si vous ne voyez pas comment faire vous pouvez vous aider de l’archive à la fin du post.
N’oubliez pas d’initialiser vos ennemis, vous pourrez voir dans l’archive que comme il y en a beaucoup j’ai utilisé une fonction pour les regrouper, en y repensant cette méthode n’est pas trés propre vous pouvez utiliser une liste d’ennemi ca sera plus efficace.
Je ne ferais pas de tuto pour le déplacement des rondins de bois vu que c’est la même méthode je vous mets donc directement le code dans l’archive finale, la classse les représentant est la classe Wood.
Je sais que ce tuto est rapide, mais je ne pense pas qu’il soit nécessaire de tout reprendre à chaque fois. Et si vous avez des questions,s’il y a des choses pas claires, n’hésitez pas à demander les commentaires sont la pour ça.

décembre 8th, 2008 à 5:21
Merci pour les tuto.
)
Grace a eux maintenant j’ai assimilé e qui me poser le plus gros probleme avec le codage XNA: comment bien decouper le code entre les parti loadcontent, draw, update… (et aussi codé en objet
Bien que le code de ce 3eme tuto fonctionne correctement j’aurai une petite remarque: il faut evité d’utilisé les fonctions
spritePerso = new SpriteBatch(m_graphics.GraphicsDevice); et
txtPerso = m_content.Load(”Textures/ennemy/monstre1″);
dans un classe destiné a etre appeler plusieurs fois. Si dans un projet de ce type cela ne pose pas de probleme, si on utilise cette methode pour gerer des éléments en tres grand nombre (par exemple les centaines de bullets recouvrant l’ecran d’un Shoot-em up) on fini par saturer la memoire vidéo meme en detruisant correctement les objet apres utilisation.
décembre 8th, 2008 à 5:43
Tu as tout a fait raison puisqu’on recharge plusieurs fois la même texture ce qui est completement inutile. Par contre je ne vois pas comment faire autrement pour l’instant, je vais y reflechir et je vous tiens au courant si je trouve quelque chose.
décembre 8th, 2008 à 6:55
j’aurai voulu posté ca dans le forum pour + de lisibilité mais pas moyen de poster dessus
pour resoudre le probleme tu peut divisé ta classe Ennemy en 2 classe
classe Ennemy.cs:
namespace Frogger
{
///
/// classe des ennemis de frog les immondes boules qui tournent
///
class Ennemy : DrawableGameComponent
{
Froger game;
GraphicsDeviceManager m_graphics;
ContentManager m_content;
Texture2D txtPersoD;
Texture2D TxtPersoG;
SpriteBatch spritePerso;
List ennemyItem = new List();
public Ennemy(Froger game, GraphicsDeviceManager graphics, ContentManager content)
: base(game)
{
this.game = game;
this.m_graphics = graphics;
this.m_content = content;
}
public override void Initialize()
{
spritePerso = new SpriteBatch(m_graphics.GraphicsDevice);
base.Initialize();
ennemyItem.Add ( new Ennemy(this.graphics.PreferredBackBufferWidth, this.graphics.PreferredBackBufferHeight - 150, 1, “g”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth, this.graphics.PreferredBackBufferHeight - 275, 3, “d”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth, this.graphics.PreferredBackBufferHeight - 525, (float)2.5, “d”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth, this.graphics.PreferredBackBufferHeight - 400, 2, “g”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 200, this.graphics.PreferredBackBufferHeight - 150, 1, “g”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 200, this.graphics.PreferredBackBufferHeight - 275, 3, “d”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 200, this.graphics.PreferredBackBufferHeight - 525, (float)2.5, “d”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 200, this.graphics.PreferredBackBufferHeight - 400, 2, “g”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 400, this.graphics.PreferredBackBufferHeight - 150, 1, “g”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 400, this.graphics.PreferredBackBufferHeight - 275, 3, “d”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 400, this.graphics.PreferredBackBufferHeight - 525, (float)2.5, “d”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 400, this.graphics.PreferredBackBufferHeight - 400, 2, “g”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 600, this.graphics.PreferredBackBufferHeight - 150, 1, “g”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 600, this.graphics.PreferredBackBufferHeight - 275, 3, “d”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 600, this.graphics.PreferredBackBufferHeight - 525, (float)2.5, “d”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 600, this.graphics.PreferredBackBufferHeight - 400, 2, “g”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 800, this.graphics.PreferredBackBufferHeight - 150, 1, “g”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 800, this.graphics.PreferredBackBufferHeight - 275, 3, “d”));
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 800, this.graphics.PreferredBackBufferHeight - 525, (float)2.5, “d”);
ennemyItem.Add ( new Ennemy( this.graphics.PreferredBackBufferWidth - 800, this.graphics.PreferredBackBufferHeight - 400, 2, “g”));
}
protected override void LoadContent()
{
txtPersoD = m_content.Load(”Textures/ennemy/monstre1″);
txtPersoG = m_content.Load(”Textures/ennemy/monstre2″);
base.LoadContent();
}
public override void Draw(GameTime gameTime)
{
DrawPerso(gameTime);
base.Draw(gameTime);
}
void DrawPerso(GameTime gametime)
{
spritePerso.Begin();
foreach (EnnemyItem A in ennemyItem)
if (A.dir == D)
{
spritePerso.Draw(txtPersoD, A.DestRect, A.SourceRect, Color.White);
}
if (A.dir == G)
{
spritePerso.Draw(txtPersoG, A.DestRect, A.SourceRect, Color.white);
}
spritePerso.End();
}
}
Public override void Update(GameTime gametime)
{
foreach (EnnemyItem A in ennemyItem)
{
A.Update (gametime);
}
}
}
décembre 8th, 2008 à 6:56
puis classe EnnemyItem.cs
namespace Frogger
{
class EnnemyItem
{
private Vector2 pospers;
private Vector2 posInit;
Rectangle rectCol;
float vitesse;
string direction;
//test anim
float Timer = 0f;
float Interval = 1000f / 10f;
int FrameCount = 3;
int CurrentFrame = 0;
int SpriteWidth = 37;
int SpriteHeight = 40;
Public Rectangle SourceRect;
Public Rectangle DestRect;
public EnnemyItem(int coordx, int coordy, float vit, string dir)
{
pospers.Y = coordy;
pospers.X = coordx;
direction = dir;
vitesse = vit / 2;
if (dir == “g”)
{
posInit.X = m_graphics.PreferredBackBufferWidth;
}
if (dir == “d”)
{
vitesse = (-vitesse);
posInit.X = 0;
}
}
public void Update(GameTime gameTime)
{
pospers.X = pospers.X - (vitesse);
if (direction == “g”)
{
if (pospers.X m_graphics.PreferredBackBufferWidth + SpriteWidth)
pospers.X = posInit.X;
}
Timer += (float)gameTime.ElapsedGameTime.TotalMilliseconds;
if (Timer > Interval)
{
CurrentFrame++;
if (CurrentFrame > FrameCount - 1)
{
CurrentFrame = 0;
}
Timer = 0f;
}
SourceRect = new Rectangle(CurrentFrame * SpriteWidth, 0, SpriteWidth, SpriteHeight);
DestRect = new Rectangle((int)pospers.X, (int)pospers.Y, 37, 40);
rectCol = new Rectangle((int)pospers.X, (int)pospers.Y, 37, 40);
}
décembre 8th, 2008 à 7:02
dans la classe froger.cs tu initialise juste la classe Ennemy.cs (comme pour les classe hero et level)
ainsi tu a tes 24 objet avec une seul initialisation du spritebatch et que 2 content.load.
il est possible qu’il ai des erreur dans le code vu qu’il a été ecrit via le bloc-note (j’utilise pas le meme Pc pour coder et aller sur internet)
décembre 8th, 2008 à 7:19
je vient de remarquer que ce qui est ecrit entre un symbole “inferieur à” et “supérieur à” disparait dans les posts
pour la declaration de la liste il faut evidement ecrire
List “symbole inferieur à” EnnemyItem “symbole superieur à” ennemyItem = new List “inferieur” EnnemyIyem “superieur” ();
corrigez aussi les Content.load
décembre 8th, 2008 à 8:45
En effet pas bete apres faut voir si ca ne gene pas avec la gestion des collisions. Merci en tout cas. Sinon pour le forum nous allons essayer de regler ca vite, mais j’ai beaucoup de probleme de temps en ce moment et pourtant j’ai des tonnes darticles de presque pret comme la gestion du reseau et du stockage. Il me faudrait des journée de 48 heure ^^.
décembre 9th, 2008 à 12:04
pour les test de collisions devrait y avoir aucun probleme du moment que le tableau/la liste (j’ai une enorme preférence pour la liste: pas besion de l’initialisé avec une taille precise, plus pratique pour ajouter/retirer des elément et pas de risque d’avoir des cases vide qui traine et comme XNA n’accepte pas que game.components.Add ajoute plus d’un unique element null) ou sont stocker les EnnemyItem est déclarer public ou a un accesseur (merci au passage de n’avoir apris a quoi sert le Get; Set; ca fessait un moment que je bloqué dessus, c bien d’etre bac+2 en prog mais j’aurai vraiment pas du passer toute mes heures de cours a jouer a mame et counter strike
)
janvier 28th, 2009 à 1:24
Zappez ce message, si un “bonjour” de la part de quelqu’un que vous ne connaissez pas, ne vous intéresse guère!
Salut tout le monde!!
J’écris juste parce que j’ai la facheuse habitude de squatter les forums pour glâner des infos tel un malpropre et puis c’est tout.
Mais comme, cette fois-ci, avec le XNA, je suis parti pour un bout de temps et qu’en plus, j’escompte apprendre très très vite, je tenais à saluer le travail investi sur ce site et tous ceux qui, développeurs confirmés comme débutants, s’entraident!!
Voilà!!
Ps: la prochaine fois que vous entendrez parler de moi, ce sera pour essayer d’aider une personne en détresse ey no juste pour raconter des bêtises… du moins je l’espère.
janvier 28th, 2009 à 3:03
Bienvenue sur le site, et content que ca te plaise.
Surtout ne te formalise pas s’il n’y a pas assez de mise a jour, je bosse sur plein de tutos mais aussi plein d’autres truc en meme temps donc ce n’est pas facile :p.
N’hesite pas a aller sur le forum aussi.
A tres bientot j’espere.
novembre 11th, 2009 à 7:28
Bien le bonjour à toi, raptorpg !
Tout d’abord, un grand bravo et merci pour ton site ! C’est quelque chose de vouloir monter un site pour assister les internautes en quêtes de nouvelles choses à faire de leurs mimines, c’en est une autre d’effectivement mener à bien le projet, et cela semble être ton cas !
J’ai déjà un peu d’expérience dans le domaine du developpement de jeux vidéo (PAlib pour Nintendo DS, SDL pour PC), et c’est vrai que la librairie XNA associée avec la plateforme .Net offre vraiment des possibilités énormes, ça fait donc plaisir de voir des indications, des conseils, pour savoir par quel bout prendre tout ce kit de développement, merci pour cela donc !
Pour en revenir précisément au sujet de l’article, j’aurai simplement une question : dans ton code, tu utilises un objet de type Rectangle “rectCol”, mais je ne comprends pas à quoi sert-il, peux-tu m’éclairer sur ce sujet ?
Bravo et merci encore,
Bonne continuation !
novembre 11th, 2009 à 9:18
Autant que je me souvienne, ca fait longtemps^^. Il me sert a gerer les collisions entre les objets. mais on ne gere pas la collision dans cet exemple, il doit donc s’agir dune erreur de copie de ma part depuis le code original, desole et merci d’avoir vu l’erreur ^^.
novembre 12th, 2009 à 12:06
D’acodac, après coup, j’ai aussi pensé à ça, merci pour ta réponse rapide !
(Et pas de souci, tout le monde fait des erreurs, ça n’enlève rien à la qualité de ton travail !)
avril 2nd, 2010 à 12:08
Bonjour, je viens d’essayer ton code, cependant la grenouille ne s’affiche pas…
J’ai bien telecharger tes sources, et j’ai le meme probleme… tout le reste marche parfaitement.
logiciel utilise: Microsoft Visual Studio 2010 Express for windows phone.
avril 2nd, 2010 à 12:09
En effet c’est bizarre et ca vient peut etre du fait que tu utilises xna 4.0.
je vais regarder ca des que je rentre de voyage, je n’ai pas de quoi tester avec moi. je pense pouvoir te donner une reponse mardi ou mercredi ^^.