Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
SDL_gfx est une bibliothèque qui nécessite que la SDL soit installée.
Vous en avez sûrement déjà entendu parler dans les cours de M@teo21, je pense au chapitre
SDL_image ou
SDL_ttf.
SDL_gfx sert à faire des rotations mais aussi des figures géométriques, filtrer des images, gérer le temps de rafraîchissement de l'écran, etc...
Mais nous, ce qui nous intéresse, c'est la rotation, alors au boulot !
Sous Code::Blocks
Téléchargement
Tout d'abord, il faut télécharger le fichier zip de SDL_gfx
ici.
Quand vous arriverez sur la page, cliquez sur
"Click here" dans le paragraphe
"Setting Up SDL_gfx in Visual Studio .NET 2003".
Ce que vous avez téléchargé est un fichier zip contenant SDL_gfx déjà compilé. Normalement, on aurait dû télécharger les sources sur le site officiel et les compiler, mais je ne sais pas le faire. C'est donc beaucoup plus pratique pour moi et pour vous de télécharger ce zip.
C'est téléchargé ? Bon maintenant, il faut décompresser ce zip.
Voici comment faire :
Faites un clic droit sur le fichier et cliquez sur
"Extraire tout...", ensuite laissez-vous guider par l'assistant d'extraction qui va vous décompresser ça en moins de deux.
Maintenant que vous avez décompressé le fichier, allez dans le dossier issu de la décompression.
Dans le dossier
lib se trouvent les fichiers
sdlgfx.dll et
sdlgfx.lib.
Dans le dossier
include se trouvent les fichiers d'en-tête, ou
headers (*.h).
Nous aurons besoin de ces fichiers pour l'installation.
Et voilà, c'est fini pour le téléchargement !
Installation
Je vous rappelle les fichiers dont nous avons besoin :
- sdlgfx.dll : placez ce fichier dans le dossier de votre projet ;
- sdlgfx.lib : ce fichier va dans le dossier "C:\Program Files\CodeBlocks\mingw32\lib" ;
- et les headers (*.h) : ils vont dans le dossier "C:\Program Files\CodeBlocks\mingw32\include\SDL".
OK ! Les fichiers sont bien placés !
Maintenant il faut... configurer votre projet pour utiliser SDL_gfx.
Créez d'abord votre projet si ce n'est pas déjà fait, en configurant comme pour un projet SDL normal. Si vous ne vous souvenez plus comment faire, rendez-vous
ici.
Puis sous Code::Blocks, allez dans le menu
"Projects",
"Build options".
Dans l'onglet
"Linker", cliquez sur le bouton
"Add" et indiquez où se trouve le fichier
"sdlgfx.lib".
Si on vous demande
"Keep as a relative path ?", répondez
Non.
C'est bon, l'installation sous Code::Blocks est terminée.
Sous Visual Studio
Désolé, mais je ne connais pas bien cet IDE, donc je ne peux pas vous expliquer comment y installer SDL_gfx.
Cependant il existe un site sur internet qui explique comment faire
ici (merci à
transfear pour m'avoir donné le lien).
Malheureusement, il est en anglais, mais je pense que vous saurez vous débrouiller.
On entre maintenant dans la partie la plus intéressante.
Surtout n'oubliez pas de mettre le fichier sdlgfx.dll dans le dossier de votre
projet !
Tout d'abord, le main.c devrait ressembler à ça :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 | #include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
int main(int argc, char *argv[])
{
SDL_Surface *ecran = NULL;
SDL_Event event;
int continuer = 1;
SDL_Init(SDL_INIT_VIDEO);
ecran = SDL_SetVideoMode(500, 500, 32, SDL_HWSURFACE);
SDL_WM_SetCaption("Faire des rotations avec SDL_gfx", NULL);
while(continuer)
{
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
break;
}
SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
SDL_Flip(ecran);
}
SDL_FreeSurface(ecran);
SDL_Quit();
return EXIT_SUCCESS;
}
|
La première chose à faire c'est d'inclure le fichier header :
Code : C1 | #include <SDL/SDL_rotozoom.h>
|
Mais il me semble que j'ai copié 5 fichiers header ? Non ?
Oui c'est vrai. Mais comme je l'ai déjà dit dans la première partie, SDL_gfx ne sert pas qu'à faire des rotations et dans notre cas, nous n'avons besoin que de
SDL_rotozoom.h.
Maintenant regardons le prototype de la fonction permettant de faire une rotation :
Code : C1 | SDL_Surface * rotozoomSurface (SDL_Surface *src, double angle, double zoom, int smooth);
|
Le premier argument est en fait le nom de la surface à modifier.
Le deuxième est l'angle de rotation.
Le troisième est le zoom à appliquer sur la surface.
Hein ! Mais qu'est-ce que le zoom vient faire ici ?
Eh bien cette fonction permet de faire une rotation mais aussi un zoom.
C'est vrai que ce n'est pas terrible comme fonctionnement, mais il doit sûrement y avoir une raison. Si vous ne voulez pas faire de zoom, mettez
1.0.
Et enfin le quatrième argument sert à lisser la surface tournée, comme ça c'est plus joli.
Mettez
1 pour lisser, sinon mettez
0.
Maintenant qu'on a tout expliqué, voilà le code complet :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 | #include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_rotozoom.h>
#define TEMPS 30 // Le temps qu'il y a entre chaque augmentation de l'angle.
int main(int argc, char *argv[])
{
SDL_Surface *ecran = NULL, *image = NULL, *rotation = NULL;
SDL_Rect rect;
SDL_Event event;
double angle = 0;
int continuer = 1;
int tempsPrecedent = 0, tempsActuel = 0;
SDL_Init(SDL_INIT_VIDEO);
ecran = SDL_SetVideoMode(500, 500, 32, SDL_HWSURFACE);
SDL_WM_SetCaption("Faire des rotations avec SDL_gfx", NULL);
image = SDL_LoadBMP("image.bmp");
rect.x = 150;
rect.y = 150;
while(continuer)
{
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
break;
}
tempsActuel = SDL_GetTicks();
if (tempsActuel - tempsPrecedent > TEMPS)
{
angle += 2; //On augmente l'angle pour que l'image tourne sur elle-même.
tempsPrecedent = tempsActuel;
}
else
{
SDL_Delay(TEMPS - (tempsActuel - tempsPrecedent));
}
SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
rotation = rotozoomSurface(image, angle, 1.0, 1); //On transforme la surface image.
SDL_BlitSurface(rotation , NULL, ecran, &rect); //On affiche la rotation de la surface image.
SDL_FreeSurface(rotation); //On efface la surface rotation car on va la redéfinir dans la prochaine boucle. Si on ne le fait pas, cela crée une fuite de mémoire.
SDL_Flip(ecran);
}
SDL_FreeSurface(ecran);
SDL_FreeSurface(image);
SDL_Quit();
return EXIT_SUCCESS;
}
|
Surtout n'oubliez pas d'ajouter une image dans le dossier de votre projet.
Maintenant vous pouvez compiler et lancer votre programme.
Quand je lance mon programme, l'image bouge en même temps qu'elle tourne !!!
Ah oui, j'ai oublié de vous dire : quand nous plaçons notre image, sa taille change à cause de la rotation ce qui la fait bouger.
La surface rotation change de taille ?
Oui, regardez ceci pour comprendre :

Ici on a fait une rotation, donc la taille de la surface a changé.
En revanche ici, l'image n'est pas tournée, donc la surface garde sa taille normale :
Donc il faut placer notre image en fonction de sa taille.
Voici le code :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 | #include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_rotozoom.h>
#define TEMPS 30 // Le temps qu'il y a entre chaque augmentation de l'angle.
int main(int argc, char *argv[])
{
SDL_Surface *ecran = NULL, *image = NULL, *rotation = NULL;
SDL_Rect rect;
SDL_Event event;
double angle = 0;
int continuer = 1;
int tempsPrecedent = 0, tempsActuel = 0;
SDL_Init(SDL_INIT_VIDEO);
ecran = SDL_SetVideoMode(500, 500, 32, SDL_HWSURFACE);
SDL_WM_SetCaption("Faire des rotations avec SDL_gfx", NULL);
image = SDL_LoadBMP("image.bmp");
while(continuer)
{
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
break;
}
tempsActuel = SDL_GetTicks();
if (tempsActuel - tempsPrecedent > TEMPS)
{
angle += 2; //On augmente l'angle pour que l'image tourne sur elle-même.
tempsPrecedent = tempsActuel;
}
else
{
SDL_Delay(TEMPS - (tempsActuel - tempsPrecedent));
}
SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
rotation = rotozoomSurface(image, angle, 1.0, 1); //On transforme la surface image.
//On positionne l'image en fonction de sa taille.
rect.x = 200 - rotation->w / 2;
rect.y = 200 - rotation->h / 2;
SDL_BlitSurface(rotation , NULL, ecran, &rect); //On affiche la rotation de la surface image.
SDL_FreeSurface(rotation); //On efface rotation car on va la redéfinir dans la prochaine boucle. Si on ne le fait pas, cela crée une fuite de mémoire.
SDL_Flip(ecran);
}
SDL_FreeSurface(ecran);
SDL_FreeSurface(image);
SDL_Quit();
return EXIT_SUCCESS;
}
|
Et voilà ! On a réussi à faire notre rotation. Alors, des questions ?
Euh... oui. Dans la fonction rotozoomSurface, est-ce qu'on n'aurait pas pu mettre "image = rotozoomSurface(image, angle, 1.0, 1);" ?
C'est une très bonne question. En fait oui, normalement on aurait pu le faire, mais on ne peut pas à cause du zoom parce que si à chaque fois on refait un zoom sur la même surface, alors l'image va gR
ANDIR jusqu'à l'infini, voilà pourquoi.
Quand dans la fonction on met
1.0, c'est pour agrandir l'image à sa taille normale. Si on met
0, l'image ne s'affiche pas, car on ne fait pas de zoom.
Un petit exercice
Maintenant on pourrait ajouter un petit gadget dans notre programme pour que vous vous rendiez compte de ce que l'on peut faire d'intéressant avec SDL_gfx.
Par exemple, ça serait bien que l'image bouge avec la souris. Et pour faire encore mieux, on pourrait aussi ajouter un effet de zoom.
Correction
:
Secret (cliquez pour afficher)Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 | #include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_rotozoom.h>
#define TEMPS 30 // Le temps qu'il y a entre chaque augmentation de l'angle.
int main(int argc, char *argv[])
{
SDL_Surface *ecran = NULL, *image = NULL, *rotation = NULL;
SDL_Rect rect;
SDL_Event event;
double angle = 0;
double zoom = 1;
int sens = 1;
int continuer = 1;
int tempsPrecedent = 0, tempsActuel = 0;
SDL_Init(SDL_INIT_VIDEO);
ecran = SDL_SetVideoMode(500, 500, 32, SDL_HWSURFACE);
SDL_WM_SetCaption("Faire des rotations avec SDL_gfx", NULL);
image = SDL_LoadBMP("image.bmp");
while(continuer)
{
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
break;
}
tempsActuel = SDL_GetTicks();
if (tempsActuel - tempsPrecedent > TEMPS)
{
angle += 2; //On augmente l'angle pour que l'image tourne sur elle-même.
tempsPrecedent = tempsActuel;
}
else
{
SDL_Delay(TEMPS - (tempsActuel - tempsPrecedent));
}
SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
rotation = rotozoomSurface(image, angle, zoom, 0); //On transforme la surface image.
//On repositionne l'image en fonction de sa taille.
rect.x = event.button.x - rotation->w / 2;
rect.y = event.button.y - rotation->h / 2;
SDL_BlitSurface(rotation , NULL, ecran, &rect); //On affiche la rotation de la surface image.
SDL_FreeSurface(rotation); //On efface la surface rotation car on va la redéfinir dans la prochaine boucle. Si on ne le fait pas, cela crée une fuite de mémoire.
if(zoom >= 2){sens = 0;}
else if(zoom <= 0.5){sens = 1;}
if(sens == 0){zoom -= 0.02;}
else{zoom += 0.02;}
SDL_Flip(ecran);
}
SDL_FreeSurface(ecran);
SDL_FreeSurface(image);
SDL_Quit();
return EXIT_SUCCESS;
}
|