2 La fenêtre avec SDL

Ben oui, si on veut faire de l'affichage il faut bien faire une fenêtre.

Je vous donne la syntaxe pour créer une fenêtre et on en discute après.

Voici le fichier main.cpp :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>

int main(int argc, char **argv){
	SDL_Init(SDL_INIT_VIDEO); //initialise le mode vidéo
	//on initialise la fenêtre
	//longueur, largeur, bit par pixel(couleur), type de fenêtre
	SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE);
	//on arrête SDL
	SDL_Quit();
	//on arrête le programme
	return EXIT_SUCCESS;
}

C'est quoi EXIT_SUCCESS ?

C'est une variable qui vaut 0, cela équivaut donc à return 0; sauf que si un jour on décide que la valeur retournée d'un programme qui fonctionne correctement n'est pas 0 mais 23723 ça foire (ça serait quand même très étonnant, mais c'est une habitude a prendre).

Vous reconnaissez #include et #include on les a vu tout à l'heure.

#include : on inclue le header de SDL (il faut juste le connaître).

Toutes les fonctions de SDL (enfin presque toutes) commencent par SDL_ ,donc si vous taper man:SDL_ dans la barre d'adresse de konqueror vous aller trouver les principales fonctions de SDL (et les includes correspondants).

Vous pouvez compiler ce programme avec g++ en faisant :

g++ -Wall main.cpp -o fenetreSDL -lSDL

Le -lSDL signifie que l'on va lier (linker) la bibliothèque SDL à notre programme, pour que g++ cherche les fonctions SDL où il faut. On en avait pas besoin précédemment car la librairie standard est liée par défaut.

Et si vous voulez le compiler avec CMake écrivez ceci dans un fichier CMakeLists.txt :

1
2
3
4
5
6
7
8
9
10
project(fenetreSDL)
cmake_minimum_required(VERSION 2.6)
#on demande a CMake de trouver le paquet SDL
find_package(SDL REQUIRED)
#il faut inclure de dossier ${SDL_INCLUDE_DIR} où il y a les .h de SDL
include_directories(${SDL_INCLUDE_DIR})
#on créé l’exécutable
add_executable(fenetreSDL main.cpp)
#on lie SDL au programme
target_link_libraries(fenetreSDL SDL)

Ensuite on se créé un dossier build :

mkdir build

On va dedans :

cd build

On appel CMake :

cmake ..
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Looking for include files CMAKE_HAVE_PTHREAD_H
-- Looking for include files CMAKE_HAVE_PTHREAD_H - found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE 
-- Configuring done
-- Generating done

On appel make :

make
Scanning dependencies of target fenetreSDL
[100%] Building CXX object CMakeFiles/fenetreSDL.dir/main.cpp.o
Linking CXX executable fenetreSDL
[100%] Built target fenetreSDL

Puis on exécute le programme :

./fenetreSDL

Heu, il ne s'est rien passé.

J'ai déjà entendu ça.

Bon, alors, il ne s'en pas rien passé c'est juste que c'est tellement rapide que vous n'avez rien vu. Nous avons créé une fenêtre et nous l'avons refermée aussitôt, mais il s'est passé plein de choses.

Il faudrait que l'on fasse une fonction pause. Pour cela on utilise les événements de SDL (le SDL_Event). Ces événements contiennent tout ce qui peut arriver dans la fenêtre : clic de la souris déplacement de la souris, appui de touche, relâchement de touches, clic dans la croix en haut a gauche, molette, joistick (enfin si on lui demande).

Pour la croix en haut de la fenêtre on peut faire ceci (fichier main.cpp) :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>

void pause(){
	SDL_Event event;
	//on attend le clic dans la croix
	while(event.type != SDL_QUIT){
		SDL_WaitEvent(&event); //on récupère les événements
	}
}

int main(int argc, char **argv){
	SDL_Init(SDL_INIT_VIDEO); //initialisation de SDL
	SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE); //fenêtre
	pause(); //mise en pause du programme
	SDL_Quit(); //arrêt de SDL
	return EXIT_SUCCESS; //fermeture du programme
}

On recompile :

make
Scanning dependencies of target fenetreSDL
[100%] Building CXX object CMakeFiles/fenetreSDL.dir/main.cpp.o
Linking CXX executable fenetreSDL
[100%] Built target fenetreSDL

On exécute le programme :

./fenetreSDL

Et voici le résultat :

plop

Voici un programme superbement inutile qui attend juste qu'on l'arrête, mais c'est un progrès.

Pour mettre un titre dans la barre supérieur de la fenêtre il faut utiliser la fonction SDL_WM_SetCaption qui, comme vous pouvez vous en doutez donne un titre à la fenêtre.

Il est très important d'écrire cette fonction après SDL_SetVideoMode , il faut en effet que la fenêtre existe si on veut lui mettre un titre.

1
SDL_WM_SetCaption("ma fenêtre vide", NULL);

Je vous met le programme complet pour que vous soyez sûre de ce que vous faites.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>

void pause(){
	SDL_Event event;
	//on attend le clic dans la croix
	while(event.type != SDL_QUIT){
		SDL_WaitEvent(&event); //on récupère les événements
	}
}

int main(int argc, char **argv){
	SDL_Init(SDL_INIT_VIDEO); //initialisation de SDL
	SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE); //fenêtre
	SDL_WM_SetCaption("ma fenêtre vide", NULL);
	pause(); //mise en pause du programme
	SDL_Quit(); //arrêt de SDL
	return EXIT_SUCCESS; //fermeture du programme
}

Compilez et vous verrez le titre de votre fenêtre.

Quelque chose comme ça :

plop

Maintenant on va essayer d'afficher quelque chose, mais pour cela il faut créer un écran, enfin une SDL_surface* ecran pour faire de l'affichage. C'est en fait une image.

Voici le fichier main.cpp :

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
#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>

void pause(){
	SDL_Event event;
	//on attend le clic dans la croix
	while(event.type != SDL_QUIT){
		SDL_WaitEvent(&event); //on récupère les événements
	}
}

int main(int argc, char **argv){
	SDL_Init(SDL_INIT_VIDEO); //initialisation de SDL
	SDL_Surface* ecran = NULL; //on créé l'écran
	ecran = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE);
	SDL_WM_SetCaption("Une superbe fenêtre blanche", NULL);
	if(ecran == NULL){ //si il y a foirage de l'initialisation de l'écran
		//on râle dans le fichier prévu, à cet effet
		fprintf(stderr, "Erreur SDL Impossible de charger le mode vidéo : %s\n", SDL_GetError());
		exit(EXIT_FAILURE);
	}
	//on affiche du blanc
	Uint32 color = SDL_MapRGB(ecran->format, 255, 255, 255);
	SDL_FillRect(ecran, NULL, color); //met la couleur sur l'écran
	//affichage
	SDL_Flip(ecran); //met à jour l'écran
	pause(); //mise en pause du programme
	SDL_Quit(); //arrêt de SDL
	return EXIT_SUCCESS; //fermeture du programme
}

C'est quoi un Uint32 ?

Un Uint32 est un entier sur 32 bits (4 octets) c'est un type définit par SDL (par souci de compatibilité), ici on s'en sert pour stocker une couleur (RGB, ou RGBA) suivant que l'on utilise SDL_MapRGB ou SDL_MapRGBA.

Ces deux fonctions construisent une couleur à partir de composantes rouge, verte et bleue (et transparente pour SDL_MapRGBA). Le premier paramètre étant le format de la surface (mais les surfaces connaissent leur format).

La fonction SDL_FillRect(surface, NULL, color) rempli d'une couleur de type Uint32 la SDL_Surface* qu'on lui passe, le deuxième paramètre étant pour ne modifier qu'une partie de l'écran (voir doc).

La fonction SDL_Flip(ecran) affiche à l'écran de l'ordinateur la SDL_Surface* ecran.

On recompile :

make
Scanning dependencies of target fenetreSDL
[100%] Building CXX object CMakeFiles/fenetreSDL.dir/main.cpp.o
Linking CXX executable fenetreSDL
[100%] Built target fenetreSDL

On exécute le programme :

./fenetreSDL

Et voici le résultat :

plop

Et voilà une superbe fenêtre blanche. Bon, enfin on a quand-même changé la couleur de fond de la fenêtre, c'est déjà pas mal.