Programmation graphique
Chapitre 4 : Les Sprites : Animation simple
Tutoriel présenté par : Robert Gillard (Gondulzak)
Publication : 28 janvier 2014
Dernière mise à jour : 16 novembre 2015
Préliminaires
Dans notre précédent chapitre, nous avons vu différentes manières de déplacer des sprites. Cependant ceux-ci étaient statiques. Mais que serait un jeu vidéo sans animation ?
Premièrement nous allons donc voir comment animer un sprite. Ensuite, dans le chapitre suivant, nous verrons comment déplacer un sprite animé en l'intégrant dans des classes et nous terminerons notre étude de l'animation dans le chapitre 6 avec des concepts d'accélération appliquée à l'animation.
Jusqu'à présent tous nos projets étaient implémentés dans la classe Game1, mais nous ne pouvons pas entrer tout le code d'un projet quelque peu important dans une seule classe. Aussi, puisque le but final de cette série de tutoriels est de réaliser un jeu, nous allons, après un premier exemple, apprendre à utiliser les classes sous la plateforme Xna et vous allez très vite vous rendre compte de l'importance de ce puissant outil.
Animer un sprite
a – Un programme élémentaire d'animation :
Je ne vais pas ici réecrire la théorie entière sur la découpe des « tilesets ». Je vous renvoie sur ce sujet, à l'excellent tuto de Jay.
Je ne vous apprendrai rien en vous disant que nous avons besoin d'une feuille de sprites et de notre IDE préféré... Nous utiliserons pour ce faire notre ami «Aron» représenté dans la feuille de sprites «Aronwalk.png» et nous allons le faire... marcher sur place (dans un premier temps).
Nous allons donc, comme à notre habitude, créer un nouveau projet Xna que nous appellerons « AronWalk ».
Et pendant que vous y êtes, afin de ne pas l'oublier, vous pouvez faire un clic droit sur AronWalkContent(Content) dans la fenêtre de l'explorateur de solutions à droite et ajouter l'élément existant « Aronwalk.png » à votre projet.
Ok, on suit la procédure habituelle, premièrement nous déclarons nos variables. Dans la classe Game1, en dessous de SpriteBatchspriteBatch; , entrez le code suivant :
// Texture d'un sprite Texture2D text_Aron; //Données concernant la feuille de sprites Point frameSize; Point currentFrame; Point sheetSize; public Vector2 aronPosition; public SpriteEffects spriteEffet; Color backgroundColor; // Données concernant le framerate int timeSinceLastFrame = 0; int millisecondsPerFrame = 150;
Parcourons rapidement ces variables, nous nous aperçevons que les données concernant la feuille de sprites, n'utilisent plus le type Vector2 mais que celui-ci est remplacé par le type Point.
Point est une structure qui, à l'instar de Vector2, encapsule les coordonnées 2D d'une variable mais qui ne possède pas le même nombre de propriétés et de méthodes publiques que cette dernière.
Nous allons initialiser ces variables un peu plus loin.
Nous déclarons aussi une variable de type SpriteEffects car la feuille de sprites Aronwalk.png présente notre petit bonhomme regardant vers la gauche alors que nous le ferons marcher vers la droite dans cet exemple et nous changerons aussi la couleur du fond à l'aide de la variable backgroundColor.
Concernant le framerate, timeSinceLastFrame représente le temps écoulé depuis la frame précédente et millisecondsPerFrame est le nombre de millisecondes pendant laquelle cette frame est affichée lors d'un cycle.
Ceci étant acquis, nous passons à l'initialisation. Supprimez la fonction Initialize() et remplacez-la par celle-ci :
//Initialisation protected override void Initialize() { // TODO: Ajoutez la logique d'initialisation ici frameSize = new Point(40, 50); //Respectivement largeur et hauteur d'une frame currentFrame = new Point(0, 0); //Origine de la première frame sheetSize = new Point(8, 1); /* Nombre de frames/ligne et nombre de colonnes dans la feuille de sprites */ aronPosition.X = 250; aronPosition.Y = 150; //Retourne le sprite horizontalement spriteEffet = SpriteEffects.FlipHorizontally; backgroundColor = new Color(200, 200, 200); //Couleur du fond base.Initialize(); }
Rien de difficile dans cette fonction, tout est commenté dans le code. Bon, passons à notre fonction LoadContent().
En dessous de spriteBatch = new SpriteBatch(GraphicsDevice); , ajoutez la ligne suivante :
text_Aron = Content.Load("Aronwalk");
Ce qui aura pour effet de charger notre feuille de sprites Aronwalk.png dans notre variable text_Aron de type Texture2D.
Vous pouvez ensuite supprimer la fonction Update() et la remplacer par celle-ci :
protected override void Update(GameTime gameTime) { // Permet la sortie du jeu if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); // TODO: Ajouter la logique de mise à jour ici timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds; if (timeSinceLastFrame > millisecondsPerFrame) { timeSinceLastFrame -= millisecondsPerFrame; ++currentFrame.X; if (currentFrame.X >= sheetSize.X) { currentFrame.X = 0; /* Et dans le cas où nous aurions plus d'une ligne dans la feuille de sprites : ++currentFrame.Y; if (currentFrame.Y >= sheetSize.Y) currentFrame.Y = 0; */ } } base.Update(gameTime); }
C'est dans cette fonction que se fait la mise à jour de l'animation. Nous voyons premièrement que la touche Escape nous permet de sortir du programme.
La logique de mise à jour nous montre que si le temps ecoulé depuis la frame précédente est supérieur au temps qui lui est imparti (150 ms dans notre cas), on soustrait ce temps du temps écoulé depuis la dernière frame et on passe à la frame suivante (++currentFrame.X) et ce, jusqu'à ce que toutes les frames de la feuille de sprites soient affichées sinon on remet currentFrame.X à 0 et on recommence.
Dans le cas où il y aurait plusieurs lignes dans une feuille de sprites, on passe à la ligne suivante en incrémentant currentFrame.Y et ainsi de suite (voir commentaires de la logique de mise à jour).
Ceci étant dit, nous passons maintenant à la fonction de dessin. Supprimez la fonction Draw() et remplacez-la par celle-ci :
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(backgroundColor); spriteBatch.Begin(); spriteBatch.Draw(text_Aron, aronPosition, new Rectangle(currentFrame.X * frameSize.X, currentFrame.Y * frameSize.Y, frameSize.X, frameSize.Y), Color.White, 0, Vector2.Zero, 1, spriteEffet, 0); spriteBatch.End(); base.Draw(gameTime); }
Comme dans nos chapitres précédents, nous utilisons une fonction surchargée de la classe SpriteBatch qui reprend successivement nos 9 variables se rapporant à :
- la texture
- la position
- la localisation
- la couleur
- la rotation
- l'origine
- l'échelle
- l'effet sur le sprite
- la profondeur.
Voilà, c'est tout pour cet exemple. Il ne vous reste plus alors qu'à sauver votre projet, et ensuite le compiler en cliquant sur Déboguer - > Générer la solution.
Pressez ensuite la touche F5 pour admirer le résultat. Vous obtiendrez la fenêtre suivante avec notre ami Aron marchant allégrement... sur place. Mais n'ayez crainte, nous allons bientôt le faire se déplacer !
Eh voilà, dans le chapitre suivant, nous verrons comment déplacer un sprite animé en l'intégrant dans des classes !
@ bientôt !