5.1.4 Écriture de sdl_application.cpp

Maintenant le fichier sdl_application.cpp :

1
2
3
#include "sdl_application.h"
#include <assert.h>
using namespace std;

Pourquoi on ne met pas le #include dans le .h ?

On pourrait, mais cette une convention. Si vous voyez un autre include que en plus de celui attendu dans un .cpp (ou un .c) c'est que l'on a besoin de ses fonctions que dans le .cpp et pas de le .h, quand on a pas besoin de variables particulières. C'est pour cette raison que vous verrez souvent un #include dans un .cpp et pas dans un .h.

Nous aurons aussi besoin de cas deux constantes :

1
2
const float DTFACTOR = 0.01;
const unsigned int TIME_MAX = 10;

Ces deux constantes se révéleront utile dans quelques lignes. DTFACTOR permet de ne pas avoir un dt trop grand (car getTick donne la durée en millisecondes), et TIME_MAX définit le temps qu'il faut pour faire un cycle complet du programme (calcul, affichage), cela permet de ne pas faire de cycle pour rien, vous pouvez changer la valeur de cette variable pour voir ce que ça fait.

Les fonctions publiques

Le constructeur le plus simple :

1
2
3
4
5
SDL_Application::SDL_Application(unsigned int width, unsigned int height){
	this->initialisation_SDL(width, height);
	Uint32 color = 0;
	this->initialisation("SDL_Application", NULL, color, "", 0);
}

ATTENTION : il ne faut pas mettre les paramètres par défaut ils ne doivent apparaître que dans le .h

1
2
3
4
5
SDL_Application::SDL_Application(unsigned int width, unsigned int height, const std::string & titre, const std::string & icon){
	this->initialisation_SDL(width, height);
	Uint32 color = 0;
	this->initialisation(titre, icon, color, "", 0);
}

Ici on appel la fonction initialisation_SDL pour créer la fenêtre et la fonction initialisation pour initialiser ce qui ne l'est pas encore. On complète les paramètres que l'on a pas par des paramètres par défaut.

Encore un constructeur :

1
2
3
4
SDL_Application::SDL_Application(unsigned int width, unsigned int height, const std::string & titre, const std::string & icon, const std::string & backgroundFile, const std::string & police, int taille){
	this->initialisation_SDL(width, height);
	this->initialisation(titre, icon, backgroundFile, police, taille);
}

Maintenant on a tout ce qu'il faut. Mais que pour avoir un fichier image pour le fond d'écran.

On fait les deux autres constructeurs :

1
2
3
4
5
6
7
8
9
SDL_Application::SDL_Application(unsigned int width, unsigned int height, const std::string & titre, const std::string & icon, SDL_Surface* background, const std::string & police, int taille){
	this->initialisation_SDL(width, height);
	this->initialisation(titre, icon, background, police, taille);
}

SDL_Application::SDL_Application(unsigned int width, unsigned int height, const std::string & titre, const std::string & icon, Uint32 backgroundColor, std::string police, int taille){
	this->initialisation_SDL(width, height);
	this->initialisation(titre, icon, backgroundColor, police, taille);
}

Encore le constructeur de copie et on a fini les constructeurs :

1
2
3
SDL_Application::SDL_Application(const SDL_Application & app){
	this->copySDL_Application(app);
}

Ouf, maintenant le destructeur :

1
2
3
4
5
6
7
8
9
10
11
12
13
SDL_Application::~SDL_Application(){
	if(this->icon != NULL && isMyIcon){
		SDL_FreeSurface(this->icon);
	}
	if(this->background != NULL && isMyBackground){
		SDL_FreeSurface(this->background);
	}
	if(this->font != NULL && isMyFont){
		TTF_CloseFont(this->font);
	}
	TTF_Quit();
	SDL_Quit();
}

Voilà l'utilité de tout ces booléens que je vous ai fait rajouter dans le .h. Il faut être sur de ne pas libérer une SDL_Surface* qui pourrait être utilisée après, sinon vous allez voir votre programme s'arrêter d'un coup et il sera écrit dans la console segmentation fault, en gros vous avez voulu lire dans la mémoire à un endroit où vous n'avez pas le droit (comme quand on essai d'effacer un pointeur NULL).

La fonction tant attendue et tant évoquées (et réciproquement) :

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
32
33
34
int SDL_Application::executer(){
	//fonction principale de SDL_Application
	SDL_Event event;
	if(this->ecran != NULL){
		if(this->ecran->w > 0 && this->ecran->h > 0){
			SDL_Rect pos;
			pos.x = 0;
			pos.y = 0;
			this->run = true;
			this->initVar();
			while(this->run){
				this->start_time = SDL_GetTicks();              //on regarde le temps qu'il s'est écoulé depuis le début de l’exécution du programme
				while(SDL_PollEvent(&event)){            //on récupéré les appuis de touches
					if(event.key.keysym.sym == SDLK_ESCAPE || event.type == SDL_QUIT){this->run = false;}
					this->getEvent(&event);
				}
				if(this->background != NULL){
					SDL_BlitSurface(this->background, NULL, this->ecran, &pos);   //on efface l'écran
				}else{
					SDL_FillRect(ecran, NULL, this->backgroundColor);           //on efface l'écran
				}
				this->current_time = SDL_GetTicks();                         //on regarde le temps courrant
				this->ellapsed_time = this->current_time - this->last_time;  //on calcul le dt
				this->last_time = this->current_time;
				this->update(this->ellapsed_time);                               //on gère les événements
				this->draw(ecran);
				SDL_Flip(ecran);                                                //on affiche tout
				this->ellapsed_time = SDL_GetTicks() - this->start_time;
				if(this->ellapsed_time < TIME_MAX){SDL_Delay(TIME_MAX - this->ellapsed_time);}
			}
			return 0;
		}else{return 1;}
	}else{return 1;}
}

Pourquoi on ne met pas les deux conditions dans un seul if ?

Car si l'écran est NULL vous vous retrouvé à demander la longueur et la largeur d'un pointeur NULL (et ça aussi c'est mal).

Faisons tout cela dans l'ordre :

  • on créé un SDL_Event : pour gérer les événements
  • on vérifie que l'écran n'est pas NULL
  • sinon on arrête et on retourne 1 (erreur)
  • on regarde si l'écran à une taille correcte
  • sinon on arrête et on retourne 1 (erreur)
  • On définit la position du fond d'écran
  • on met run à true (pour que l'application s'exécute)
  • On appel la fonction initVar (si l'utilisateur veut initialiser de choses a ce moment là)
  • Tan que run == true on boucle (l'application s'exécute)
  • On se rappel de l'heure au début de la boucle
  • tant qu'il y a un événement on le gère (ce qui permet de gérer plusieurs événements simultanément (enfin presque)
  • Si le fond d'écran n'est pas NULL on l'affiche
  • Sinon on met un couleur à sa place (noir par défaut)
  • On regarde à nouveau l'heure
  • on calcul le temps mis
  • le temps courant devient le temps passé
  • calcul , mise à jour des variables
  • affichage
  • on regarde combien de temps on à mis
  • Si on a mis moins de temps que prévu (c'est préférable), on attend ce qu'il faut pour ne pas aller trop vite
  • on recommence

Les fonctions protected :

Toutes les fonctions d'initialisation :

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void SDL_Application::setTitle(const std::string & titre){
	SDL_WM_SetCaption(titre.c_str(), NULL);
}

void SDL_Application::setIcon(SDL_Surface* icon){
	this->isMyIcon = false;
	this->icon = icon;
	if(this->icon != NULL) SDL_WM_SetIcon(this->icon, NULL);
}

void SDL_Application::setIcon(const std::string & iconFile){
	this->icon = IMG_Load(iconFile.c_str());
	if(this->icon != NULL) SDL_WM_SetIcon(this->icon, NULL);
	this->isMyIcon = true;
}

void SDL_Application::setBackground(SDL_Surface* background){
	this->background = background;
	this->isMyBackground = false;
}

void SDL_Application::setBackground(const std::string & backgrounsFile){
	this->isMyBackground = true;
	this->background = IMG_Load(backgrounsFile.c_str());
}

void SDL_Application::setBackgroundColor(Uint32 color){
	this->backgroundColor = color;
}

void SDL_Application::setBackgroundColor(Uint8 r, Uint8 g, Uint8 b){
	if(this->ecran != NULL){
		this->backgroundColor = SDL_MapRGB(ecran->format, r, g, b);
	}
}

void SDL_Application::setFont(const std::string & police, int taille){
	this->font = TTF_OpenFont(police.c_str(), taille);
	this->isMyFont = true;
}

void SDL_Application::setFont(TTF_Font* font){
	this->font = font;
	this->isMyFont = false;
}

Elles sont assez simple à comprendre, et je vous en ai déjà parlé.

Maintenant l'opérateur = :

1
2
3
4
SDL_Application & SDL_Application::operator = (const SDL_Application & app){
	this->copySDL_Application(app);
	return *this;
}

Mais pourquoi on veut à tout prix redéfinir l'opérateur = alors que de toute façon on n'aura pas le droit de s'en servir ?

C'est justement pour cela qu'on le redéfinit c'est pour interdire son utilisation.

Et où est-elle cette interdiction ?

Elle sera dans copySDL_Application.

Les fonctions protégées :

1
2
void SDL_Application::initVar(){}
void SDL_Application::stop(){this->run = false;}

Vous reconnaissez ici la fonction que l'on a implémenté (vide mais quand même) pour le futur utilisateur de la classe (vous en fait, pour le moment). Et la fonction d'arrêt de l'application.

Ajout et réalisation d'un événement :

1
2
3
4
5
6
7
8
void SDL_Application::addKeyEvent(const std::string action, SDLKey key, bool initValue){
	this->keyconf[action] = key;
	this->keystates[this->keyconf[action]] = initValue;
}

bool SDL_Application::keyEventMade(const std::string action){
	return this->keystates[this->keyconf[action]];
}

Toutes les fonctions d'écriture :

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
32
33
34
35
36
37
38
//écrit du texte Solid
void SDL_Application::drawText_Solid(int x, int y, const std::string & str, SDL_Color color){
	SDL_Rect pos;
	pos.x = x;
	pos.y = y;
	if(this->font != NULL){
		//écrit un texte avec le police de l'application
		SDL_Surface* texte = TTF_RenderText_Solid(this->font, str.c_str(), color);
		SDL_BlitSurface(texte, 0, this->ecran, &pos); //met le texte dans l'écran
		SDL_FreeSurface(texte); //libère la SDL_Surface
	}
}

//écrit du texte Shaded
void SDL_Application::drawText_Shaded(int x, int y, const std::string & str, SDL_Color color, SDL_Color fond){
	SDL_Rect pos;
	pos.x = x;
	pos.y = y;
	if(this->font != NULL){
		//écrit un texte avec le police de l'application
		SDL_Surface* texte = TTF_RenderText_Shaded(this->font, str.c_str(), color, fond);
		SDL_BlitSurface(texte, 0, this->ecran, &pos); //met le texte dans l'écran
		SDL_FreeSurface(texte); //libère la SDL_Surface
	}
}

//écrit du texte Blended
void SDL_Application::drawText_Blended(int x, int y, const std::string & str, SDL_Color color){
	SDL_Rect pos;
	pos.x = x;
	pos.y = y;
	if(this->font != NULL){
		//écrit un texte avec le police de l'application
		SDL_Surface* texte = TTF_RenderText_Blended(this->font, str.c_str(), color);
		SDL_BlitSurface(texte, 0, this->ecran, &pos); //met le texte dans l'écran
		SDL_FreeSurface(texte); //libère la SDL_Surface
	}
}

ATTENTION : il ne faut encore pas oublier SDL_FreeSurface.

Les fonctions privées :

Aller, les fonctions privées et on a finit :

Les trois fonctions d'initialisation :

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
//fonction d'initialisation avec fichier image bg
void SDL_Application::initialisation(const std::string & titre, const std::string & icon, const std::string & backgroundFile, const std::string & police, int taille){
	this->backgroundColor = 0;
	this->setTitle(titre);
	this->setIcon(icon);
	this->setBackground(backgroundFile);
	this->setFont(police, taille);
}

//fonction d'initialisation pointeur image bg
void SDL_Application::initialisation(const std::string & titre, const std::string & icon, SDL_Surface* background, const std::string & police, int taille){
	this->backgroundColor = 0;
	this->setTitle(titre);
	this->setIcon(icon);
	this->setBackground(background);
	this->setFont(police, taille);
}

//fonction d'initialisation couleur de fond
void SDL_Application::initialisation(const std::string & titre, const std::string & icon, Uint32 backgroundColor, const std::string & police, int taille){
	this->background = NULL;
	this->setTitle(titre);
	this->setIcon(icon);
	this->setFont(police, taille);
}

La fonction qui initialise SDL :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void SDL_Application::initialisation_SDL(unsigned int width, unsigned int height){
	static bool initSDL = false;
	if(!initSDL){
		time_t t = time(NULL);
		srand(t);                                       //initialisation de l'aléatoire
		SDL_Init(SDL_INIT_VIDEO);                       //initialisation SDL
		this->ecran = SDL_SetVideoMode(width, height, 32,SDL_HWSURFACE | SDL_DOUBLEBUF);
		cout << "init SDL_INIT_VIDEO" << endl;
		TTF_Init();                                   //initialisation de SDL_ttf
		cout << "init SDL_ttf" << endl;
		initSDL = true;
		this->lastTick = 0;
		this->font = NULL;
		this->background = NULL;
		this->backgroundColor = 0;
	}
}
  • On créé un booléen initSDL (static veut dire qu'on le définira qu'une fois, même si on rappel la fonction)
  • Si initSDL est false on entre dans le if
  • On regarde l'heure
  • On initialise une variable aléatoire (ça peut toujours servir dans un jeu)
  • On initialise SDL (vous vous souvenez)
  • On initialise le mode vidéo de SDL avec l'écran
  • On initialise SDL_ttf
  • On met initSDL à true
  • On met le dernier tick à 0
  • On met font a NULL (par défaut un pointeur vaut n'importe quoi, mais pas NULL)
  • On met l'image de fond à NULL
  • On met la couleur de fond à 0 (noir)

On empêche la copie de l'application :

1
2
3
void SDL_Application::copySDL_Application(const SDL_Application & app){
	assert(false);
}

C'EST TOUT !!!?

Ben, oui, ça suffit.

En fait assert est une fonction qui stoppe l'exécution d'un programme si ce qu'on lui passe en paramètre est false. L'avantage c'est que cette méthode disparaît quand on compile de manière optimisée, et c'est très utile quand on développe, bien sur ça ne fait pas tout.

Bon, si vous voulez que je vous dégoutte encore un peut, sachez que vous pouvez réglé le problème de la copie non désirée en mettant le constructeur de copie de la classe en private, et là c'est le compilateur qui râlera, et pas le programme.

Mais il est bon de connaître les deux méthodes.

Ensuite la fonction qui récupère les touches que l'on a demander :

1
2
3
4
5
6
7
8
9
10
void SDL_Application::getEvent(SDL_Event* event){
	//on parcourt toutes les touches que l'on doit surveiller
	for (KeyStates::iterator it = this->keystates.begin();it != this->keystates.end();it++){
		/*est-ce que la touche responsable de l'événement est celle du keystate ?*/
		if (event->key.keysym.sym == it->first){
			it->second = (event->motion.type == SDL_KEYDOWN); //true si enfoncé, false si relâché
			break; /*la touche responsable de l'événement a été utilisée, on quitte le for*/
		}
	}
}

Et enfin la fonction qui met a jour les ticks :

1
2
3
4
5
6
float SDL_Application::updateTicks(){
	Uint32 tick = SDL_GetTicks();
	float dt = ((float)(tick - this->lastTick));
	this->lastTick = tick;
	return dt*DTFACTOR;
}

Et voilà. Ça fait beaucoup de choses d'un coup je l'admet. Aussi, je vous recommande de commenter votre code source (si vous l'avez recopier), c'est un bon exercice et c'est une bonne habitude à prendre. De ce point de vue là tout le monde est à la même enseigne, on est tous étrange a notre programme si on le laisse de côté pendant deux semaines, et plus tout à fait dans le coup quand on le laisse pendant une semaine.

Pour résumer, ça donne ça :

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
#include "sdl_application.h"
#include <assert.h>

using namespace std;

const float DTFACTOR = 0.01; //pour ne pas avoir d'intervalle de temps trop grand (utilisé dans updateTicks())
const unsigned int TIME_MAX = 10; //temps entre deux calculs


////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                             Fonctions public                               //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

SDL_Application::SDL_Application(unsigned int width, unsigned int height){
	this->initialisation_SDL(width, height);
	Uint32 color = 0;
	this->initialisation("SDL_Application", NULL, color, "", 0);
}

SDL_Application::SDL_Application(unsigned int width, unsigned int height, const std::string & titre, std::string icon){
	this->initialisation_SDL(width, height);
	Uint32 color = 0;
	this->initialisation(titre, icon, color, "", 0);
}

SDL_Application::SDL_Application(unsigned int width, unsigned int height, const std::string & titre, const std::string & icon, const std::string & backgroundFile, const std::string & police, int taille){
	this->initialisation_SDL(width, height);
	this->initialisation(titre, icon, backgroundFile, police, taille);
}

SDL_Application::SDL_Application(unsigned int width, unsigned int height, const std::string & titre, const std::string & icon, SDL_Surface* background, const std::string & police, int taille){
	this->initialisation_SDL(width, height);
	this->initialisation(titre, icon, background, police, taille);
}

SDL_Application::SDL_Application(unsigned int width, unsigned int height, const std::string & titre, const std::string & icon, Uint32 backgroundColor, const std::string & police, int taille){
	this->initialisation_SDL(width, height);
	this->initialisation(titre, icon, backgroundColor, police, taille);
}

//constructeur de copie
SDL_Application::SDL_Application(const SDL_Application & app){
	this->copySDL_Application(app);
}

//destructeur
SDL_Application::~SDL_Application(){
	if(this->icon != NULL && isMyIcon){
		SDL_FreeSurface(this->icon);
	}
	if(this->background != NULL && isMyBackground){
		SDL_FreeSurface(this->background);
	}
	if(this->font != NULL && isMyFont){
		TTF_CloseFont(this->font);
	}
	TTF_Quit();
	SDL_Quit();
}


int SDL_Application::executer(){      //fonction principale de SDL_Application
	SDL_Event event;
	if(this->ecran != NULL){
		if(this->ecran->w > 0 && this->ecran->h > 0){
			SDL_Rect pos;
			pos.x = 0;
			pos.y = 0;
			this->run = true;
			this->initVar();
			while(this->run){
				this->start_time = SDL_GetTicks();
				while(SDL_PollEvent(&event)){
					if(event.key.keysym.sym == SDLK_ESCAPE || event.type == SDL_QUIT){this->run = false;}
					this->getEvent(&event);
				}
				if(this->background != NULL){
					SDL_BlitSurface(this->background, NULL, this->ecran, &pos);//on efface l'écran
				}else{
					SDL_FillRect(ecran, NULL, this->backgroundColor); //on efface l'écran
				}
				this->current_time = SDL_GetTicks();
				this->ellapsed_time = this->current_time - this->last_time;
				this->last_time = this->current_time;
				this->update(this->ellapsed_time);   //on gère les événements
				this->draw(ecran);               //on affiche tout
				SDL_Flip(ecran);
				this->ellapsed_time = SDL_GetTicks() - this->start_time;
				if(this->ellapsed_time < TIME_MAX){SDL_Delay(TIME_MAX - this->ellapsed_time);}
			}
			return 0;
		}else{return 1;}
	}else{return 1;}
}


void SDL_Application::setTitle(const std::string & titre){                                  //donne un titre à la fenêtre
	SDL_WM_SetCaption(titre.c_str(), NULL);
}

void SDL_Application::setIcon(SDL_Surface* icon){                                 //icone passé à l'application
	this->isMyIcon = false;
	this->icon = icon;
	if(this->icon != NULL) SDL_WM_SetIcon(this->icon, NULL);
}

void SDL_Application::setIcon(const std::string & iconFile){                             //icone à initialiser (puis détruire)
	this->icon = IMG_Load(iconFile.c_str());
	if(this->icon != NULL) SDL_WM_SetIcon(this->icon, NULL);
	this->isMyIcon = true;
}

void SDL_Application::setBackground(SDL_Surface* background){                   //donne une image de fond de l'application
	this->background = background;
	this->isMyBackground = false;
}

void SDL_Application::setBackground(const std::string & backgrounsFile){               //donne une image de fond de l'application
	this->isMyBackground = true;
	this->background = IMG_Load(backgrounsFile.c_str());
}

void SDL_Application::setBackgroundColor(Uint32 color){                         //couleur de fond de l'application
	this->backgroundColor = color;
}

void SDL_Application::setBackgroundColor(Uint8 r, Uint8 g, Uint8 b){           //couleur de fond de l'application (rouge, vert, bleu)
	if(this->ecran != NULL){
		this->backgroundColor = SDL_MapRGB(ecran->format, r, g, b);
	}
}

void SDL_Application::setFont(const std::string & police, int taille){                //initialisation de la police
	this->font = TTF_OpenFont(police.c_str(), taille);
	this->isMyFont = true;
}

void SDL_Application::setFont(TTF_Font* font){                               //passe une police
	this->font = font;
	this->isMyFont = false;
}

//définition de l'opérateur =
SDL_Application & SDL_Application::operator = (const SDL_Application & app){
	this->copySDL_Application(app);
	return *this;
}

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                           Fonctions protected                              //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

//comme ça l'utilisateur n'est pas obligé d'implémenter cette fonction
void SDL_Application::initVar(){}

//arrête l’application
void SDL_Application::stop(){this->run = false;}

//ajout d'une touche à gérer
void SDL_Application::addKeyEvent(const std::string action, SDLKey key, bool initValue){
	this->keyconf[action] = key;
	this->keystates[this->keyconf[action]] = initValue;
}

//dit si un événement est réalisé
bool SDL_Application::keyEventMade(const std::string action){
	return this->keystates[this->keyconf[action]];
}

//écrit du texte Solid
void SDL_Application::drawText_Solid(int x, int y, const std::string & str, SDL_Color color){
	SDL_Rect pos;
	pos.x = x;
	pos.y = y;
	if(this->font != NULL){       //écrit un texte avec le police de l'application
		SDL_Surface* texte = TTF_RenderText_Solid(this->font, str.c_str(), color);
		SDL_BlitSurface(texte, 0, this->ecran, &pos);  //met le texte dans l'écran
		SDL_FreeSurface(texte);   //libère la SDL_Surface
	}
}

//écrit du texte Shaded
void SDL_Application::drawText_Shaded(int x, int y, const std::string & str, SDL_Color color, SDL_Color fond){
	SDL_Rect pos;
	pos.x = x;
	pos.y = y;
	if(this->font != NULL){       //écrit un texte avec le police de l'application
		SDL_Surface* texte = TTF_RenderText_Shaded(this->font, str.c_str(), color, fond);
		SDL_BlitSurface(texte, 0, this->ecran, &pos);  //met le texte dans l'écran
		SDL_FreeSurface(texte);   //libère la SDL_Surface
	}
}

//écrit du texte Blended
void SDL_Application::drawText_Blended(int x, int y, const std::string & str, SDL_Color color){
	SDL_Rect pos;
	pos.x = x;
	pos.y = y;
	if(this->font != NULL){       //écrit un texte avec le police de l'application
		SDL_Surface* texte = TTF_RenderText_Blended(this->font, str.c_str(), color);
		SDL_BlitSurface(texte, 0, this->ecran, &pos);  //met le texte dans l'écran
		SDL_FreeSurface(texte);   //libère la SDL_Surface
	}
}

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                             Fonctions private                              //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

//fonction d'initialisation 
void SDL_Application::initialisation(const std::string & titre, const std::string & icon, const std::string & backgroundFile, const std::string & police, int taille){
	this->backgroundColor = 0;
	this->setTitle(titre);
	this->setIcon(icon);
	this->setBackground(backgroundFile);
	this->setFont(police, taille);
}

//fonction d'initialisation 
void SDL_Application::initialisation(const std::string & titre, const std::string & icon, SDL_Surface* background, const std::string & police, int taille){
	this->backgroundColor = 0;
	this->setTitle(titre);
	this->setIcon(icon);
	this->setBackground(background);
	this->setFont(police, taille);
}

//fonction d'initialisation 
void SDL_Application::initialisation(const std::string & titre, const std::string & icon, Uint32 backgroundColor, const std::string & police, int taille){
	this->background = NULL;
	this->setTitle(titre);
	this->setIcon(icon);
	this->setFont(police, taille);
}

//initialisation de SDL
void SDL_Application::initialisation_SDL(unsigned int width, unsigned int height){
	static bool initSDL = false;
	if(!initSDL){
		time_t t = time(NULL);
		srand(t);                     //initialisation de l'aléatoire
		SDL_Init(SDL_INIT_VIDEO);    //initialisation SDL
		this->ecran = SDL_SetVideoMode(width, height, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
		cout << "init SDL_INIT_VIDEO" << endl;
		TTF_Init();                 //initialisation de SDL_ttf
		cout << "init SDL_ttf" << endl;
		initSDL = true;
		this->lastTick = 0;
		this->font = NULL;
		this->background = NULL;
		this->backgroundColor = 0;
	}
}

//fonction de copie de l'application
void SDL_Application::copySDL_Application(const SDL_Application & app){
	assert(false);
}

//récupère les événements
void SDL_Application::getEvent(SDL_Event* event){
	//on parcourt toutes les touches que l'on doit surveiller
	for (KeyStates::iterator it = this->keystates.begin();it != this->keystates.end();it++){
		//est-ce que la touche responsable de l'événement est celle du keystate ?
		if (event->key.keysym.sym == it->first){
			it->second = (event->motion.type == SDL_KEYDOWN); //true si enfoncé, false si relâché
			break; //la touche responsable de l'événement a été utilisée, on quitte le for
		}
	}
}

//met à jour les ticks
float SDL_Application::updateTicks(){
	Uint32 tick = SDL_GetTicks();
	float dt = ((float)(tick - this->lastTick));
	this->lastTick = tick;
	return dt*DTFACTOR;
}

Ouf, ça, c'est fait.