5.2.2 Écrire apptest.cpp

Une fois de plus on commence le fichier apptest.cpp sans changer nos habitudes :

1
2
3
#include "apptest.h"

using namespace std;

Le constructeur par défaut :

1
2
3
4
5
AppTest::AppTest()
	:SDL_Application()
{
	this->init();
}

Il ne faut pas oublier d'appeler le constructeur par défaut de SDL_Application.

Le constructeur complet :

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

Bien sur tout les paramètre du constructeur ne sont pas forcément pour le constructeur de la classe mère.

Dans les deux fonctions précédentes il ne faut pas non plus oublier d'appeler la fonction init de la classe, sinon pas de valeur par défaut.

Le constructeur de copie :

1
2
3
4
5
AppTest::AppTest(const AppTest & app)
	:SDL_Application(app)
{

}

On appelle le constructeur de copie de la classe mère pour que la copie ne soit pas permise.

Le destructeur :

1
2
3
4
5
AppTest::~AppTest(){
	if(this->vaisseau != NULL){
		SDL_FreeSurface(this->vaisseau);
	}
}

Ce n'est pas la peine d'appeler le destructeur de la classe mère, car c'est automatique.

Récupération de l'image du vaisseau :

1
2
3
void AppTest::setVaisseau(const std::string & vaisseau){
	this->vaisseau = IMG_Load(vaisseau.c_str());
}

L'affichage :

1
2
3
void AppTest::draw(SDL_Surface* ecran){
	if(vaisseau != NULL){SDL_BlitSurface(this->vaisseau, NULL, ecran, &pos);}
}

On s'assure quand même que l'image du vaisseau existe.

Le calcul et la gestion d’événement en toute simplicité :

1
2
3
4
5
6
7
void AppTest::update(float dt){
	//on gère les événements
	if(keyEventMade("UP")) this->pos.y--;
	if(keyEventMade("DOWN")) this->pos.y++;
	if(keyEventMade("LEFT")) this->pos.x--;
	if(keyEventMade("RIGHT")) this->pos.x++;
}

L'avantage c'est que l'on se démarque des touches proprement dite avec ce système d’événement et on peu enfin gérer plusieurs événements à la fois. Vous allez enfin pouvoir aller en biais.

Pour être un peu plus rigoureux on devrait faire :

1
2
3
4
5
6
7
void AppTest::update(float dt){
	//on gère les événements
	if(keyEventMade("UP")) this->pos.y--;
	else if(keyEventMade("DOWN")) this->pos.y++;
	if(keyEventMade("LEFT")) this->pos.x--;
	else if(keyEventMade("RIGHT")) this->pos.x++;
}

L'avantage c'est que là on ne peut pas avoir d'événements contraires, par exemple aller à droite et à gauche.

L'initialisation et la déclaration des événements :

1
2
3
4
5
6
7
8
9
10
11
void AppTest::init(){
	//on ajoute des touches a gérer
	this->addKeyEvent("UP", SDLK_UP false);
	this->addKeyEvent("DOWN", SDLK_DOWN, false);
	this->addKeyEvent("LEFT", SDLK_LEFT, false);
	this->addKeyEvent("RIGHT", SDLK_RIGHT, false);
	//on initialise les variables par défaut
	this->vaisseau = NULL;
	this->pos.x = 0;
	this->pos.y = 0;
}

Bien sur là il faut dire quelle touche correspond à quel événement mais dans ce cas on pourrait faire une fonction pour que l'utilisateur rentre ses touches de contrôle lui même (un menu avec les événement et un SDL_WaitEvent qui renverra la touche dès que le joueur appuiera). Mais dans cette fonction vous devez quand même utiliser un bon vieux switch.

Voilà ce que nous avons écris :

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
#include "apptest.h"

using namespace std;

const float WAIT_BEGIN = 10;
//fichier de configuration des images
const string FILE_CONFIG_IMAGE = "../image/IMGconfigFile.txt";

//constructeur par défaut
AppTest::AppTest()
	:SDL_Application()
{
	this->init();
}

//constructeur utilisé (il y a plein de constructeur dans la classe SDL_Application
AppTest::AppTest(unsigned int width, unsigned int height, std::string titre, std::string icon, std::string backgroundFile, std::string police, int taille)
	:SDL_Application(width, height, titre, icon, backgroundFile, police, taille)
{
	this->init();
}

//destructeur
AppTest::~AppTest(){}

//initialisation de l'image du vaisseau
void AppTest::setVaisseau(const std::string & vaisseau){
	this->vaisseau = IMG_Load(vaisseau.c_str());
}


//affichage
void AppTest::draw(SDL_Surface* ecran){
	if(vaisseau != NULL){SDL_BlitSurface(this->vaisseau, NULL, ecran, &pos);}
	if(*it != NULL){SDL_BlitSurface(*it, NULL, ecran, &posTux);}
}

//mise à jour et calculs
void AppTest::update(float dt){
	this->wait = this->wait - 0.4;
	if(this->wait < 0){
		this->wait = WAIT_BEGIN;
		it++;
		if(it == this->sprite->end()) it = this->sprite->begin();
	}
}

//initialisation
void AppTest::init(){
	this->vaisseau = NULL;
	this->pos.x = 0;
	this->pos.y = 0;
	this->bibliotheque.load(FILE_CONFIG_IMAGE);
	this->vaisseau = this->bibliotheque.getImage("VAISSEAU");
	this->sprite = this->bibliotheque.getSprite("TUXWALK");
	this->it = this->sprite->begin();
	this->wait = WAIT_BEGIN;
	this->posTux.x = 200;
	this->posTux.y = 200;
}

La classe étant fini (pas le cours, la classe) je vous invite à faire le main.cpp.