SDL logo

C. Drocourt - 2006

drocourt@iut-amiens.fr

SDL

logo iut

Introduction.

SDL (Simple DirectMedia Layer) est une librairie permettant d'accéder aux ressources multimédias (clavier, souris, accélération 3D via openGL, ...) et de réaliser des applications portables sous différents systèmes d'exploitation (après recompilation évidemment) comme Linux, Windows, BeOS, MacOS Classic, MacOS X, FreeBSD, OpenBSD, BSD/OS, Solaris, IRIX, et QNX. Il existe aussi d'autres portages mais non officiels pour Windows CE, AmigaOS, Dreamcast, Atari, NetBSD, AIX, OSF/Tru64, RISC OS, et SymbianOS. Tous les renseignements sont disponibles à l'adresse suivante : http://www.libsd.org/.

Pour compiler un programme utilisant la librairie SDL sous linux, on utilise la commande :
gcc `sdl-config --libs --cflags` monprog.c -o monprog

Qui va ainsi utiliser les bonnes options de compilation pour gcc (chemin des librairies, includes, ...).

Premiers pas - Nous allons donc commencer par un premier exemple :

/* ---------- sdl1.c ---------- */

/* On inclus ici les choses classiques mais aussi SDL.h */
/* Qui contient tous les "headers" des fonctions SDL,   */
/* ainsi que les différents types d'objets              */
#include <stdlib.h>
#include <SDL.h>

int main( int argc, char *argv[ ] ) {
  /* Creation d'un objet SDL */
  SDL_Surface *screen;

  /* Initialisation de la video */
  if(SDL_Init(SDL_INIT_VIDEO)==-1) {
    fprintf(stderr,"Erreur SDL_Init() : %s\n",SDL_GetError());
    exit(1);
  }

  /* Si l'utilisateur quitte */
  atexit(SDL_Quit);

  /* Notre objet d'affichage est en fait une fenetre de l'ecran */
  if((screen = SDL_SetVideoMode(800,600,32,SDL_HWSURFACE))==NULL) {
    fprintf(stderr,"Erreur SDL_SetVideoMode() : %s\n",SDL_GetError());
    exit(1);
  }  

  /* Titre de fenetre */
  SDL_WM_SetCaption("Application SDL",NULL);

  /* Autres fonctions */

  /* On attend 3 secondes */
  SDL_Delay(3000);

  exit(0);
}

SDL_init : permet d'initialiser le media video, les parametres possibles sont SDL_INIT_AUDIO, SDL_INIT_VIDEO, SDL_INIT_CDROM et SDL_INIT_TIMER. On peut initialiser plusieurs média en meme temps en utilisant un "|", exemple SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO);

SDL_SetVideoMode : permet de créer une zone d'affichage sur l'ecran en utlisant une fenetre, les parametres donnent la taille en largeur, en hauteur (on utilise en general des tailles classiques comme 640x480, 800x600, 1024x768, ...), le nombre de bits par pixel pour la couleur, et d'éventuels options (flags), ici SDL_HWSURFACE. Si l'on veut travailler en plein ecran, on utilisera par exemple SDL_FULLSCREEN. On peut combiner les options (flags) avec le caractère '|', par exemple : SDL_FULLSCREEN|SDL_HWSURFACE.

SDL_WM_SetCaption("Application SDL",NULL) permet de donner un titre à la fenetre.

SDL_Delay(3000) permet ensuite une attente de 3 secondes.

Exercice 1 : Tapez et compilez ce programme.

Pour remplir une partie d'une surface d'une couleur on utilise la fonction :
    SDL_FillRect(surface, rectangle_concerné, couleur);
La surface est du type SDL_Surface, le rectangle est un type SDL_Rect SDL_Rect (contenant 4 variables x, y , w et h renseignant sur la position x et y du rectangle et la taille w et h) ou NULL pour la surface totale, la couleur est du type Uint32. Pour obtenir le code d'une couleur spécifique en fonction des composantes RGB, on peut utiliser la fonction :
    SDL_MapRGB(surface->format, R, G, B);

Exercice 2 : Modifiez votre programme pour afficher un rectangle de fond d'ecran d'une certaine couleur.

Attention : Pour préciser à SDL de mettre à jour l'écran il faut faire un appel a SDL_UpdateRect(screen,0,0,0,0);

Les images

Pour charger une image on utilisera la fonction SDL_LoadBMP(), qui prend en unique parametre le nom de l'image BMP (avec le chemin eventuel), et nous renvoi un objet de type SDL_Surface, que nous avons vu precedemment. Une fois l'image chargee, il faudra la copier (blit) sur l'ecran par l'appel a la fonction SDL_BlitSurface(), puis rafraichir l'ecran par un appel a SDL_UpdateRect(). Enfin, nous pourrons liberer l'espace memoire reserve a l'image en utilisant la fonction SDL_FreeSurface().

  ...
  SDL_Surface *screen,*image;
  ...
  /* Autres fonctions */
  /* On charge notre image image.bmp */
  if((image=SDL_LoadBMP("image.bmp"))==NULL) {
    fprintf(stderr,"Erreur SDL_LoadBMP() : %s\n",SDL_GetError());
    exit(1);
  }
  /* On copie par defaut toute l'image a l'ecran en position 0,0 */
  SDL_BlitSurface(image,NULL,screen,NULL);
  /* On libere l'espace reserve a l'image */
  SDL_FreeSurface(image);
  /* On rafraichit l'ecran */
  SDL_UpdateRect(screen,0,0,0,0);
  ...

Exercice 3 : Modifiez votre programme pour qu'il affiche l'image : image.bmp.

En ce qui concerne les arguments 2 et 4 de SDL_BlitSurface(), il s'agit de rectangles de type SDL_Rect qui permettent respectivement de préciser la zone source et la zone de destination. On aurait pu avoir dans le programme :

  ...
  SDL_Rect rectsrc,rectdst;
  ...
  rectsrc.x=30;
  rectsrc.y=20;
  rectsrc.w=50;
  rectsrc.h=70;
  rectdst.x=130;
  rectdst.y=120;
  SDL_BlitSurface(image,&rectsrc,screen,&rectdst);
  ...

Il en va de meme pour la fonction SDL_UpdateRect(), qui permet de specifier la zone a rafraichir.

Exercice 4 : Modifiez votre programme pour qu'il n'affiche qu'une portion de l'image.

Autres types d'images.

Pour pouvoir utiliser d'autres types d'images que les bmp, on peut utiliser la librairie SDL_image qui n'est pas inclus par défaut, pour cela il faut include en début de programme :
#include <SDL_image.h>

Puis utiliser la ligne de compilation suivante pour utiliser la librairie lors de l'édition de liens :
gcc `sdl-config --libs --cflags` -lSDL_image monprog.c -o monprog

Et pour charger une image quelconque on utilisera pour un png (valable pour tous les types de format) :
image=IMG_Load("image.png");

Exercice 5 : Modifiez votre programme pour faire défiler l'image tux.png de la gauche vers la droite. Comment supprimer la trace ?

Fonctions supplémentaires.

Pour dessiner un pixel, il n'existe pas de fonctions spécifique, mais on utilise directement le pointeur de la surface, et plus particulièrement la propriétée "pixels", exemple pour afficher un point en x,y :
*((Uint32*)screen->pixels+x+y*screen->w)=SDL_MapRGB(screen->format,0,0,255);

Autres fonctions utiles :
SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface) : Qui convertit une surface dans le format d'affichage, tres utile pour accelerer l'affichage des images.
SDL_SetAlpha(SDL_Surface *surface, SDL_SRCALPHA | SDL_RLEACCEL, entier) : Permet de rendre une surface transparente, l'entier donne le degré de transparence.
SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key) : Qui permet de supprimer une couleur à l'affichage d'une surface, le flag est une combinaison de SDL_SRCCOLORKEY et SDL_RLEACCEL.

On peut creer une surface vide avec la fonction :
new_surface=SDL_CreateRGBSurface(type_surface,largeur,hauteur,profondeur,0,0,0,0);
Le type de surface peut etre SDL_HWSURFACE ou SDL_SWSURFACE pour une surface en mémoire video ou en mémoire classique.
ATTENTION : Il faut penser a supprimer la surface en quittant le programme par un appel a SDL_FreeSurface().

Exercice 6 : Faire un programme qui fait défiler le motif tux.png sur le fond d'ecran image.bmp, en prenant en compte évidemment les problèmes de traces.