Académique Documents
Professionnel Documents
Culture Documents
Tutoriel - (TP) Zozor Dans Son Enclos
Tutoriel - (TP) Zozor Dans Son Enclos
com/informatique/tutoriels/tp-zozor-dans-son-enclos)
À la base, j'avais créé ce petit programme, certes inutile mais assez marrant, pour
entretenir mes connaissances après la lecture du tuto de M@teo jusqu'au chapitre des
évènements. Ceci détermine d'ailleurs le niveau requis pour bien comprendre mon tuto.
Donc, si vous n'avez pas encore lu le tuto de M@teo, je vous recommande de le faire
jusqu'au chapitre des évènements.
Le projet
Mettre Zozor dans son enclos o_O ? Je ne comprends pas trop où tu veux en venir :o !
C'est simple : dans ce TP, nous allons ouvrir une fenêtre dans laquelle le curseur est remplacé par une
image de Zozor (à fond transparent). On placera dans cette fenêtre, à 40 pixels de chaque bord, une
clôture de 10 px d'épaisseur (représentée par un simple rectangle noir). Les mouvements de Zozor
(dirigés par la souris) seront limités à l'intérieur des "clôtures" (autrement dit on ne pourra pas
approcher la souris à moins de 50 pixels du bord de la fenêtre). :)
Je vais vous aider en vous donnant la structure du code ainsi que quelques informations ;) . Ah oui, je
vous fournis aussi l'image de Zozor ;) (clic droit + Enregistrer l'image sous... pour la télécharger) :
:
1. Les variables
Je ne m'étends pas là-dessus, vous verrez bien au fur et à mesure de quelles variables & pointeurs
vous aurez besoin. Par contre, je précise que vous n'aurez pas besoin de 4 surfaces pour les
"clôtures". En e!et, une surface pour les verticales (gauche / droite) et une autre pour les horizontales
(haut / bas) su!isent. Celles-ci seront blittées 2 fois chacune à deux endroits di!érents. ;)
2. La fenêtre
Petite précision : la fenêtre fera 640 px de large sur 480 px de haut et sera en 32 bits. N'oubliez pas le
double bu!ering. Je vous laisse choisir le titre et la couleur de fond (bien qu'un vert imitation herbe
serait pas mal :p )!
3. Les "clôtures"
Dans cette section, vous allez déterminer la dimension des clôtures, de préférence par rapport à la
largeur / hauteur de la fenêtre. Il su!it de faire une soustraction entre la hauteur / largeur de la
fenêtre (ecran->w ou ecran->h) et les deux "marges" à laisser entre le bord de celle-ci et la "clôture".
N'oubliez pas ce que j'ai dit au début : 40 px de "marge" (que l'on peut considérer comme l'extérieur
de l'enclos) + 10 px d'épaisseur de "clôture" pour un total de 50 px de chaque bord dans lesquels
Zozor ne pourra pas gambader ;) . Oups! J'en ai déjà trop dit :-° :p ...
Pour vous aider, voici un schéma qui vous permettra de mieux comprendre ce que j'attends de vous.
J'ai bien dit placer Zozor au centre. Il faut donc que l'image soit centrée mais si vous vous
contentez de placer le point curseur au milieu de la fenêtre, l'image ne le sera pas tout à fait,
car le curseur se situe dans le bord supérieur gauche de celle-ci, et non pas en son centre. À
vous de réfléchir (utilisez les dimensions de l'image) ;) !
6. On libère la mémoire
Juste pour rappel, il n'y a que la surface principale (ecran) qui ne doit pas être libérée par la fonction
SDL_FreeSurface() : il y en a donc quelques-uns à faire ^^ .
La solution
Alors... vous avez réussi ? :) J'espère que oui. Mais si ce n'est pas le cas, pas d'inquiétude ; on
n'apprend pas qu'en réussissant ;) mais aussi en se trompant (à condition de se corriger). Voici donc
la solution présentée de la même manière que le projet.
J'espère que vous n'aviez pas oublié la SDL (sinon honte à vous, mouahaha :p ).
1. Les variables
/*
1. Déclaration des variables
*/
SDL_Surface *ecran = NULL, *zozor = NULL;
SDL_Surface *clotureVerticale = NULL, *clotureHorizontale = NULL;
SDL_Event event;
SDL_Rect positionZozor;
SDL_Rect positionClotureGH, positionClotureD, positionClotureB;
int continuer = 1;
Petite précision à propos des variables de positionnement des clôtures : la lettre en majuscule à la fin
du nom de la variable signifie son emplacement (G pour gauche, H pour haut, D pour droite et B pour
bas).
On peut s'apercevoir que la clôture gauche et celle du haut auront la même position. Si vous
ne comprenez pas pourquoi maintenant, patientez un peu, je vous le montrerai lors de leur
blittage.
2. La fenêtre
:
/*
2. On s'occupe de la fenêtre
*/
SDL_Init(SDL_INIT_VIDEO);
Pas besoin d'explications, je présume. Il ne fallait pas oublier de mettre le double bu!ering.
3. Les clôtures
Ici, j'a!iche les réponses en plusieurs fois.
/*
3. Les clôtures
*/
// On détermine les dimensions des clôtures verticales et horizontales
clotureVerticale = SDL_CreateRGBSurface(SDL_HWSURFACE, 10, ecran->h - 2*40, 3
2, 0, 0, 0, 0);
clotureHorizontale = SDL_CreateRGBSurface(SDL_HWSURFACE, ecran->w - 2*40, 10,
32, 0, 0, 0, 0);
Grâce aux mesures que j'ai a!ichées en dessous, on peut maintenant facilement déterminer les
coordonnées de chaque origine et s'apercevoir qu'il faut, pour obtenir l'ordonnée de la clôture du
bas, faire "la hauteur de la fenêtre moins 50 px" (soit ecran->h - 50 pour l'ordonnée) alors que pour
obtenir l'abcisse de la clôture de droite, on fait "la largeur de l'écran moins 50 px" (soit ecran->w - 50
pour l'abcisse). Compris ? :p
Si vous n'aviez pas compris tout à l'heure pourquoi la clôture du haut et celle de gauche
avaient la même position, vous en avez maintenant l'explication : les points G et H se
superposent ^^ .
Hormis le fait qu'on charge l'image de Zozor dans sa surface et qu'on rend le fond transparent (je
suppose que ça, c'était OK de votre côté), il faut rendre le curseur invisible grâce à la fonction
SDL_ShowCursor(). De plus, on doit déplacer Zozor au milieu de la fenêtre. Mais il ne faut pas perdre
de vue que, lorsque la boucle d'évènements fera que Zozor suit les déplacements de la souris, le
curseur sera dans le coin supérieur gauche de l'image (testez en n'e!açant pas le curseur et vous
verrez). De ce fait, il ne su!it pas de faire :
En e!et, il faut faire une soustraction entre la largeur / hauteur de la fenêtre et la largeur / hauteur de
Zozor pour obtenir les bonnes coordonnées (comme dans la solution ci-dessus). Vous ne comprenez
pas ? Pas de bol, c'est comme ça, les maths :lol: !
5. La boucle principale
/*
5. La boucle principale
*/
while(continuer)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
break;
positionZozor.x = event.motion.x;
positionZozor.y = event.motion.y;
break;
}
SDL_Flip(ecran);
}
Parlons un peu du traitement des évènements. En dehors de l'habituelle fermeture en cliquant sur la
croix, on retrouve un autre moyen de fermeture en appuyant sur une touche du clavier. J'ai fait cela
pour permettre de quitter plus facilement le programme car, comme la souris est coincée dans
:
l'enclos, il n'est pas possible d'atteindre la croix (sauf en faisant un mouvement rapide ;) ). Ensuite, en
cas d'évènement MOUSEMOTION (quand la souris bouge), à l'aide des conditions if, on teste si Zozor
ne sort pas de ses frontières :p . Si c'est le cas, on déplace la souris.
Lors du même évènement il faut modifier le positionnement de Zozor en remplaçant l'initial par les
coordonnées de la souris.
Pour terminer, on e!ace et on blitte à nouveau toutes les surfaces aux éventuels nouveaux
emplacements :D (sans oublier le SDL_Flip() ;) ).
6. On libère la mémoire
/*
6. Pour terminer
*/
SDL_Flip(ecran);
SDL_FreeSurface(zozor);
SDL_FreeSurface(clotureVerticale);
SDL_FreeSurface(clotureHorizontale);
SDL_Quit();
return EXIT_SUCCESS;
}
Aucune explication n'est nécessaire, on libère seulement la mémoire utilisée pour stocker les
surfaces ^^ .
Le code en entier
#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
/*
3. Les clôtures
*/
// On détermine les dimensions des clôtures verticales et horizontales
clotureVerticale = SDL_CreateRGBSurface(SDL_HWSURFACE, 10, ecran->h - 2*4
0, 32, 0, 0, 0, 0);
clotureHorizontale = SDL_CreateRGBSurface(SDL_HWSURFACE, ecran->w - 2*40,
10, 32, 0, 0, 0, 0);
/*
4. Placement initial de Zozor
*/
:
//On charge l'image de Zozor dans la surface et on rend le fond transparen
t
zozor = SDL_LoadBMP("zozor.bmp");
SDL_SetColorKey(zozor, SDL_SRCCOLORKEY, SDL_MapRGB(zozor->format, 0, 0, 25
5));
/*
5. La boucle principale
*/
while(continuer)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
break;
positionZozor.x = event.motion.x;
positionZozor.y = event.motion.y;
break;
}
SDL_Flip(ecran);
}
/*
6. Pour terminer
*/
SDL_Flip(ecran);
SDL_FreeSurface(zozor);
SDL_FreeSurface(clotureVerticale);
SDL_FreeSurface(clotureHorizontale);
SDL_Quit();
return EXIT_SUCCESS;
}
J'espère que ce TP vous a plu et surtout vous a permis de bien ancrer une partie de ce que vous avez
appris jusqu'ici.
Il y a bien sûr moyen de mettre des images à la place des clôtures noires toutes moches. On peut
aussi envisager de mettre une image d'herbe de 640 * 480 à la place du fond vert pour un meilleur
e!et. Si vous le faites, je serais très intéressé de voir le résultat :) .
Je terminerai en disant qu'aucun animal (en l'occurrence Zozor) n'a sou!ert pendant le codage de ce
programme :lol: !
: