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 :

L'architecture d'un event/input manager


Sujet :

C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2018
    Messages : 5
    Par défaut L'architecture d'un event/input manager
    Bonjour,
    Je travaille actuellement sur un projet de moteur de jeu (juste pour m'éclater, rien de sérieux),
    et je bloque sur la gestion des events et des entrées utilisateur.

    I| Event Manager

    Pour l'instant, j'ai une boucle du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    while(running) {
        Event event = getNextEvent();
        if(event == KeyPressed && event.code == Key::Escape) {
            closeApp();
        }
    }
    Même si mon assemblement de if/else est vraiment sympathique, je vois déjà plusieurs problèmes :
    • mon code va vite être difficile à maintenir, surtout si je commence à relier une action à plusieurs évènements
    • je suis obligé d'inclure toutes les déclarations de fonctions/méthodes que je souhaite relier à un évènement
    • il va être très compliqué de "rebind" les actions (ex: je veux passer d'un clavier QWERTY à AZERTY)


    Du coup, j'avais pensé faire une classe EventManager du style:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class EventManager {
    public:
        notify(Event *event);  //permet à n'importe qui de prévenir qu'un évènement est arrivé
        getNotified(Binding *binding, void(*callback)(Binding*));
    }
    Avec une structure Binding qui associe tout les évènements qui doivent être réunis pour que le callback soit appelé.
    Sauf que la aussi, j'ai plusieurs questions qui restent en suspens :
    • Sachant que dans ma boucle de jeu, handleInput() et render() s'executent quand ils peuvent, mais que update() s'execute à intervale régulier, ne vaut il pas mieux que les callback soient appelés à chaque update(), et que je leur passe le deltatime en argument ?
    • Cette question rejoint un peu la précédente, mais ne vaudrait-il pas mieux que j'appelle handleInput() avant chacune des update(), pour éviter de faire trop de suppositions sur le déplacement du personnage?


    II| Input Manager

    Jusque là, je ne parlais que d'évènements ponctuel, du type "une touche vient d'être pressée", ce qui est bien dans le cas
    ou je souhaite, par exemple, que mon personnage lance un sort, mais si je veux que mon personnage se déplace,
    j'utilise plutôt quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    while(running) {
        if(Keyboard.isKeyPressed(Key::Z) {
            actor.move(0.0f, 1.0f)  //déplace actor sur l'axe +y
        }
    }
    Or la, je n'ai aucune idée de comment gérer ça correctement. Est-ce qu'il est préférable que j'implémente un InputManager
    similaire à mon EventManager, mais qui, à chaque tour de boucle, vérifie si les touches inscrites via getNotified(...) sont pressée ?
    Devrais-je plutôt l'intégrer directement à mon EventManager ?

    Voila, je pense que j'ai exposé la majorité de mes questions,
    Merci beaucoup à ceux qui ont pris le temps de me lire !

  2. #2
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    handleInput() et render() s'executent quand ils peuvent, mais que update() s'execute à intervale régulier
    ??

    As-tu lu des articles type https://alexandre-laurent.developpez...boucle-de-jeu/ ? C'est un bon début.

    Après, perso j'implémente toujours ainsi:
    - MouseController
    > onClick, onMove, ...
    > interface retournant true
    - KeyboardController
    > onKeyPressed, Released, ...
    > interface retournant true
    - Controller
    > aggrégat de Mouse, Keyboard, (manette, joystick, ...)
    > et gère des états intermédiaires comme le maintien d'une touche, les modifiers alt, ctrl, shift, ...
    Tous ces trucs sont indépendants de la plateforme et du moteur

    - ControllerManager
    > liste de Controller rangés par priorité

    Et tu envoies les évènements au ControllerManager qui dispatch du plus prioritaire au moins prioritaire, tant qu'il retourne true; false sert à briser la chaîne
    > si tu as 2 Controllers : un pour l'UI, un pour ingame, , avec priorité UI > Game, quand tu cliques
    >> évènement envoyé à l'UI (disons un click)
    >> si tu es sur un bouton, tu l'actives, et tu retournes false
    >> si rien ne se passe, retournes true et ça l'envoi au jeu
    >> le jeu peut faire un déplacement ou peu importe, et retourne false

    J'ai un embryon d'article qui traine à ce sujet, un jour je m'y mettrais pour de bon
    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.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2018
    Messages : 5
    Par défaut
    As-tu lu des articles type https://alexandre-laurent.developpez...boucle-de-jeu/ ? C'est un bon début.
    Je ne les avais pas lu, mais je suis bien au courant de ce qu'est une boucle de jeu, j'ai du mal m'expliquer :p
    En effet, la boucle présentée dans cet article à un désavantage majeur, les moteurs physique sont beaucoup plus précis si ils sont
    "mis à jour" à interval de temps stable. Du coup, j'utilise une boucle comme celle la:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    float timestep = 1.f / 60.f;
    float time = 0;
    Clock clock = beginClock();
    while(running) {
        //ici, time correspond au temps qu'il a fallu pour accomplir le tour de boucle précédent
        handleInput();
        while (time >= timestep) {
            update(timestep);  //ici le but est de "rattraper le retard", la grosse différence est que ici on appelle successivement update toujours avec le même deltatime, au lieu d'une fois avec un deltatime qui varie
            time -= timestep;
        }
        render();
        time += clock.restart();
    Après, perso j'implémente toujours ainsi:
    - MouseController
    > onClick, onMove, ...
    > interface retournant true
    - KeyboardController
    > onKeyPressed, Released, ...
    > interface retournant true
    - Controller
    > aggrégat de Mouse, Keyboard, (manette, joystick, ...)
    > et gère des états intermédiaires comme le maintien d'une touche, les modifiers alt, ctrl, shift, ...
    Tous ces trucs sont indépendants de la plateforme et du moteur
    C'est à peu près ce que je fais, mais je voulais avoir plus de détails sur l'implémentation.

    En tout cas merci beaucoup pour ta réponse, en particulier pour la différenciation des priorités ui/game, je n'y avais
    pas du tout pensé !

  4. #4
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Tu devrais avoir les 2 cas, que j'identifie comme step et update.
    Le step est une mise à jour sur temps fixe, qui peut éventuellement survenir plusieurs fois dans la frame si y'a un pic de latence mais dans l'idéal non, l'update survient à chaque frame.
    Dane le step tu mets à jour la physique, le gameplay, tout le jeu, dans l'update l'affichage, ce qui n'incide pas ou peut être fait en 1 seule fois (animations, ..).
    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
     
    int main()
    {
      ...
      Game thegame;
      ....
      Time accumulator = 0, lastframe = now;
      while(!thegame.exit())
      {
        Event event;
        while(poll(event))
        {
           switch(event)
           {
              case click: thegame.controller.onClick();
              ...
           }
        }
        Time startframe = now;
        dt = lastframe - startframe;
        accumulator += dt;
        while (accumulator > StepTime)
        {
          thegame.step(StepTime);
          accumulator -= StepTime;
        }
        thegame.update(dt);
        thegame.render();
        lastframe = startframe;
      }
    }
    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.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 04/07/2011, 16h19
  2. Réponses: 4
    Dernier message: 25/11/2010, 09h41
  3. [Architecture N-tiers] Le rôle du manager
    Par rad_hass dans le forum ASP.NET
    Réponses: 4
    Dernier message: 21/03/2008, 02h44
  4. Réponses: 9
    Dernier message: 14/08/2007, 09h05

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