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

Langage C++ Discussion :

Quel est la méthode la plus rapide ?


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut Quel est la méthode la plus rapide ?
    Salut, je voudrais en fait passer les événements de différentes librairies à une interface commune.

    Alors, j'ai deux solution pour passer les types de événements et les paramètres des événements, cependant je ne sais pas pour laquelle opter.

    1ère solution :

    Je fais un if sur le type de l'événement et en fonction du type de l'événement j'affecte les bons paramètres un exemple :

    Code cpp : 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
     
    SystemEvent popEvent () {
               sf::Event event;
               if (window.pollEvent(event)) {
                   if (event.type == sf::Event::Closed) {
                       SystemEvent sysevent;
                       sysevent.eventID = sf::Event::Closed;
                       sysevent.info.origin = SystemEvent::Origin::Window;
                       sysevent.info.type = SystemEvent::Type::NO_TYPE;
                       sysevent.paramID = SystemEvent::Type::NO_TYPE;
                       return sysevent;
                       //Nothing.
                   } else if (event.type == sf::Event::Resized) {
                       //....
                   }
               }
    }

    La seconde solution est de parcourir tout les états (fenêtre, clavier, souris, etc...) et de générer un événement si il y a un changement d'état. (Ce qui serait plus long si il y a beaucoup d'état à vérifier comme par exemple pour vérifier l'était de chaque touche du clavier. (Mais il y aura moins de if)

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    //Exécuter à chaque tout de boucle.
    void produceEvents () {
           for (unsigned int i = 0; i < sf::Keyboard::Key::Count, i++) {
                if (sf::Keyboard::isKeyPressed(i) || keyStates[i] !=(sf::Keyboard::isKeyPressed(i))  {
                    keyStates[i] = !keyStates[i];
                    //On créer l'événement et ou l'ajoute dans la pile.
                }
           }
    }
    //Et on fait la même chose pour la fenêtre, la souris, etc...
    Faut voir avec la complexité maintenant mais, je n'ai jamais très bien compris comment la mesurer.

    Merci d'avance pour votre aide.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Après réflexion je vais opter pour la seconde méthode, le fait que pollEvent n'envoie plus d'event dès qu'une seule touche est relâchée. (ce qui est embêtant si plusieurs touche sont pressées en même temps et qu'on ne veut relâcher qu'une seule touche) me gêne.

    Donc j'aimerais générer les events à ma façon.

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    SFML est sensé être un détail d'implémentation, tu as normalement ton propre système. SFML se plug dans l'application principale, et l'idée est juste de le dispatcher.
    Ce qui donne chez moi, dans la boucle principale (ou dans un thread à part qui push pour le main thread)
    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
    sf::Event event;
    		while (window.pollEvent(event))
    		{
    			switch (event.type)
    			{
    			case sf::Event::Closed:
    				window.close();
    				break;
    			case sf::Event::TextEntered:
    				theGame.GetController().OnTextEntered(event.text.unicode);
    				break;
    			case sf::Event::KeyPressed:
    				theGame.GetController().OnKeyPressed(event.key.code);
    				break;
    			case sf::Event::KeyReleased:
    				if (event.key.code == sf::Keyboard::F12)
    					theGame.GetRenderer()->Screenshot(BouSdK::Time::FormatTimestamp(BouSdK::Time::CurrentTimestamp(), "./Screens/%Y-%m-%d_%H-%M-%S.png").c_str());
     
    				theGame.GetController().OnKeyReleased(event.key.code);
    				break;
    			case sf::Event::MouseWheelMoved:
    				theGame.GetController().OnWheel(event.mouseWheel.delta);
    				break;
    			case sf::Event::MouseButtonPressed:
    				theGame.GetController().OnClick(event.mouseButton.button);
    				break;
    			case sf::Event::MouseButtonReleased:
    				theGame.GetController().OnClickReleased(event.mouseButton.button);
    				break;
    			case sf::Event::MouseMoved:
    				theGame.GetController().OnMove(event.mouseMove.x, event.mouseMove.y);
    				break;
    			case sf::Event::MouseEntered:
    				theGame.GetController().OnMouseEnter();
    				break;
    			case sf::Event::MouseLeft:
    				theGame.GetController().OnMouseLeft();
    				break;
    			}
    		}
    Le GetController est une classe sur laquelle j'enregistre mes controlleurs d'évènements (GuiManager, Gameplay, ScriptManager, ...) qui dispatch à leurs acteurs si nécessaire.

    le fait que pollEvent n'envoie plus d'event dès qu'une seule touche est relâchée. (ce qui est embêtant si plusieurs touche sont pressées en même temps et qu'on ne veut relâcher qu'une seule touche) me gêne
    T'es sur que t'as compris comment ça marche ?
    que pollEvent ne retourne rien quand il ne se passe rien c'est.. normal
    à chaque frame tu vas boucler sur l'ensemble des touches du clavier, manette, souris, ... ? bonjour les perfs

    pour avoir régulièrement un évènement lors du maintien d'une touche il faut utiliser RenderWindow::setKeyRepeatEnabledta solution est le meilleur moyen de rater des évènements : je relache et rappuye une touche dans la même frame -> tu le détectes pas
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bonjour,

    pour avoir régulièrement un évènement lors du maintien d'une touche il faut utiliser RenderWindow::setKeyRepeatEnabledta solution est le meilleur moyen de rater des évènements : je relache et rappuye une touche dans la même frame -> tu le détectes pas
    C'est encore pire .
    Non seulement tu va générer un événement à chaque "tour" (au lieu d'avoir un évent de début et de fin), bonjour les perfs .
    Mais en plus, tu peux louper pas mal d'événements si tu as déjà plusieurs touches d'enfoncées sans compter que tu attaques le principe d'encapsulation à grands coups de hache.

    Le tout serait de savoir si on a une garantie que les événements d'appuis et de relâchements sont bien générés même s'il y a déjà plusieurs touches d'enfoncées.
    Si c'est bien générés, alors cela ne sert à rien de parcourir l'état du clavier.

    Pour en revenir à ton switch, je ne sais pas si la complexité d'un switch est en O(n) ou en O(log(n) ) sachant qu'avec un tableau de std::function, on passe en O(1).
    Après, de créer une structure au lieu d'appeler une fonction, il y a des inconvéniants et des avantages.
    • inconvénients
      • il faudra deux évaluations, 1 pour SFML -> structure et 1 pour structure -> action ;

    • avantages
      • les mapping sont un peu plus dynamiques et simples.
      • on a qu'une seule méthode au lieu de ~8, on évite donc de la duplication de code ;
      • on peut aussi transmettre une structure sans apriori sur son contenu (encapsulation), imagine de devoir ajouter un nouveau type d'événement .
      • entre créer une structure et appeler une méthode virtuelle, je pense que la création de la structure est beaucoup plus rapide.


  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Neckara Voir le message
    C'est encore pire .
    Non seulement tu va générer un événement à chaque "tour" (au lieu d'avoir un évent de début et de fin), bonjour les perfs .
    Mais en plus, tu peux louper pas mal d'événements si tu as déjà plusieurs touches d'enfoncées sans compter que tu attaques le principe d'encapsulation à grands coups de hache.
    Quel rapport avec l'encapsulation ?
    Non justement tu ne loupes rien puisque c'est juste fait pour ça. C'est de cette manière que tu gères très simplement le fait que maintenir la touche "a" enfoncée permet d'écrire plusieurs fois aaaaa dans une zone de texte. Et il s'agit de la configuration système. Sinon tu dois te prendre la tête sévère pour gérer un cooldown interne etc... autant dire que tu le gèreras pas tant la complexité est grande.
    Ca ne génère pas un évènement à chaque tour, ça génère un évènement à chaque fois.. que le système en génère un.
    Il suffit de comboter ça avec un set et tu sais trivialement s'il s'agit d'un repeat ou d'un start.

    Citation Envoyé par Neckara Voir le message
    Le tout serait de savoir si on a une garantie que les événements d'appuis et de relâchements sont bien générés même s'il y a déjà plusieurs touches d'enfoncées.
    Encore heureux que oui

    le fait que pollEvent n'envoie plus d'event dès qu'une seule touche est relâchée. (ce qui est embêtant si plusieurs touche sont pressées en même temps et qu'on ne veut relâcher qu'une seule touche) me gêne
    As-tu fait un seul test ?
    Tu appuyes et maintiens 3 touches, tu relâches n'importe laquelle et tu as bien un évènement qui l'indique.

    on a qu'une seule méthode au lieu de ~8, on évite donc de la duplication de code ;
    méthode dans laquelle (lesquelles) tu vas devoir faire 8 if ou.. un switch pour faire la bonne action
    on peut aussi transmettre une structure sans apriori sur son contenu (encapsulation), imagine de devoir ajouter un nouveau type d'événement .
    tu rajoutes une méthode, si personne n'utilise cet évènement il ne la redéfinit pas et laisse son implémentation par défaut qui ne fait rien
    complexité : nulle
    je suppose que c'est ça le rapport avec l'encapsulation plus haut ? avoir une structure magique qui contient tout et n'importe quoi, j'appelle pas vraiment ça de l'encapsulation
    c'est peut-être nécessaire à bas niveau, comme le fait SFML mais pas obligatoire : GLFW fait autrement et ça marche tout aussi bien
    entre créer une structure et appeler une méthode virtuelle, je pense que la création de la structure est beaucoup plus rapide.
    les méthodes listées ici ne sont pas du tout virtuelles, celles dans les acteurs oui, mais entre appeler une méthode spécifique qui indique qu'il s'agit d'un click de souris et devoir dans la méthode traduire l'évènement afin de savoir s'il s'agit d'un click de souris ou d'un appui sur une touche, j'ai un autre avis sur la "plus rapide"
    tu as 4 acteurs qui doivent faire le test, alors que seul l'un d'eux agit sur le click vs 3 implémentations par défaut et 1 qui fera une action
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Non justement tu ne loupes rien puisque c'est juste fait pour ça. C'est de cette manière que tu gères très simplement le fait que maintenir la touche "a" enfoncée permet d'écrire plusieurs fois aaaaa dans une zone de texte. Et il s'agit de la configuration système.
    Prend un éditeur de texte, enfonce A, puis enfonce E. Tu vas voir :
    AAAEEEEEEE et non AAAAAEAEAEAEAEAEAEAEA.

    Dès qu'il y a plusieurs touches enfoncées, ce n'est plus fiable. Normalement il y a une raison au niveau du hardware du clavier.

    Sinon tu dois te prendre la tête sévère pour gérer un cooldown interne etc...
    Donc laisser le nombre d'attaques par seconde (exemple) dépendant du nombre d'events envoyé par seconde par le système ?

    autant dire que tu le gèreras pas tant la complexité est grande.
    En quoi serait-ce complexe d'avoir uniquement un événement "start" et "stop" ?

    Ca ne génère pas un évènement à chaque tour, ça génère un évènement à chaque fois.. que le système en génère un.
    Il suffit de comboter ça avec un set et tu sais trivialement s'il s'agit d'un repeat ou d'un start.
    Pourquoi ne pas tout simplement faire simple et attendre d'avoir l'événement de key release ?


    méthode dans laquelle (lesquelles) tu vas devoir faire 8 if ou.. un switch pour faire la bonne action
    Pas du tout.
    Surtout que la fonction n'est pas obligée de traiter l'événement et peut se contenter de la rediriger.
    Utiliser un std::map est bien plus efficace et pourra mapper n'importe quel évent en O(log2), les comparaisons se faisant en une seule instruction.

    tu rajoutes une méthode, si personne n'utilise cet évènement il ne la redéfinit pas et laisse son implémentation par défaut qui ne fait rien
    complexité : nulle
    Déjà la classe qui recevra l'événement devra être recompilée.
    Et ensuite, tu pars du postula que la classe recevant l'événement saura que personne n'en aura besoin ?
    Déjà, si tel est le cas, ce n'est pas la peine d'ajouter cet événement.
    Ensuite, tu brises l'encapsulation, la classe qui reçoit l'événement ne sait pas nécessairement si les autres classes aux-quelles elle peut éventuellement redirigé l'événement en aurait besoin ou non.

    les méthodes listées ici ne sont pas du tout virtuelles, celles dans les acteurs oui, mais entre appeler une méthode spécifique qui indique qu'il s'agit d'un click de souris et devoir dans la méthode traduire l'évènement afin de savoir s'il s'agit d'un click de souris ou d'un appui sur une touche, j'ai un autre avis sur la "plus rapide"
    Faudra que tu m'explique là .

    tu as 4 acteurs qui doivent faire le test, alors que seul l'un d'eux agit sur le click vs 3 implémentations par défaut et 1 qui fera une action
    Je ne comprend pas ce que tu essayes de nous dire.

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Prend un éditeur de texte, enfonce A, puis enfonce E. Tu vas voir :
    AAAEEEEEEE et non AAAAAEAEAEAEAEAEAEAEA.

    Dès qu'il y a plusieurs touches enfoncées, ce n'est plus fiable. Normalement il y a une raison au niveau du hardware du clavier.
    Oui, et ?
    Le système fonctionne ainsi, SFML ou autre ne font que cacher le système, donc tu t'attends à quel fonctionnement ?
    Si tu veux que A et E se répète
    - c'est pas forcément une bonne idée puisque tu surprends l'utilisateur
    - il te suffit d'enregistrer les touches enfoncées (un set fera l'affaire) et quand tu reçois un nouvel évènement de KeyPressed tu parcours ce set (s'il n'est pas vide) pour balancer ce qui t'intéresse

    Citation Envoyé par Neckara Voir le message
    Donc laisser le nombre d'attaques par seconde (exemple) dépendant du nombre d'events envoyé par seconde par le système ?
    Quelle rapport cette fois ?
    Soit tu agis quand le système envoit un évènement, soit tu agis sur un timer.
    Tu n'as aucun controle que le nombre d'évènements puisque c'est un paramètre du système.

    Citation Envoyé par Neckara Voir le message
    En quoi serait-ce complexe d'avoir uniquement un événement "start" et "stop" ?
    Si tu relis, tu verrais que c'est pas le propos. Il s'agit des évènements "repeat", qui sont des "start" envoyé alors qu'on n'a pas reçu de "stop" entre temps.

    Citation Envoyé par Neckara Voir le message
    Pourquoi ne pas tout simplement faire simple et attendre d'avoir l'événement de key release ?
    Parce que tu as besoin de gérer un "repeat", au hasard.
    Et que ce repeat se base sur la configuration système de l'utilisateur n'est pas forcément stupide

    Citation Envoyé par Neckara Voir le message
    Surtout que la fonction n'est pas obligée de traiter l'événement et peut se contenter de la rediriger.
    Bravo, c'est exactement le fonctionnement de la classe de "ControllerManager" sur laquelle on enregistre les "Controller"/"Actors".
    Citation Envoyé par Neckara Voir le message
    Utiliser un std::map est bien plus efficace et pourra mapper n'importe quel évent en O(log2), les comparaisons se faisant en une seule instruction.
    De quel map parles-tu ? Il n'y a aucune notion ou mention de map dans les posts précédents. Tu as sûrement une idée derrière la tête, dommage qu'elle ne soit que là-bas.

    Citation Envoyé par Neckara Voir le message
    Déjà la classe qui recevra l'événement devra être recompilée.
    Et ensuite, tu pars du postula que la classe recevant l'événement saura que personne n'en aura besoin ?
    Déjà, si tel est le cas, ce n'est pas la peine d'ajouter cet événement.
    Recompiler, est-ce si extraordinaire lors d'un développement ?
    Je pars d'aucun postulat, la classe de manager dispatch à tous les controller qui se sont enregistrés dessus et basta.
    C'est toi qui me parles de la "difficulté extrême" à ajouter un évènement. Il n'en est rien. Si un acteur a besoin de cet évènement, il surcharge la méthode qui le récupère et agit. S'il fait rien avec bah... il fait rien et laisse l'implémentation par défaut.
    Ensuite, je soutiens qu'il est beaucoup plus simple et intelligent d'avoir une méthode OnClick qui est clairement appelée lorsqu'un évènement de click survient, qu'une méthode OnEvent dans laquelle il faut commencer par deviner de quel évènement il s'agit.
    Tu parles de duplication de code, c'est exactement ce que tu as avec ton OnEvent puisque chaque acteur qui possède cette fonction va devoir traduire l'évènement pour savoir si oui ou non il va agir.
    Citation Envoyé par Neckara Voir le message
    Ensuite, tu brises l'encapsulation, la classe qui reçoit l'événement ne sait pas nécessairement si les autres classes aux-quelles elle peut éventuellement redirigé l'événement en aurait besoin ou non.
    Elle en sait rien et scoop : elle s'en moque !
    Son seul but est de dispatcher les évènements à quiconque s'est enregistré chez elle.

    Implémentation bateau
    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
     
    struct Controller
    {
     virtual bool OnClick(int btn, int x, int y) { return false; }
    };
    struct ControllerManager
    {
     void OnClick(int btn, int x, int y)
     {
        for (uint i = 0, i < controllers.size(); ++i)
        {
           if (controllers[i]->OnClick(btn, x, y))
             return; // true => stop propagation
        }
     }
     std::vector<Controller*> controllers;
    };
    Rien d'extraordinaire non ?
    SFML utilise une super-struct qui englobe tout, grand bien lui fasse.
    GLFW utilise une méthode plus granulaire tout aussi efficace (et que je préfère) http://www.glfw.org/docs/latest/quic...uick_key_input
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  8. #8
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Bousk Voir le message
    - c'est pas forcément une bonne idée puisque tu surprends l'utilisateur
    Je ne suis pas d'accord sur ce point.
    Ex : gauche + haut + A pour attaque.

    - il te suffit d'enregistrer les touches enfoncées (un set fera l'affaire) et quand tu reçois un nouvel évènement de KeyPressed tu parcours ce set (s'il n'est pas vide) pour balancer ce qui t'intéresse
    Dans ce cas là, à quoi nous sert la répétition du "key pressed" ?
    On a donc besoin que de deux événements : les changements d'états de la touche clavier.

    Derrière, on peut faire des sets, des machines d’États, etc.

    Soit tu agis quand le système envoit un évènement
    Donc dépendant du système, hors
    Tu n'as aucun controle que le nombre d'évènements puisque c'est un paramètre du système.
    Donc on ne peut pas dire que ce soit une bonne idée.

    soit tu agis sur un timer.
    DOnc gérer une sorte de cooldown à la main ? Pourtant tu disais que ce serait trop "compliqué" ?


    Si tu relis, tu verrais que c'est pas le propos.
    ?

    Il s'agit des évènements "repeat", qui sont des "start" envoyé alors qu'on n'a pas reçu de "stop" entre temps.
    Si on a des événements "start" et "stop", à quoi nous servent ces événements "repeat" ?

    Parce que tu as besoin de gérer un "repeat", au hasard.
    Et en quoi un événement "stop" ne serait-il pas suffisant ?
    N'est-ce pas au final un changement d'état ?

    Et que ce repeat se base sur la configuration système de l'utilisateur n'est pas forcément stupide
    En quoi ?


    Bravo, c'est exactement le fonctionnement de la classe de "ControllerManager" sur laquelle on enregistre les "Controller"/"Actors".
    ?

    De quel map parles-tu ? Il n'y a aucune notion ou mention de map dans les posts précédents. Tu as sûrement une idée derrière la tête, dommage qu'elle ne soit que là-bas.
    Le but est bien d'exécuter une action en fonction des événements non?
    On a donc un mapping événements => action.
    Le mapping se moque que l'événement soit d'un type keyboard ou Joystick.

    Pourquoi discriminer les différents événements alors qu'on ne sait pas à priori comment ils vont être traités derrière ?

    Recompiler, est-ce si extraordinaire lors d'un développement ?
    Quand on programme proprement on essaye d'éviter les dépendances/couplage entre classes/modules.
    Si ton code est séparé en trois modules distribués dans 3 fichiers binaires distincts, ça serait bien de ne pas devoir modifier les trois fichiers binaires à la moindre modification d'un module.

    C'est toi qui me parles de la "difficulté extrême" à ajouter un évènement. Il n'en est rien. Si un acteur a besoin de cet évènement, il surcharge la méthode qui le récupère et agit. S'il fait rien avec bah... il fait rien et laisse l'implémentation par défaut.
    Et si ton acteur se contente de rediriger tes événements ?
    Tu le modifies pas et tu t'aperçoit qu'en bout de chaîne il te manque des événements sans comprendre pourquoi?

    De plus, est-ce qu'une classe qui se contenterait de rediriger un événement a forcément besoin de connaître son type ?

    Ensuite, je soutiens qu'il est beaucoup plus simple et intelligent d'avoir une méthode OnClick qui est clairement appelée lorsqu'un évènement de click survient, qu'une méthode OnEvent dans laquelle il faut commencer par deviner de quel évènement il s'agit.
    Je ne suis pas du tout d'accord.
    Qui te dit que ton "OnEvent" a besoin de deviner de quel événement il s'agit ?
    Tu reçoit des événements "système", tu as plusieurs choses à faire :
    • l'envoyer à son bon destinataire ;
    • le convertir en un événement "utilisateur" (généralement un appel de méthode/fonction).

    Or cela n'a pas nécessairement besoin de discriminer les événements par "types".

    Tu parles de duplication de code, c'est exactement ce que tu as avec ton OnEvent puisque chaque acteur qui possède cette fonction va devoir traduire l'évènement pour savoir si oui ou non il va agir.
    Ce n'est pas comme si on pouvait créer des classes pour s'aider pour par exemple effectuer des mappings.

    Elle en sait rien et scoop : elle s'en moque !
    Son seul but est de dispatcher les évènements à quiconque s'est enregistré chez elle.
    Donc tu es obligé de surcharger chacune de ses méthodes.
    Or à chaque ajout d'un type d'événement, tu créé une nouvelle méthode.
    Donc tu est obligé de réécrire ta classe pour surcharger la nouvelle méthode.

    Donc tu ne respectes pas certains "bon principes" du C++.

    GLFW utilise une méthode plus granulaire tout aussi efficace (et que je préfère) http://www.glfw.org/docs/latest/quic...uick_key_input
    Donc il faut définir :
    • un callback pour le clavier ;
    • un callback pour la souris ;
    • ...

    Pas génial si tu veux rediriger tes événements à un destinataire précis.

  9. #9
    Invité
    Invité(e)
    Par défaut
    Bon après réflexion j'ai trouvé une meilleur solution, en effet, il fallait faire un système avec un tableau de pointeurs sur fonctions, car je dois convertir chaque événement générés pour chaque librairies en un type plus générique (celui de mon moteur) et en même temps ça me permet d'éviter un if sur chaque type d'événement SFML.

    Et pour vérifier les states, j'ai fais une interface qui redéfini des méthode de conversion de int vers le type de l'enum pour les touches pour chaque librairies.

    PS : j'ai aussi un système d'action mais ça je l'utiliser plutôt pour les événements combiner, ça permet à l'utilisateur de pouvoir créer ses propre type d'événements.
    Le seul soucis c'est que si il y a un nouveau type d'événement dans la librairie il faudra refaire une surcharge de fonction. (Ca, pas trop le choix. :/)

    Ma classe action permet de gérer soit des événements de type repeat (sans dépendre du délai imposé par l'os grâce à sf::Keyboard) ou bien des événements de type pressed, ou bien de type released.)
    Je pense que le mieux est de ne pas utiliser un set mais d'enregistrer les mapping des touches qui sont pressée et de les appeler avec une manager, et les supprimer lorsque les touches sont relâchées.
    J'en ai aussi profité pour rajouter à chaque type d'event une priorité.(D'ailleurs merci pour tes interfaces neckara. )
    Dernière modification par Invité ; 09/11/2014 à 21h57.

  10. #10
    Invité
    Invité(e)
    Par défaut
    Bon, j'ai testé cette méthode pour la conversion des events avec un tableau de pointeurs sur fonctions et elle semble prometteuse.

    Code cpp : 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
     
    #include <SFML/Graphics.hpp>
    #include "sfmlEventMapper.hpp"
    #include <iostream>
    int main() {
        sf::RenderWindow window(sf::VideoMode(800, 600), "test");
        while (window.isOpen()) {
            window.clear();
            window.display();
            sf::Event event;
            while(window.pollEvent(event)) {
                odfaeg::SystemEvent sysEvent(event.type);
                odfaeg::SFMLEventMapper eventMapper;
                eventMapper.setEvent(event);
                eventMapper[sysEvent];
                if (sysEvent.eventInfos.origin == odfaeg::SystemEvent::Origin::Window
                    && sysEvent.eventInfos.type == odfaeg::SystemEvent::Type::Closed) {
                    std::cout<<"close"<<std::endl;
                    window.close();
                }
                if (sysEvent.eventInfos.origin == odfaeg::SystemEvent::Origin::Window
                    && sysEvent.eventInfos.type == odfaeg::SystemEvent::Type::Resized) {
                    std::cout<<"new size : "<<sysEvent.params[0].paramValue<<" "<<sysEvent.params[1].paramValue<<std::endl;
                }
            }
        }
        return 0;
    }

    Pour la génération d'event je pense que je vais la redéfinir et faire un truc du genre si les touche sont pressé je génère des events avec le mapping, sinon, j'arrête de générer des events, donc faire plutôt un système de "start" et de "stop" pour chaque touche ce qui donne quelque chose comme ceci. (Pas encore testé)

    Code cpp : 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
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    void SFMLWindow::checkEvents(void) {
         sf::Event event;
         while (m_window.pollEvent(event)) {
            SystemEvent curr_sys_event(event.type);
            m_current_mapper.setEvent(event);
            m_current_mapper[curr_sys_event];
            std::map<SystemEvent, IEventMapperManager::EventMapperID>::iterator it = m_mappers.find(curr_sys_event);
            if (it == m_mappers.end()) {
                SFMLEventMapper mapper;
                mapper.setEvent(event);
                m_mappers.insert(std::make_pair(curr_sys_event, m_eventManager.registerEventMapper(mapper)));
            }
            for (it = m_mappers.begin(); it != m_mappers.end();it++) {
                 SystemEvent sysEvent(event.type);
                 m_eventManager.changeCurrentMapping(it->second);
                 m_eventManager[sysEvent];
                 m_events.insert(m_events.begin(), sysEvent);
            }
            for (it = m_mappers.begin(); it != m_mappers.end();) {
                if (event.type != sf::Event::KeyPressed && event.type != sf::Event::MouseButtonPressed) {
                    m_eventManager.deleteEventMapper(it->second);
                    it = m_mappers.erase(it);               
                } else {
                    it++;
                }
            }
            if (event.type == sf::Event::KeyReleased || event.type == sf::Event::MouseButtonReleased) {
                curr_sys_event.eventInfos.type = SystemEvent::Type::Pressed;
                it = m_mappers.find(curr_sys_event);
                m_eventManager.deleteEventMapper(it->second);
                it = m_mappers.erase(it);
            }
        }
    }
    SystemEvent SFMLWindow::popEvent() {
        checkEvents();
        if (m_events.size() == 0) {
            SystemEvent event(-1);
            event.eventInfos.origin = SystemEvent::Origin::NoEvent;
            event.eventInfos.typeID = SystemEvent::Type::NoType;
            event.eventInfos.type = SystemEvent::Type::NoType;
            event.paramTypeID = SystemEvent::Type::NoType;
            return event;
        } else {
            SystemEvent event = m_events.back();
            m_events.pop_back();
            return event;
        }
    }

    Normalement je n'ai même plus besoin de sf::Keyboard::isKeyPressed, mais bon, je vais redéfinir une interface quand même pour les keystates, on ne sait jamais.

    Mais je préférerai faire un timer personnalisé pour gérer les interval de temps entre la génération de deux événements successifs.
    Je pense que ça serait mieux que un bête sf::Keyboard::isKeyPressed.

Discussions similaires

  1. Quel est le parcours le plus rapide
    Par Atsibat dans le forum WinDev
    Réponses: 14
    Dernier message: 12/02/2013, 22h03
  2. [Firebird] Quel est le code le plus rapide ?
    Par ILP dans le forum Bases de données
    Réponses: 8
    Dernier message: 26/10/2009, 13h01
  3. Réponses: 2
    Dernier message: 27/01/2009, 19h01
  4. PGCD: quelle est la méthode la plus rapide
    Par progfou dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 05/03/2008, 18h26
  5. Réponses: 16
    Dernier message: 19/05/2005, 16h20

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