Bonjour à tous, je profite de mon week end amplement mérité pour vous offrir un modèle de programmation ce coup ci, sans doute connu des programmeurs un peu expérimentés il s'agit de créer une classe de base abstraite d'où l'on fait dériver des classes filles spécialisées pour chaque problème et auquel on accedera simplement via un tableau polymorphique
Et on optimise l'optimisation ensuite voir le message suivant si vous n'avez pas peur des maux de crâne et si vous connaissez les pointeurs de fonctions en C++ En français dans le texte ?

......

, bon pas grave je vais expliquer point par point.
I)Switch, case et breakOn se placer dans une situation de jeux vidéo pour faciliter la compréhension. Afin de gérer les entrée clavier et les evenements divers a vrai dire nous allons créé une classe (engine_event pour l'occasion) qui grace à un appel via une fonction regardera quel est le dernier évennement en date.
Pour ce faire nous déclarons donc engine_event :
Citer:
class engine_event {
public :
// **********************************
engine_event() ;
// **********************************
virtual ~engine_event() ;
// **********************************
void frame() ;
// **********************************
private :
// **********************************
SDL_Event event ;
/* variable en charge de l'evenement */
// **********************************
} ;
J'ai volontairement simplifié drastiquement la classe bien entendu en ne prennant en compte aucun moyen de dialoguer avec l'extérieur, c'est un autre problème que j'aborderais un autre moment.
Analysons nous avons donc un constructeur, un destructeur virtuel (de base définissez toujours virtuels les destructeurs de toutes vos classes, cela permettra de ne pas avoir à trembler en cas d'un appelle à
delete après utilisation de l'héritage) une fonction frame() qui est en fait l'appel au moteur (donc tout ce que l'on a a faire pour que le moteur chercher le dernier évenement et d'appeller frame) et une variable interne que vous reconnaitrez.
Oui mais voilà maintenant, que mettre dans la définition de frame ?
l'idée de base est de faire ainsi (ne pas tenir compte des §, ils servent a garder la mise en forme) :
Citer:
engine_event::frame() {
SDL_PollEvent(event) ;
switch (event.type) {
_______ case SDL_QUIT :
____________//action dans ce tel cas ....
_______ case SDL_KEYDOWN :
____________ switch (event.key.keysym.sym) {
___________________ case SDLK_UP :
___________________ //ect .....
_____________ }
_______ //ect .....
}
Je supose que personne ne sera choqué si je précise que cette solution est assez mauvaise un exemple simple imaginons que l'evenement voulut soit le dernier ! le programme va quand même vérifier toutes les posibilité jusqu'à trouver le bon (et donc perdre un certain temps jusqu'en bas), pire imaginons qu'à ce moment du jeu seul un évenement clavier soit utile (lorsque des messages défilent par exemple) l'ordinateur ferra tout une liste de vérification totalement inutile quand même.

sur un système aussi basique que le moteur d'evennement la perte niveau temps est pas forcément négligeable diront nous. De plus le système est assez peu évolutif et au bout d'un moment va être très lourd niveau maintenace.
Alors vous voulez une solution hein ?

, naaaa ze la donne pas, ou alors si mais il faudra m'appeller maître

et me vénerer

.
(

)
Quoi ?

pourquoi vous faite cette tête là ? euh .... rangez ces épée s'il vous plait ..... non pas les haches ! Ok je dis !

zen ...... *retourne au tableau*
II)Penser ObjetLa solution demande que vous connaissiez très bien les mécanismes suivant : héritage, polymorphisme, méthode virtuelle et éventuellement ce que j'ai zapé en cour de route.
la première remarque à faire est que nous n'avons pas besoin à tout instant des vérifier toujours les mêmes évenements selon "l'état" du système (en cinématique/combat/dialogues ect) nous allons donc incorporer une variable dans notre moteur d'évenement qui gardera cela en mémoire :
Citer:
class engine_event : public engine {
public :
// **********************************
engine_event() ;
// **********************************
virtual ~engine_event() ;
// **********************************
void frame() ;
// **********************************
private :
// **********************************
SDL_Event event ;
/* variable en charge de l'evenement */
// **********************************
int game_stat
// **********************************
} ;
Voilà pour le moment c'est assez simple c'est maintenant que tout va se corser. Alors tennez vous bien
Ce que nous allons faire c'est définir une classe de base abstraite [respirez j'explique ensuite] d'écouteur d'évenement.
Globalement cela veut dire une classe tel :
Citer:
class modulate_catch {
public :
modulate_catch() ;
virtual ~modulate_catch() ;
virtual void what(SDL_Event&) = 0 ;
}
Analysons simplement on trouve un constructeur et un destructeur (toujours virtuel !) ainsi qu'une fonction virtuelle pure nommée what.
Je n'ai pas vraiment la possibilité de vous faire un cour sur le polymorphisme ici mais pour rappel une fonction virtuelle pure doit obligatoirement être redéfinie dans les classes dérivées.
Je pense que vous commencez à voir, modulate_catch est abstraite (vu que contenant une fonction virtuelle pure) mais ensuite nous allons définir des classes dérivée de celle ci pour chaque état du système :
Citer:
class in_pause : public modulate_catch {
public :
in_pause() ;
virtual ~in_pause() ;
virtual void what(SDL_Event&) ;
}
Citer:
class in_battle : public modulate_catch {
public :
in_battle() ;
virtual ~modulate_catch() ;
virtual void what(SDL_Event&) ;
}
Citer:
class in_dialogue : public modulate_catch {
public :
in_dialogue() ;
virtual ~in_dialogue() ;
virtual void what(SDL_Event&) ;
}
Et pour chaque module nous décrirons un switch restrint à ce qui nous interresse actuellement :
Citer:
in_pause::what(SDL_Event &event) {
switch (event.type) {
case SDL_KEYDOWN :
switch (event.key.keysym.sym) {
case SDLK_PAUSE :
retirer la pause....
break ;
}
}
Citer:
in_battle::what(SDL_Event &event) {
switch (event.type) {
case SDL_KEYDOWN :
switch (event.key.keysym.sym) {
case SDLK_A :
faire attaquer....
break ;
case SDLK_B :
mettre en défense....
break ;
}
}
Maitenant il nous faut donc créer un tableau de pointeur vers des modulate_catch dans notre classe de moteur d'évenement :
Citer:
class engine_event : public engine {
public :
// **********************************
engine_event() ;
// **********************************
virtual ~engine_event() ;
// **********************************
void frame() ;
// **********************************
private :
// **********************************
SDL_Event event ;
/* variable en charge de l'evenement */
// **********************************
int game_stat
// **********************************
modulate_catch* catch_system[NBR_MODULATE_CATCH] ;
// **********************************
} ;
Et ensuite on définit un état par un numéro (de 0 à NBR_MODULATE_CATCH -1 bien sûr) pour cela il suffit d'utiliser quelques #define ou un enum.
reste à penser au constructeur et au destructeur :
Citer:
engine_event::engine_event() {
catch_system[IN_PAUSE] = new in_start() ;
catch_system[IN_BATTLE] = new in_battle() ;
catch_system[IN_DIALOGUE] = new in_dialogue() ;
(sous entendu ici IN_PAUSE = 0, IN_BATTLE = 1 ect)
Citer:
engine_event::~engine_event() {
for(int i = 0 ; i < NBR_MODULATE_CATCH ; i++) {delete catch_system ;}
}
Et maintenant il est très simple de voir la méthode frame() :
Citer:
engine_event::frame() {
SDL_PollEvent(event) ;
catch_system[game_stat]->what(event) ; //On aura toujours ici le minimum de vérification néccéssaire
}
Ainsi il suffit de faire varier la variable game_stat a chaque changement néccéssaire.
III)Le revers de la médailleLes programmeurs en C++ (et même les autres d'ailleurs) le savent bien à chaque médaille son revers, ici on gagne bien souvent en vitesse d'éxecution (mais aussi en maintient du code) mais cependant l'existence des modules prend plus de place en mémoire vive qu'un code utilisant switch. Il ne faut cependant pas exagerer trop ce dernier point mais il faut le connaitre.
Voilà pour cette petite "astuce" assez violente au niveau de la programmation quand même j'avoue (mais que voulez vous on a rien sans rien). Sur ce je vous laisse et vous souhaite une bonne journée à tous les programmeurs/makeurs/personnes qui se seraient paumés ici et à la prochaine
