Programmation en C/SDL2
Initiation à la SDL
Introduction
La SDL est une bibliothèque destinée à créer des jeux vidéos. Elle met à disposition du programmeur des fonctions permettant de gérer l'affichage en 2D et 3D (en la combinant avec OpenGL). D'autres fonctions sont également disponibles afin de gérer le son et les manettes de jeux.
Notions abordées
- Initialisation de la SDL
- Création d'une fenêtre simple
- Événement - boucle infinie
- Les types SDL_Window et SDL_Event
- Fonctions SDL_VideoInit(), SDL_CreateWindow(), SDL_PollEvent(), SDL_Quit()
Description du programme
Une simple fenêtre SDL, n'affichant aucun contenu.
win_quit.c
#include <stdio.h> #include <SDL2/SDL.h> int main(int argc, char *argv[]) { /* SDL_Window est une variable pointant vers une fonction * permettant de creer une fenetre -> voir SDL_CreateWindow() plus bas*/ SDL_Window *window; /* SDL_Event est une variable regroupant différents types struct. * Ces types struct permettent de gerer des evenements comme : * - les entrees claviers, * - les boutons et les mouvements de la souris * - les boutons ou le joystick d'une manette de jeux */ SDL_Event event; /* On cree une variable de type int qui permettra de sortir d'une boucle infinie. * - Si la variable est a 0 la boucle continue * - Si la variable est a 1 on sort de la boucle et le jeux s'arrete */ int quit=0; /* On passe en argument de SDL_VideoInit() le type de driver. * On utilise NULL pour utiliser celui par defaut. * La fonction renvoie 0 en cas de succes et un nombre negatif en cas d'echec. */ if (SDL_VideoInit(NULL) < 0) { /* La fonction SDL_LogError permet d'afficher des erreurs SDL */ SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, /* Flag par defaut pour des logs de type Application */ "Couldn't initialize SDL video: %s\n", /* La fonction SDL_GetError() renvoi une chaine de caractere * contenant la derniere erreur SDL enregistree */ SDL_GetError() ); /* Fin de SDL_LogError */ exit(1); }// Fin du if de SDL_VideoInit() window = SDL_CreateWindow("Fenetre", SDL_WINDOWPOS_UNDEFINED, /* Position de la fenetre selon x */ SDL_WINDOWPOS_UNDEFINED, /* Position de la fenetre selon y */ 640, /* Taille de la fenetre en pixel */ 480, /* Hauteur de la fenetre en pixel */ /* En utilisant le flag SDL_WINDOW_SHOWN, la fenetre ne peut-être ni * maximise, ni minimise et n'est pas redimensionnable */ SDL_WINDOW_SHOWN ); /* Fin de SDL_CreateWindow */ while ( !quit ) { /* SDL_PollEvent est une fonction renvoyant le nombre 1 * tant qu'il y a des evenements en attente */ if ( SDL_PollEvent(&event) ) { switch (event.type) { case SDL_QUIT: /* SDL_QUIT correspond au bouton de fermeture de la fenetre */ quit=1; break; }//end switch event.type }//end if PollEvent }//end while quit SDL_DestroyWindow(window); SDL_Quit(); exit(0); }//end main
Ci-dessous le même programme mais sans les commentaires :
#include <stdio.h> #include <SDL2/SDL.h> int main(int argc, char *argv[]) { SDL_Window *window; SDL_Event event; int quit=0; if (SDL_VideoInit(NULL) < 0) { SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL video: %s\n", SDL_GetError() ); exit(1); } window = SDL_CreateWindow("Fenetre", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN ); while ( !quit ) { if ( SDL_PollEvent(&event) ) { switch (event.type) { case SDL_QUIT: quit=1; break; }//end switch event.type }//end if PollEvent }//end while quit SDL_DestroyWindow(window); SDL_Quit(); exit(0); }//end mainPour compiler le programme, on tape dans le terminal
gcc win_quit.c -o win_quit -lSDL2
En tapant la commande ls, vous devriez voir un exécutable appelé win_quit. Pour l'exécuter on tape:./win_quit
Première utilisation d'un sprite
Les sprites sont des éléments graphiques qui servent à afficher des décors et des personnages animés. Pour manipuler les sprites la SDL utilise le type SDL_Surface.
On affiche pas les sprites directement sur l'écran. Pour cela on utilise un moteur de rendu. Le moteur de rendu est un pointeur vers une structure du type SDL_Renderer. On dessine d'abord dans le moteur de rendu et une fois que l'on a dessiné tous les éléments dans le moteur de rendu on affiche celui-ci à l'écran. Cette technique évite les scintillements et donne une impression de fluidité.
De même, on ne dessine pas directement les sprites dans le moteur de rendu mais on passe par une texture avec le type SDL_Texture. On pourra par exemple charger nos décors dans une texture qui lui est propre et nos personnages dans d'autres textures. Une fois celle-ci chargée, on les couplent au moteur de rendu.
Le fait de séparer nos éléments graphiques en texture permet d'améliorer la gestion de la mémoire et donc la rapidité d'affichage de nos éléments graphiques. On peut par exemple décider de créer une texture de type "décors" une fois pour toute, en ne la chargeant qu'une seul fois durant tout le niveau d'un jeux. On alternerera ensuite l'affichage des différentes textures décors/personnages durant l'animation de nos personnages.
Le code suivant va se contenter de créer un sprite et de charger une image dans celui-ci.
Vous aurez donc besoin de l'image suivante pour faire fonctionner le programme (sol.bmp):
sprite.c
#include <stdio.h> #include <SDL2/SDL.h> int main(int argc, char *argv[]) { SDL_Window *window; SDL_Renderer *renderer; SDL_Surface *sprite; SDL_Texture *texture; SDL_Event event; int quit=0; if (SDL_VideoInit(NULL) < 0) { SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL video: %s\n", SDL_GetError()); exit(1); } window = SDL_CreateWindow("Fenetre", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN); /* * On cree notre moteur de rendu avec la fonction SDL_CreateRenderer() * On passe en argument la fenetre d'affichage cree precedemment (window) * Le -1 signifie que l'on initialise le pilote de rendu par defaut * SDL_RENDERER_ACCELERATED demande a ce que le moteur de rendu * utilise l'acceleration materielle */ renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); // on charge l'image dans le sprite sprite = SDL_LoadBMP("sol.bmp"); /* * On cree une texture qui sera utilise par le moteur de rendu * et on associe cette texture au sprite cree precedemment */ texture = SDL_CreateTextureFromSurface(renderer, sprite); /* * On copie la texture (et donc le sprite) dans le moteur de rendu * Pour l'instant on met les deux derniers arguments a NULL * et on verra dans un autre chapitre ce que cela signifie */ SDL_RenderCopy(renderer, texture, NULL, NULL); //On affiche le tout SDL_RenderPresent(renderer); while ( !quit ) { if ( SDL_PollEvent(&event) ) { switch (event.type) { case SDL_QUIT: quit=1; break; }//end switch event.type }//end if PollEvent }//end while quit SDL_DestroyTexture(texture); SDL_FreeSurface(sprite); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); exit(0); }//end mainPour compiler le programme, on tape dans le terminal:
gcc sprite.c -o sprite -lSDL2
Pour l'exécuter:./sprite
Il va alors s'afficher la fenêtre ci-contre :