IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Gestionnaire d'évènements pour un jeu


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    136
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 136
    Points : 71
    Points
    71
    Par défaut Gestionnaire d'évènements pour un jeu
    Bonjour,

    Je souhaite faire un jeu en C++ avec la SFML, et pour cela je veux créer un gestionnaire d'évènements qui me permettrait de reporter tout évènement comme le début d'une partie, la fin d'un niveau,... et le transmettre à chaque partie du programme le souhaitant (via des fonctions de rappel passées à la classe).
    Le vrai problème que je rencontre est le stockage des évènements (via une classe dédiée). Cette classe sera clairement au centre du programme donc il me parait risqué (et déconseillé) d'utiliser des dynamic_cast pour obtenir les informations propres à un évènement (Evenement étant une classe virtuelle pure dans ce cas).
    Est-ce que ce serait une solution convaincante d'intégrer au code les types d'évènements?
    Par exemple Evenement contiendrait un pointeur vers chaque type de donnée qu'il peut être, un seul de ces pointeurs étant effectivement utilisé.

    Bref je bloque un peu sur un problème simple mais je souhaite surtout m'améliorer alors si vous avez mieux (sans doute) n'hésitez pas

    Merci

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Ce que tu pourrais faire, c'est, tout simplement, envisager le fait qu'un événement va... provoquer quelque chose...

    Tu pourrais donc avoir une classe de base Event proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Event
    {
        public:
            Event();
            virtual ~Event();
            virtual void onEvent() = 0;
    };
    et, d'un autre coté, une classe Sender qui serait une classe de base dont dérivent... toutes les classes susceptibles de provoquer un événement.

    A partir de là, tu peux envisager de dériver d'autres classes d'événements plus "particulières", dont le constructeur prendrait les informations "manquantes".

    Ainsi, un bouton aurait sans doute un comportement au moment où on clique dessus, et prendrait sans doute la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Button : public Sender
    {
        public:
            void onButtonClick()
            {
                /*...*/
            }
    };
    Tu pourrais donc avoir un événement ButtonClick qui dériverait de Event (en fait, qui dériverait bien plus surement de Click, qui dériverait lui-même de Event, mais ce n'est qu'un détail ) proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class ButtonClick : public Event /* ( normalement ce serait sans doute
                                      * public Click )
                                      */
    {
        public:
            ButtonClick(Sender * send):send_(send);
            virtual ~ButtonClick(){}
            virtual void onEvent()
            {
                dynamic_cast<Button*>(send_)->onButtonClick();
            }
        private:
            Sender * send_;
    };
    Et tu suivrais une logique similaire pour les différents éléments capables de provoquer des événéments (foncteurs, callbak, templates et "type erasure" te viendront sans doute bien en aide sur ce coup )

    Enfin, ton gestionnaire d'événements serait implémenté sous la forme d'une file d'appels (queue en anglais), ou d'une "priority queue" proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    class EventManager
    {
        public:
            /* le gestionnaire d'événements serait sans doute un singleton :-D
             */
            static EventManager & instance()
            {
                static EventManager inst;
                return inst;
            }
            /* rajoute un événement à la file  */
            void addNextEvent( Event * ev)
            {
                items_.push(ev);
                /* provoque la réaction au premier événement */
                    callFirstEvent();
            }
            void callFirstEvent()
            {
                /* il y a peut être plusieurs événement en attente
                 * Si tel est le cas, nous veillons à tous les gérer ;) 
                 */
                while(! items_.empty)
                {
                     items_.front()->onEvent();
                     delete items_.front();
                     items_.pop();
                }
            }
        private:
            EventManager():items_(){}
            ~EventManager()
            {
                while(! items_.empty)
                {
                     delete items_.front();
                     items_.pop();
                }
            }
            std::queue<Event*> items_;
    };
    Tu utilisera le gestionnaire d'événements sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    EventManager::instance().addNextEvent(new ButtonClick(leBouton));
    où "leBouton" correspond au pointeur vers l'instance du bouton sur lequel on a cliqué
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    A mon avis c'est pas une bonne idée d'utiliser un dynamic_cast a ce niveau là, ça peut être très couteux dans certains jeux, a tester donc. Par contre c'est le plus simple, donc certainement la meilleure solution pour commencer.

    Personellement j'utilise dans mon jeu une variante de ce qui est très bien décris dans cet (excellent) article : http://www.gamedev.net/reference/pro...s/effeventcpp/
    Il utilise aussi dynamic_cast mais de manière moins...intempestive disons.

    Avant j'utilisais le code qui est dispo là: http://code.google.com/p/game-core/s...pec=svn19&r=18 (voir eventuellement les autres classes)
    mais j'ai pas mal changé ce code depuis, inspiré entre autre par l'article dont je parlais.

    Je mettrais en ligne mon système (qui reste "basique") dans la journée au cas ou ça en interesse (dans le trunk du même projet que précédemment). Je ne pense pas que ce soit une référence mais au moins ça te fais des exemples.

    Si tu ne veux pas te compliquer la vie, de toutes manières, fait simple, comme koala01 te l'a décris.

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    136
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 136
    Points : 71
    Points
    71
    Par défaut
    Merci koala01 pour ta réponse mais ce n'est pas du tout ce à quoi je pensais :S
    mais ça m'intéresse bien sûr.

    Klaim : je vais éplucher tout ça merci!


    Au départ mon idée était, comme les types d'évènement et leur nombre sont connus à l'exécution, d'avoir un pointeur vers chacun d'entre eux comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    enum Type{type1, type2 /*...*/};
     
    class event
    {
    public:
    /** des méthodes pour avoir les pointeurs*/
    private:
    Type le_type;
    Type1* p1; //un seul des pointeurs n'est pas égal à NULL
    Type2* p2;
    /*...*/
     
    };
     
    ///utilisation
    Type le_type = un_event.getType();
     
    switch (le_type) /*...*/
    Le gros problème est l'occupation mémoire à mon avis, mais en échange de l'absence de cast. En se débrouillant bien, on peut même organiser les types d'évènements pour ne pas en avoir plus de 10-15 je pense (avec des sous-évènements reprenant le système).

  5. #5
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Plomeg Voir le message
    Merci koala01 pour ta réponse mais ce n'est pas du tout ce à quoi je pensais :S
    mais ça m'intéresse bien sûr.

    Klaim : je vais éplucher tout ça merci!


    Au départ mon idée était, comme les types d'évènement et leur nombre sont connus à l'exécution, d'avoir un pointeur vers chacun d'entre eux comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    enum Type{type1, type2 /*...*/};
     
    class event
    {
    public:
    /** des méthodes pour avoir les pointeurs*/
    private:
    Type le_type;
    Type1* p1; //un seul des pointeurs n'est pas égal à NULL
    Type2* p2;
    /*...*/
     
    };
     
    ///utilisation
    Type le_type = un_event.getType();
     
    switch (le_type) /*...*/
    Le gros problème est l'occupation mémoire à mon avis, mais en échange de l'absence de cast. En se débrouillant bien, on peut même organiser les types d'évènements pour ne pas en avoir plus de 10-15 je pense (avec des sous-évènements reprenant le système).
    A vrai dire, tu évite un transtypage, mais, d'un autre coté, tu va te retrouver avec autant de pointeurs que de classes d'événements concretes...

    Tant que tu n'as deux ou trois événements à gérer, nous pourrions estimer que c'est faisable, mais, si tes différents événements commencent à se multiplier ( ce qui risque fort d'arriver ), tu vas te retrouver avec une classe qui va gérer une vingtaine ou une trentaine de pointeurs différents ( ce qui fait 20 ou 30 fois 4 à 8 bytes, mine de rien) là où... le polymorphisme serait amplement suffisant
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    136
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 136
    Points : 71
    Points
    71
    Par défaut
    Bon je pense avoir compris.
    Merci!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Gestionnaire de son pour un jeu video
    Par lordmyko dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 16/08/2011, 16h44
  2. Réponses: 4
    Dernier message: 17/02/2010, 10h09
  3. Gestionnaire d'évènements pour les fichiers sur disque
    Par chourmo dans le forum Composants VCL
    Réponses: 2
    Dernier message: 01/03/2006, 16h18
  4. Gestionnaire d'événements pour la souris en assembleur
    Par bassim dans le forum Assembleur
    Réponses: 2
    Dernier message: 09/12/2005, 23h45
  5. Quel style de DirectX pour un jeu 2D ?
    Par delire8 dans le forum DirectX
    Réponses: 34
    Dernier message: 31/07/2003, 00h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo