On va mettre en pratique à peu près tout ce que l'on a vu depuis le début de ce cour.
Vous vous en rappelez sûrement, dans sdl_application.h :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#ifndef SDL_APPLICATION_H
#define SDL_APPLICATION_H
#include <iostream>
#include <string>
#include <string.h>
#include <time.h> //pour l'initialisation des aléatoires (on verra ça plus bas)
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
class SDL_Application{
};
#endif
|
Jusque là rien de bien surprenant, maintenant nous allons définir deux types pour les deux std::map que l'on va devoir utiliser, mettez ces lignes entre #include et class SDL_Application { :
1
2
3
4
|
#include <map> //on va utiliser des map
typedef std::map<SDLKey,bool> KeyStates;
typedef std::map<std::string,SDLKey> KeyConf;
|
Intéressons nous à la partie publique de la classe.
Je vous propose de faire plusieurs constructeurs :
- un avec que la taille de la fenêtre en option (SDL_Application(int width = 640, int height = 480);)
- un constructeur avec la taille, le titre et l’icon de a fenêtre (de dernier étant en option)
- un constructeur avec les quatre précédents et une SDL_Surface* backGround (pour le fond), le nom d'une police, sa taille, ces deux derniers paramètres étant en option
- un constructeur avec tout les paramètres précédents mais en replaçant SDL_Surface* backGround par Uint32 backGroungColor (la couleur de font de l'application)
- un constructeur avec tout les paramètres précédents en remplaçant Uint32 backGroungColor par const std::string & backgroundFile
Ce qui donne :
1
2
3
4
5
|
SDL_Application(unsigned int width = 640, unsigned int height = 480);
SDL_Application(unsigned int width, unsigned int height, const std::string & titre, SDL_Surface* icon = NULL);
SDL_Application(unsigned int width, unsigned int height, const std::string & titre, SDL_Surface* icon, const std::string & backGroundFile, const std::string & police = "", int taille = 0);
SDL_Application(unsigned int width, unsigned int height, const std::string & titre, SDL_Surface* icon, SDL_Surface* backGround, const std::string & police = "", int taille = 0);
SDL_Application(unsigned int width, unsigned int height, const std::string & titre, SDL_Surface* icon, Uint32 backGroundColor, const std::string & police = "", int taille = 0);
|
N'oublions pas le destructeur :
1
|
virtual ~SDL_Application();
|
Nous pouvons également ajouter des fonctions d'initialisations (setteurs) :
1
2
3
4
5
6
7
8
9
|
void setTitle(const std::string & titre);
void setIcon(SDL_Surface* icon);
void setIcon(const std::string & iconFile);
void setBackGroundColor(Uint32 color);
void setBackGroundColor(Uint8 r, Uint8 g, Uint8 b);
void setBackground(SDL_Surface* background);
void setBackground(const std::string & backgrounsFile);
void setFont(const std::string & police, int taille);
void setFont(TTF_Font* font);
|
Il nous faut aussi une fonction int executer() pour lancer l'application (qui retournera 0 si tout fonctionne et 1 si un truc à foiré (comme main) :
On à dit tout à l'heure que la classe ne devait pas pouvoir être copiée, pour cela il suffit de définir un constructeur de copie et l'opérateur =, pour empêcher la copie de la classe.
Les fonctions protégées (protected).
Le schéma d'un programme est assez simple :
- initialisation
- exécution (en boucle jusqu'à l'arrêt de l'application)
- affichage
- mise à jour (calculs)
- fin du programme (nettoyage de la mémoire, sauvegarde de données)
Et s'est tout.
Nous avons déjà la fonction exécution, il nous manque l'affichage (draw) et la mise à jour (update).
Elles seront virtuelles pures car c'est l'utilisateur qui en aura besoin, et pas nous.
Pourquoi on les déclare alors ?
Tout simplement pour pouvoir les appeler. Nous devons appeler des fonctions qui n'existent pas, donc on les créés sans les implémentés.
Pour dessiner nous devons donner l'écran en paramètre, donc la déclaration ressemblera à cela :
1
|
virtual void draw(SDL_Surface* ecran) =0;
|
Quant à la fonction update on pourrait fournir l'intervalle de temps entre deux calcul (le dt en physique) :
1
|
virtual void update(float dt) =0;
|
De la même manière nous pouvons rajouter une fonction virtuelle pour permettre une initialisation, par exemple :
1
|
virtual void initVar();
|
Pour que l'utilisateur puisse mettre des valeurs par défaut dans son application.
Nous en avons parler tout à l'heure il faut une fonction pour ajouter une touche à gérer :
1
|
void addKeyEvent(const std::string action, SDLKey key, bool initValue);
|
On passe donc à cette fonction :
- action : le nom de l’événement appuis de touche
- key : la touche associée
- initValue : sons état initial (true pressée, false relâchée)
La fonction qui va nous dire si un événement s'est réalisé :
1
|
bool keyEventMade(const std::string action);
|
Pensons aussi à la fonction d'arrêt de l'application :
Et aux différentes fonctions pour écrire du texte à l'écran :
1
2
3
|
void drawText_Solid(int x, int y, const std::string & str, SDL_Color color);
void drawText_Shaded(int x, int y, const std::string & str, SDL_Color color, SDL_Color fond);
void drawText_Blended(int x, int y, const std::string & str, SDL_Color color);
|
Les fonctions et variables privées.
Une fonction pour initialiser SDL :
1
|
void initialisation_SDL(unsigned int width, unsigned int height);
|
Une fonction d'initialisation pour chaque constructeur complet (7 paramètres).
Une fonction pour récupérer les événements :
1
|
void getEvent(SDL_Event* event);
|
Une fonction pour mettre à jour l'intervalle de temps entre deux calculs.
Une fonction qui met l'icon à l'application :
1
|
void openIcon(SDL_Surface* icon);
|
Une fonction pour initialiser SDL :
1
|
void initialisation_SDL(unsigned int width, unsigned int height);
|
Côté variable :
La dernière mesure de temps :
Le temps courant :
Le dernier ticks :
L'intervalle de temps entre deux calculs :
L'instant où l'application a été déclenchée :
Le tableau de booléens pour les événements du clavier :
Le tableau qui associe les touches aux événements :
Un booléen pour dire si l'application s'exécute :
L'écran (si on veut faire de l'affichage ça peut servir) :
Le fond d'écran de l'application :
1
|
SDL_Surface* background;
|
La couleur de fond de l’application :
1
|
Uint32 backgroundColor;
|
L'icon de l'application :
La police de l'application :
Un booléen qui dit si l'image de fond a été ouverte par l'application :
Un booléen qui dit si la police a été ouverte par l'application :
En effet il faut s'assurer que l'application ne va pas détruire une SDL_Surface* qui n'est pas à elle ou fermer une fonte qu'elle n'a pas ouverte.
Voilà un petit résumé de la situation :
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
|
#ifndef SDL_APPLICATION_H
#define SDL_APPLICATION_H
#include <string>
#include <string.h>
#include "time.h"
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#include <iostream>
#include <map>
typedef std::map< SDLKey,bool> KeyStates; typedef std::map<std::string,SDLKey> KeyConf;
/**
@brief Classe qui a pour but de créer une application SDL sans avoir besoin de se trimbaler toute l'initialisation à chaque fois
*/
class SDL_Application
{
public:
SDL_Application(unsigned int width = 640, unsigned int height = 480);
SDL_Application(unsigned int width, unsigned int height, const std::string & titre, const std::string & icon = "");
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 = 0);
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 = 0);
SDL_Application(unsigned int width, unsigned int height, const std::string & titre, const std::string & icon, Uint32 backgroundColor, const std::string & police = "", int taille = 0);
SDL_Application(const SDL_Application & app);
virtual ~SDL_Application();
int executer();
void setTitle(const std::string & titre); void setIcon(SDL_Surface* icon); void setIcon(const std::string & iconFile); void setBackground(SDL_Surface* background); void setBackground(const std::string & backgrounsFile); void setBackgroundColor(Uint32 color); void setBackgroundColor(Uint8 r, Uint8 g, Uint8 b); void setFont(const std::string & police, int taille); void setFont(TTF_Font* font);
SDL_Application & operator = (const SDL_Application & app);
protected:
virtual void draw(SDL_Surface* ecran) =0;
virtual void update(float dt) =0;
virtual void initVar();
void stop();
void addKeyEvent(const std::string action, SDLKey key, bool initValue);
bool keyEventMade(const std::string action);
void drawText_Solid(int x, int y, const std::string & str, SDL_Color color);
void drawText_Shaded(int x, int y, const std::string & str, SDL_Color color, SDL_Color fond);
void drawText_Blended(int x, int y, const std::string & str, SDL_Color color);
private:
void initialisation(const std::string & titre, const std::string & icon, const std::string & backgroundFile, const std::string & police, int taille);
void initialisation(const std::string & titre, const std::string & icon, SDL_Surface* background, const std::string & police, int taille);
void initialisation(const std::string & titre, const std::string & icon, Uint32 backgroundColor, const std::string & police, int taille);
void initialisation_SDL(unsigned int width, unsigned int height);
void copySDL_Application(const SDL_Application & app);
void getEvent(SDL_Event* event);
float updateTicks();
///dernière mesure de temps de l'application (SDL_Ticks)
Uint32 last_time; ///temps courrant
Uint32 current_time; ///dernier ticks
Uint32 lastTick; ///intervalle de temps entre le temps courrant et la dernière mesure de temps de l'application
Uint32 ellapsed_time; ///instant ou l’application a été déclenchée
Uint32 start_time; ///tableau de bool pour les entrées clavier
KeyStates keystates; ///association actions touches
KeyConf keyconf;
///dit si il y a exécution
bool run; ///écran de l'application
SDL_Surface* ecran; ///dit si l'icon à été ouvert par la classe
bool isMyIcon; ///icone de l'application
SDL_Surface* icon; ///dit si le l'image de fond a été ouverte par l’application
bool isMyBackground; ///image de fond
SDL_Surface* background; ///couleur de fond
Uint32 backgroundColor; ///dit si la fonte a été ouverte par l'application
bool isMyFont; ///fonte de l'application
TTF_Font *font;};
#endif
|
Maintenant nous pouvons écrire le fichier sdl_application.cpp.
|