Problème de design objet

Problème de design objet - C++ - Programmation

Marsh Posté le 15-03-2004 à 21:39:07    

J'aimerais faire une sorte de "game engine". Pour cela, j'ai pensé le décomposer en plusieurs parties, théoriquement indépendantes les unes des autres.
Par exemple, il pourrait y avoir un module consacré pour le son, un autre pour les graphismes, un autre pour le rezo...
 
Le problème c'est que chacun de ces modules devrait etre accessible de n'importe où dans le programme. Par exemple, dans la fonction qui s'ocuppe de faire tirer le personnage, j'aimerais produire un son de coup de feu. Il faudrait donc que je puisse accéder au module 'SoundManager'. Mais le truc, c'est que je n'ai pas envie de créer une instance de SoundManager a chaque fois que je veux jouer un son.
Donc, j'ai pensé a plusieurs solutions que je trouve pas tellement élégantes.
 
- On commence par la pire:
Je mets toutes les fonctions membres de SoundManager en static ce qui a mon humble avis, est vraiment ce qui peut ce faire de plus crade... enfin peut etre que je me trompe. :)
Pour jouer un son, ca donnerait:

Code :
  1. SoundMng::PlaySound(...);


 
- Un peu moins crade mais dans le meme registre d'idées:
Regrouper tous les modules dans une classe GameEngine, encore une fois en static. Mais ca eviter que tous les membres de tous les modules soient en static. Donc en gros, ca me donnerait ca:

Code :
  1. class GameEngine
  2. {
  3. public:
  4.    static SoundManager SoundMng;
  5.    static VideoManager VideoMng;
  6. ...
  7. };
  8. //Et donc, pour jouer un son, il faudrait que je fasse:
  9. GameEngine::SoundMng.PlaySound(...);


 
- J'ai pensé aussi à créer une instance de chaque module en tant que variable globale. Je pourrais alors accéder a mon SoundManager sans problème depuis partout, mais je sais pas, je trouve ca un peu crade aussi.

Code :
  1. g_SoundMng.PlaySound(...);


 
- Enfin, jpeux faire de chacun des modules un singleton:

Code :
  1. SoundManager::GetInstancePointer()->PlaySound(...);


 
 
J'aimerais avoir votre avis sur toutes ces propositions ou alors meme, que vous en proposiez de nouvelles plus adaptées.

Reply

Marsh Posté le 15-03-2004 à 21:39:07   

Reply

Marsh Posté le 15-03-2004 à 21:58:40    

ben tu peux faire une class "Son" qui connait le soundManager d'ou elle est issu, et donner cette class "Son" a ton gugus.
 
genre :

Code :
  1. class Soldat
  2. {
  3. Son *bruitDeFusil;
  4. }


et  
 

Code :
  1. void Soldat::tir()
  2. {
  3. bruitDeFusil->joue();
  4. }

Reply

Marsh Posté le 15-03-2004 à 22:05:36    

Pas mal, j'y avait pas pensé :)
Mais du coté de la classe son, tu implémenterais ça comment?
 
Un truc genre:

Code :
  1. class Son
  2. {
  3. private:
  4.    static SoundManager *SoundMng;
  5. };


 
ou quelquechose de complètement différent?
 
 
En tout cas, merci pour ta réponse! :)


Message édité par _momone_ le 15-03-2004 à 22:05:59
Reply

Marsh Posté le 15-03-2004 à 22:07:40    

pas de static, non :o
snul le static :o
chaipas, je sais pas comment est foutu ton bazard. Ptet un constructeur privée, une relation d'amitié avec SoundManager et soundManager qui crée des instance de Son
 
 
genre
 
Son *prout = SoundManager->load("prout.wav" );
 
enfin je te dis ca au debotté hein ?


Message édité par chrisbk le 15-03-2004 à 22:07:49
Reply

Marsh Posté le 15-03-2004 à 22:13:29    

Citation :

Son *prout = SoundManager->load("prout.wav" );


Ouaip, mais ca change pas tellement le problème, il faut toujours que je trouve un moyen pour accéder à SoundManager.
 
Sinon, jsuis d'accord avec toi, le static, c'est pas super beau... :|

Reply

Marsh Posté le 15-03-2004 à 22:44:56    

Il y a une autre solution (celle que j'utilise actuellement) mais qui est nettement plus complexe et qui demande un effort de programmation au départ assez conséquent.
 
Voci comment se décompe cette solution (je vais essayé de vulgariser) :
 
* Chaque module de traitement hérite d'une classe de type "boite aux lettres".
 
* Toutes les classes "boite aux lettres" communiquent entre elles via un unique "module de messagerie (singleton)".
 
* Les modules de traitement s'échangent des message standardisés (basés sur une classe message de base non typée) que le "module de messagerie" aiguille.
 
Les avantages de cette solution sont multiples :
 
* une architecture evolutive et extensible.
* des possibilités de trace/debug interessantes.
* ...
 
L'inconvénient majeur est la lourdeur pour des applications simples avec peu de modules de traitement. La commutation (nombre de messages aiguillés par seconde) demande bcp de ressources cpu/mémoire par rapport à une architecture optimisée.
 
D'autre part, si tu ajoutes au "module de messagerie" une fonction de communication réseau, tu peux réaliser une application complexe dont les modules s'executent sur des machines différentes et distantes via Internet ou un réseau local.
 
Cordialement,
   Xter.


Message édité par xterminhate le 15-03-2004 à 22:46:48
Reply

Marsh Posté le 15-03-2004 à 22:50:04    

Cela dit, pour reprendre l'idée de chrisbk, un singleton repond partiellement à ton problème, à condition que chaque type de module soit unique : 1 x son, 1 x video, 1...
 
Cordialement,
   Xter.
 

Reply

Marsh Posté le 15-03-2004 à 23:12:13    

bin il peut avoir 1 seule instance de son soundmanager, qui contient une liste (un cache en qq sortes) de sons chargés, (un std::map par exemple) puis ses objets (soldat par exemple) doivent avoir acces au son dans la liste


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 15-03-2004 à 23:25:38    

Oui tout a fait.

Reply

Marsh Posté le 16-03-2004 à 13:42:10    

c est pas au soldat de faire le bruit du fulsil !
 
le tir du soldat ne devrait faire qu'un truc su style
if (arme)
 arme->tir()
 
 
bon vla ma contribution.
 
 
les arme derivant toutes d'une classe arme de base
qui prendrait en constructeur un soundmanager*  
 
(cree par ton engine au demarrage)
 
et chaque arme appelle le bon play sur le sound manager dans sa methode tir ( qui est virtuelle pure dans la classe arme de base)
 
 c'est  donc l arme qui produit le bruit (logique)
bazooka::tir()
{
 sndmanager->playbazooka(); // tu peux faire ton propre snd manager qui herite de l existant pour avoir des noms de methode explicite aussi..
 pis dautre truc du style
emettrefummee()...
}
 
 
ect...


Message édité par frenchkiss le 16-03-2004 à 13:44:57
Reply

Marsh Posté le 16-03-2004 à 13:42:10   

Reply

Marsh Posté le 16-03-2004 à 19:32:33    

Ok merci pour toutes vos réponses!
 
Jtrouve l'idée de xterminhate, pour faire communiquer les différents modules entre eux à l'aide d'une classe unique de "messagerie", plutot astucieuse et ca m'a donné des idées pour implémenter d'autres choses :)
 
Sinon, le probleme avec la solution de frenchkiss, qui a l'air d'être à peu près la même que celle de chrisbk, c'est qu'il faut toujours passer un pointeur vers le SoundManager au constructeur de bazooka. Et justement mon problème c'est de savoir comment connaitre l'adresse du SoundManager à partir de n'importe où dans le prog (si j'ai par exemple envie de creer un bazooka en plein milieu du jeu).
 
Donc je pense m'orienter vers la solution:

Citation :

Regrouper tous les modules dans une classe GameEngine, encore une fois en static. Mais ca eviter que tous les membres de tous les modules soient en static. Donc en gros, ca me donnerait ca:

Code :
  1. class GameEngine
  2. {
  3.   public:
  4.      static SoundManager SoundMng;
  5.      static VideoManager VideoMng;
  6.   ...
  7. };
  8.  
  9. //Et donc, pour jouer un son, il faudrait que je fasse:
  10. GameEngine::SoundMng.PlaySound(...);



 
J'aimerais avoir votre avis sur cette solution.
Et vous ne pensez pas que ca serait pas plus propre de faire de SoundManager une variable globale, ou un singleton?
 
Merci

Reply

Marsh Posté le 16-03-2004 à 19:43:57    

Connais tu le design pattern singleton ? Il est tres facile de récupérer le pointeur sur l'instance unique d'un singleton n'importe ou dans ton programme.

Code :
  1. class soundmanager // programmé selon le design singleton...
  2. {
  3. public:
  4.    static soundmanager * GetInstance() { if( smInstance == NULL ) smInstance = new soundmanager; return smInstance; }
  5.    playsound( std::string & );
  6. private:
  7.    soundmanager();
  8.    ~soundmanager();
  9.    soundmanager( soundmanager & );
  10.    soundmanager & operator= ( soundmanager & );
  11.    static soundmanager * smInstance;
  12. }
  13. soundmanager * soundmanager::smInstance = NULL;
  14. class player
  15. {
  16. public:
  17.    player();
  18.    tir();
  19. private:
  20.    soundmanager * sm; // pas tres judicieux comme nom :)
  21. };
  22. player::player()
  23. {
  24.    sm = soundmanager::GetInstance();
  25. }
  26. player::tir()
  27. {
  28.    sm->playsound("panTmort" );
  29. }


 
Cordialement,
   Xter.


Message édité par xterminhate le 16-03-2004 à 19:48:56
Reply

Marsh Posté le 16-03-2004 à 22:16:01    

Le singletons m'ont l'air de correspondre en effet à ce que je cherche à faire ;)

Reply

Marsh Posté le 17-03-2004 à 11:38:42    

non ca n a rien a voir avec ce que propose chrisb
 
de toute facon si t as envie de creer un bazooka encore une fois  
il te faut un object du style " fabrique d'arme "
aui pourrait eventuellement etre un singleton mais je pense pas que ca soit tres uilise
puisqu'a priori tu pourra construire une arme que dans ceraint cas particulier ( chai pas moi genre fabrique d arme)
et a toi de t arranger pour avoir toute l info necessaire au moment ou tu construit ton jouet... etc..
 
c'est un travail de conception avant tout , eventuellement tu peux lire un bouquin sur les design pattern . C'est plein de bon sens avec un mot technique dessus mais apparement ca t'aiderai pour pouvoir penser un peu plus " object"  
 
salut  
FK

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed