Aller au menu - Aller au contenu

[Plan du site] Vous êtes ici --- > Le Site du Zér0 > Les tutoriels > Non-Officiels > Programmation > C > Lecture du tutoriel

[SDL] Faire des rotations avec SDL_gfx

Avatar
Auteur : Clément.S
Créé : le 28/11/2006 12:58:32
Modifié : le 11/01/2008 21:54:56
Noter et commenter ce tutoriel
Imprimer ce tutoriel
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)
Bonjour à tous. :D

Bienvenue dans ce mini-tuto où vous allez apprendre à faire des rotations sur des surfaces grâce à... SDL_gfx. :o
Ce tuto nécessite que vous connaissiez un peu la SDL. Donc ça ne sert à rien d'essayer de comprendre ce tuto si vous n'avez pas une petite connaissance de cette bibliothèque graphique. Si vous ne connaissez pas la SDL, vous pouvez suivre les cours de M@teo21 ici.

Bon, commençons...
Sommaire du chapitre :

C'est quoi SDL_gfx ?

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 ! :pirate:

Installation de SDL_gfx

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 :



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 installer SDL_gfx dessus. :(

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.

Faire une rotation

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 : C
1
#include <SDL/SDL_rotozoom.h>


Mais il me semble que j'ai copié 5 fichiers headers ? 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 : C
1
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. ;)

J'ai mis ici le code qui permet de gérer le temps qu'il y a entre chaque augmentation de l'angle, cela permet de gérer la vitesse de rotation. M@teo21 en a parlé ici.


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 :

erreurRotation1
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 :
erreurRotation2


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 gRANDIR 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 :magicien: :



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;
}

Voilà, c'est fini !!

Maintenant vous savez faire des rotations !
Et donc grâce à cela, vous allez pouvoir réaliser de superbes jeux (si si, croyez-moi :p ).

Quoi comme jeux par exemple ?

Vous pourriez créer un Astéroïde ou un jeu de voiture 2D, etc...

Toujours pas convaincus ? Bon je vous donne un exemple.

Bonne programmation !!!

Image utilisateur
Auteur : Clément.S
Noter et commenter ce tutoriel
Imprimer ce tutoriel

Nombre de connectés 233 Zér0s connectés | Requêtes SQL 7 requêtes | Temps de génération de la page 0.1427s (0.128s)

Changer de design - Revue de presse - En savoir plus - Plan du site
Nous contacter - Mentions légales - Publicité
Politique d'accessibilité - Fil RSS - XHTML 1.0 - CSS 2.0

Y'a plus rien à lire, faut remonter maintenant !