Dans cette partie nous allons découvrir comment animer une image.
C'est par exemple un personnage qui marche, qui saute, etc ...
Pour y parvenir, il nous faut décomposer en une succession d'images intermédiaires, le
mouvement complet que nous voulons reproduire.
C'est ce qu'on appelle encore une chronophotographie.
Il suffit ensuite, de projeter ces images les unes après les autres avec une cadence suffisante
pour donner à notre vision une impression de fluidité du mouvement.
Dans les jeux videos très simples, contrairement au cinéma, nous n'avons pas besoin d'une
grande quantité d'images.
Ainsi vous allez voir qu'une douzaine d'images peuvent suffir pour simuler de façon réaliste
le déplacement à pied d'un personnage.
Voici un exemple de cette décomposition :
Surprise, vous vous attendiez à voir des images séparées, et ce n'est pas le cas.
Quel intérêt alors à réassembler nos 12 images en une seule ?
Il y a au moins deux raisons :
• Il est plus rapide d'accéder à une zone de l'image que de travailler avec un tas
d'images différentes,
• et l'écriture du programme, comme vous allez le découvrir, s'en retrouve simplifiée.
Vous allez voir que récupérer un morceau d'image est d'une simplicité surprenante.
Souvenez vous de la fonction SDL_RenderCopy() utilisée dans les chapitres
précédents.
Jusqu'à présent nous lui fournissions un pointeur nul en troisième argument.
C'est terminé, maintenant nous allons lui donner l'adresse d'une structure SDL_RECT.
Pourquoi ?
Pour justement préciser la zone d'image que nous voulons récupérer pour l'afficher à l'écran.
Voici un exemple :
Supposons vouloir afficher le personnage se trouvant à la troisième colonne et à la deuxième
ligne de l'image ci-dessus.
Commençons par définir un objet SDL_RECT :
SDL_Rect srcRect;
Chaque personnage appartient à un rectangle de hauteur h = 200 pixels et de largeur
w = 150 pixels. Il n'y a aucune marge entre chaque image, donc
l'abscisse du coin supérieur gauche de la troisième colonne aura pour coordonnée,
x = 2 × w = 300.
et, l'ordonnée du coin supérieur gauche de la deuxième ligne sera y = h = 200.
Nous écrirons donc :
srcRect.x
= 300;
srcRect.y
= 200;
srcRect.w
= 150;
srcRect.h
= 200;
Il n'y a plus qu'à transmettre l'adresse de cet objet
(&srcRect) à la fonction
SDL_RenderCopy() pour provoquer l'affichage du personnage.
Je donne maintenant ici le programme complet qui résume l'ensemble du travail
des chapitres précédents en incluant celui-ci.
#include <iostream>
#include <SDL.h>
using namespace std;
int main(int
argc,
char* argv[])
{
cout <<
"Une animation" <<
endl;
SDL_Window *pFenetre
=
0;
SDL_Renderer *pRendu
=
0;
// Création et initialisation des zones rectangulaires "source" et "destination".
SDL_Rect srcRect, destRect;
srcRect.x
= 0;
srcRect.y
= 0;
srcRect.w
= 150;
srcRect.h
= 200;
destRect.x
= 600;
destRect.y
= 100;
destRect.w
= 150;
destRect.h
= 200;
SDL_Init (SDL_INIT_VIDEO);
pFenetre =
SDL_CreateWindow(
"Une animation",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
600,
400,
SDL_WINDOW_SHOWN);
pRendu =
SDL_CreateRenderer(pFenetre,
-1, SDL_RENDERER_ACCELERATED);
// L'image est chargée dans une surface
SDL_Surface *image =
SDL_LoadBMP("robot.bmp");
if (!image)
{
cout
<<
"erreur de chargement de l'image"
<<
endl;
}
// Transfert de l'image de la surface à une texture
SDL_Texture *pTextureImage
=
SDL_CreateTextureFromSurface(pRendu,
image);
SDL_FreeSurface(image);
// La mémoire de surface est libérée
int attendre =
1;
int numImage =
0;
SDL_Event evenement;
// Boucle d'evenements
while(attendre)
{
SDL_PollEvent(&evenement);
switch(evenement.type)
{
case SDL_QUIT:
attendre =
0;
break;
}
// On redessine le fond
SDL_SetRenderDrawColor(pRendu,
65,
65,
65,
255);
SDL_RenderClear(pRendu);
// Determination de la position de l'image source
srcRect.x
= (numImage %
4) *
150;
// Colonne
srcRect.y
= (numImage /
4) *
200;
// Ligne
// On dessine le personnage
SDL_RenderCopy(pRendu,
pTextureImage,
&srcRect,
&destRect);
// Actualisation de la fenêtre
SDL_RenderPresent(pRendu);
// Image suivante
numImage +=
1;
if(numImage
> 11)
numImage =
0;
// Décalage à gauche de l'image
destRect.x -=
11;
if(destRect.x
< -150)
destRect.x =
600;
SDL_Delay(100);
// Pause 1/10ème de seconde
}
SDL_DestroyTexture(pTextureImage);
SDL_DestroyRenderer(pRendu);
SDL_DestroyWindow(pFenetre);
SDL_Quit ();
return
EXIT_SUCCESS;
}
En plus de l'animation du personnage, j'ai ajouté un déplacement de l'image vers la gauche, pour donner plus de réalisme à la marche. Ce déplacement est réalisé en décrémentant le paramètre "destRect.x" transmis lors de chaque cycle à la fonction SDL_RenderCopy(). L'image est ramenée à droite à chaque sortie du personnage du cadre de la fenêtre.