Créons un jeu de plateformes de A à Z !
Tutoriel présenté par : Jérémie F. Bellanger
Dernière mise à jour : 20 novembre 2013
Difficulté :
3. Le moteur du jeu : ouvrir une fenêtre
Alors, n'oubliez pas, le tout est d'avancer tranquillement, étape par étape et petit à petit votre jeu se construira. Rien ne sert de viser trop haut, si ce n'est à ne redescendre que plus vite. Ce tutoriel est là pour vous, laissez vous guider ! Alors, on y va !
Une boîte de dialogue s'ouvre. Choisissez le deuxième onglet, qui ressemble à ça :
Pour Debug et pour Release (à gauche), changez le type de Console application à GUI application. Faites OK et le tour est joué !!
On va donc y aller progressivement ensemble. Pour chaque partie du code, je vais vous donner le nom de la page à créer en cliquant sous Code::Blocks sur File / New / Empty File, en sauvegardant votre projet puis en rentrant le nom de la page à créer. Ensuite je vous donnerai le code commenté dans un cadre au fond blanc, puis une explication, plus ou moins longue selon le besoin.
Ok ! On y va ?!
C'est parti !!!!!
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <SDL.h> #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 |
Quel intérêt, me direz-vous ? C'est tout simple, plus tard, par exemple, on va définir la vitesse moyenne de notre héros : plutôt que de devoir la changer partout dans le code quand on s'apercevra qu'elle est pas bien, on écrira dans notre code PLAYER_SPEED, et quand on voudra changer la vitesse du héros, on viendra le faire ici en changeant la valeur du define. C'est donc super utile ! Et si vous voulez reprendre votre code plus tard, pour faire un autre jeu plus lent ou plus rapide, vous n'aurez presque rien à changer !
Bon, pour l'instant, on ne définit que deux paramètres : la largeur et la hauteur de notre fenêtre, qui fera donc 640 x 480 pixels.
#include "defs.h" /* Structures qui seront utilisées pour gérer le jeu */ /* Structure pour gérer l'input (clavier puis joystick) */ typedef struct Input { int left, right, up, down, jump, attack, enter, erase, pause; } Input; /* Structure pour gérer le niveau (à compléter plus tard) */ typedef struct Gestion { SDL_Surface *screen; } Gestion; |
La structure Gestion gèrera au fur et à mesure toutes les variables utiles à la gestion globale du jeu. Ces structures seront globales aux fichiers qui en auront besoin : ainsi, par exemple, Input sera globale au fichier traitant les entrées clavier/joystick mais n'apparaîtra pas, par exemple dans le fichier traitant l'affichage du level où on n'en a pas besoin .
#include "main.h" int main( int argc, char *argv[ ] ) { unsigned int frameLimit = SDL_GetTicks() + 16; int go; /* Initialisation de la SDL dans une fonction séparée (voir après) */ init("Aron"); /* Appelle la fonction cleanup à la fin du programme */ atexit(cleanup); go = 1; /* Boucle infinie, principale, du jeu */ while (go == 1) { /* On vérifie l'état des entrées (clavier puis plus tard joystick */ getInput(); /* On affiche tout */ draw(); /* Gestion des 60 fps ( 60 images pas seconde : soit 1s ->1000ms/60 = 16.6 -> 16 On doit donc attendre 16 ms entre chaque image (frame) */ delay(frameLimit); frameLimit = SDL_GetTicks() + 16; } /* Exit */ exit(0); } |
Voilà, il n'y a pas grand chose à dire de plus, c'est vraiment très basique, et ça ne devrait pas vous poser de problème si vous avez déjà lu les tutoriels sur la SDL que je vous ai recommandés .
Bon passons rapidement à l'en-tête maintenant :
#include "structs.h" /* Prototypes des fonctions utilisées */ extern void init(char *); extern void cleanup(void); extern void getInput(void); extern void draw(void); extern void delay(unsigned int); /* Déclaration des structures globales utilisées par le jeu */ Input input; Gestion jeu; |
#include "init.h" /* Fonction qui initialise le jeu */ void init(char *title) { /* Initialise SDL Video. Si la valeur de retour est inférieure à zéro, la SDL n'a pas pu s'initialiser et on quite */ if (SDL_Init(SDL_INIT_VIDEO ) < 0) { printf("Could not initialize SDL: %s\n", SDL_GetError()); exit(1); } /* On crée la fenêtre, représentée par le pointeur jeu.screen en utilisant la largeur et la hauteur définies dans les defines (defs.h). On utilise aussi la mémoire vidéo (SDL_HWPALETTE) et le double buffer pour éviter que ça scintille (SDL_DOUBLEBUF) */ jeu.screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 0, SDL_HWPALETTE|SDL_DOUBLEBUF); /* Si on y arrive pas, on quitte */ if (jeu.screen == NULL) { printf("Couldn't set screen mode to %d x %d: %s\n", SCREEN_WIDTH, SCREEN_HEIGHT, SDL_GetError()); exit(1); } /* On entre le titre de la fenêtre */ SDL_WM_SetCaption(title, NULL); /* On cache le curseur de la souris */ SDL_ShowCursor(SDL_DISABLE); } /* Fonction qui quitte le jeu proprement */ void cleanup() { /* Quitte la SDL */ SDL_Quit(); } |
#include "structs.h" extern Gestion jeu; |
#include "input.h" void getInput() { SDL_Event event; /* Keymapping : gère les appuis sur les touches et les enregistre dans la structure input */ while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: exit(0); break; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_ESCAPE: exit(0); break; case SDLK_DELETE: input.erase = 1; break; case SDLK_c: input.jump = 1; break; case SDLK_v: input.attack = 1; break; case SDLK_LEFT: input.left = 1; break; case SDLK_RIGHT: input.right = 1; break; case SDLK_DOWN: input.down = 1; break; case SDLK_UP: input.up = 1; break; case SDLK_RETURN: input.enter = 1; break; default: break; } break; case SDL_KEYUP: switch (event.key.keysym.sym) { case SDLK_DELETE: input.erase = 0; break; case SDLK_c: input.jump = 0; break; case SDLK_LEFT: input.left = 0; break; case SDLK_RIGHT: input.right = 0; break; case SDLK_DOWN: input.down = 0; break; case SDLK_UP: input.up = 0; break; case SDLK_RETURN: input.enter = 0; break; default: break; } break; } } } |
Ainsi, tant que la touche C est enfoncée, input.jump vaut 1 et quand on la relache, elle vaut 0. L'utilisation qu'on en fera se trouvera plus tard dans la fonction doPlayer() qui s'occupera de déplacer notre héros et tester les collisions.
#include "structs.h" extern Input input; |
Là encore, rien de spécial. On indique juste que la structure input a déjà été déclarée ailleurs.
#include "draw.h" void draw(void) { /* Affiche l'écran */ SDL_Flip(jeu.screen); /* Delai */ SDL_Delay(1); } void delay(unsigned int frameLimit) { /* Gestion des 60 fps (images/stories/seconde) */ unsigned int ticks = SDL_GetTicks(); if (frameLimit < ticks) { return; } if (frameLimit > ticks + 16) { SDL_Delay(16); } else { SDL_Delay(frameLimit - ticks); } } |
#include "structs.h" extern Gestion jeu; |
Eh voilà, on a maintenant l'ossature complète de notre jeu !!! Il ne reste plus qu'à compiler, en choisissant BUILD puis à tester en choisissant RUN (on peut aussi faire les 2 à la suite avec BUILD AND RUN). Tadaaaaam ! On a notre fenêtre noire !!!
Hum, c'est pas encore super top, mais c'est le début ! Alors vivement la suite !!!