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

SDL Discussion :

Problème avec la gestion des événements


Sujet :

SDL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut Problème avec la gestion des événements
    Bonjour,

    Je vais essayer de vous faire voir ce qu'il faut parce que c'est sur mon moteur de mon futur jeu donc c'est du gros dossier

    Bon, en premier lieu, il s'agit d'une intégration d'une petite API pour créer et gérer des widgets en SDL pour mon moteur, jusque là rien de bien compliqué, la suite ....

    Dans le fichier bdialog.c à partir de la ligne 164, je gère la possibilité d'un événement utilisateur pour mon widget destiné à créer des boîtes de dialogues, tu verras ma solution temporaire à la ligne 181

    Ensuite, je travail essentiellement avec des pointeurs, tu peux le remarquer à la ligne 148 su même fichier. Voici les détails de la fonction bengine_get_event dans le fichier bengine.c à partir de la ligne 100. La structure privée contenant le SDL_Event se situe en haut du fichier, ligne 57 !

    Voilà, c'est à peu près tout ce qu'il faut savoir, il n'y a pas un grand cheminement des données, j'ai essayé de rester le plus simple et pratique possible par rapport à l'envergure de mon projet. Tu peux voir mon main de test du moteur dans mon fichier main.c

    Le test que j'avais effectué était une fonction utilisateur (un callback) sur l'événement mouse_motion de ma boîte de dialogue. Le but de cette fonction qui n'existe plus dans le main, était d'afficher les coordonnées de la boîte. Ca fonctionnais bien mais même lorsque j'arrêtais de faire bouger la souris, j'affichais toujours la dernière position de la fenêtre, ce qui est un peu gênant


    J'espère que ca vous ira comme pistes parce que ca deviens de plus en plus gros alors pour montrer un problème et si tout est dispatché en modules ... ca pas très pratique
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  2. #2
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Ok je viens de regarder ton code, j'avoue que cela me rend en fait bien perplexe.

    Je vois plusieurs problèmes à comment tu as dispatché ton système de gestion d'événements.

    Tu as voulu mettre un événement central pour pouvoir gérer l'événement pour chaque élément (passant donc un élément dans une structure qu'on récupère avec bengine_get_event)

    1) Pourquoi ne pas déclarer p_bengine static vu que tu passes par des fonctions ensuite ?

    Dans ta gestion des événements, tu mets effectivement une jolie boucle while :


    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
                while (SDL_PollEvent (p_event))
                {
                   switch (p_event->type)
                   {
                      case SDL_QUIT:
                      {
                         b_quit = SDL_TRUE;
                      }
                      break;
     
                      case SDL_KEYDOWN:
                      {
                         if (p_event->key.keysym.sym == SDLK_ESCAPE)
                         {
                            b_quit = SDL_TRUE;
                         }
                      }
                      break;
                   }
                }
    2) Mais si c'est un clic de souris ou un mouvement d'un joystick, tu ne le gères pas. Tu espères que tu n'auras pas d'autres événements qui vont écraser les valeurs dans ta variable p_event.

    Parce que s'il y a un événement clavier qui passe après ton clic souris, BAM tu te fais avoir.

    En effet, vu que tu ne gères pas les événements en directement quand tu les recois, tu es obligé de remettre la valeur du type à une valeur non utilisée puisque sinon au prochain rendu, le widget va regarder de nouveau cette valeur.

    Une solution serait que le widget concerné consumme l'événement en modifiant le type de l'événement.

    Malheureusement pour les raisons que j'ai cité plus haut, je ne vois pas comment cette architecture est en fait viable. Dès que tu auras plusieurs événements en même temps tu ne pourras pas garantir que les événements soient correctement gérés.

    Jc

  3. #3
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par fearyourself
    1) Pourquoi ne pas déclarer p_bengine static vu que tu passes par des fonctions ensuite ?
    En effet, j'avais pas remarqué mais normalement le compilateur le fait implicitement si c'est dans un fichier source non ?

    Citation Envoyé par fearyourself
    2) Mais si c'est un clic de souris ou un mouvement d'un joystick, tu ne le gères pas. Tu espères que tu n'auras pas d'autres événements qui vont écraser les valeurs dans ta variable p_event.

    ...

    En effet, vu que tu ne gères pas les événements en directement quand tu les recois, tu es obligé de remettre la valeur du type à une valeur non utilisée puisque sinon au prochain rendu, le widget va regarder de nouveau cette valeur.
    Oui en effet mais SDL_Event ne contient à chaque que un seul événement à un instant donné non ? Ou bien s'agit-il d'une pile ? Car à mon sens et comme j'ai fait, si un événement utilisateur surviens, tous les widgets étant automatiquement parcourus à un instant donné, l'événement sera automatiquement capté par le widget visé et dans le pire des cas, si c'est un événement non géré bin rien ne se passe tout simplement.


    Citation Envoyé par fearyourself
    Malheureusement pour les raisons que j'ai cité plus haut, je ne vois pas comment cette architecture est en fait viable. Dès que tu auras plusieurs événements en même temps tu ne pourras pas garantir que les événements soient correctement gérés.
    Je suis ouvert à toutes propositions d'amélioration de ma gestion des événements, le moteur lui même n'est pas fini alors c'est encore le bon moment pour faire des changements/optimisations


    Merci
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  4. #4
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Citation Envoyé par Franck.H
    Oui en effet mais SDL_Event ne contient à chaque que un seul événement à un instant donné non ? Ou bien s'agit-il d'une pile ?
    En effet, c'est un seul événement et pas une pile.

    Car à mon sens et comme j'ai fait, si un événement utilisateur surviens, tous les widgets étant automatiquement parcourus à un instant donné, l'événement sera automatiquement capté par le widget visé et dans le pire des cas, si c'est un événement non géré bin rien ne se passe tout simplement.
    Justement ! Tu ne parcours pas tous tes widgets pour chaque événement mais seulement quand tu sors de ta boucle événementielle.

    C'est là le problème !

    Je suis ouvert à toutes propositions d'amélioration de ma gestion des événements, le moteur lui même n'est pas fini alors c'est encore le bon moment pour faire des changements/optimisations
    La seule solution : parcourir tous les objets susceptibles d'être intéressé par un événement à chaque itération de la boucle.

    La solution que j'avais choisi : utiliser une solution de focus, du coup seul l'objet actif recoit les événements et seulement pendant un clic doit on faire un parcours. Et encore, la liste des objets sont triés par profondeur du coup, dès qu'on trouve un objet dans la ligne de mir du curseur, on s'arrête.

    Jc

  5. #5
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Oui en effet, je parcours tous les widgets présents et ce par le moyen de la boucle qui affiche les widgets car c'est une fonction conjointement lié à celle des événements.

    Ce que je peut éventuellement faire, si j'ai bien compris ton résonnement et que je soit pas obligé de modifier la moitié de mon code, est de faire un parcours séparé des widgets par rapport à celui qui posède le focus (un petit flag à ajouter pour son adresse, rien de bien complqué).

    Ca fairais donc en somme, une gestion bien séparée pour les événements des widgets ce qui est en effet pas plus mal.

    Voulant faire le plus simple possible j'avais fait un parcours global par rapport aux fonctions d'affichage de chaque widget mais j'avais pas pensé à ce problème.


    Ca me fera du boulot pour la semaine prochaine quand je me remettrait sur mon beau projet


    Si tu as d'autres remarques à faire hésite pas, merci
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  6. #6
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Citation Envoyé par Franck.H
    Oui en effet, je parcours tous les widgets présents et ce par le moyen de la boucle qui affiche les widgets car c'est une fonction conjointement lié à celle des événements.
    C'est aussi ce que j'ai vu

    Ce que je peut éventuellement faire, si j'ai bien compris ton résonnement et que je soit pas obligé de modifier la moitié de mon code, est de faire un parcours séparé des widgets par rapport à celui qui posède le focus (un petit flag à ajouter pour son adresse, rien de bien complqué).
    Voilà, moi en fait je passais l'événement au Moteur de jeu (ton bengine) et il décidait ce qu'il en faisait. Evénement clavier passait d'abord par l'élément en focus et si cela lui intéressait il le prenait sinon le moteur le gérer.

    Ceci était facilement possible en utilisant ce genre de code pour la gestion du clavier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void promain_keyb(unsigned char touche, int x, int y)
    {
        if(!windowhandler.key(touche,x,y))
        {
        switch(touche)
          {
                case 'q':
                    promain.save("maingame");
                    exit(1);
                    break;
          }         
        }           
    }
    Donc lorsque le moteur recoit un événement clavier, il l'envoit au gestionnaire de fenêtres qui fonctionne comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //Returns if we captured the key or not
    bool ComponentHandler::key(unsigned char k, int x, int y)
    {
        //Send the key event to the last selected component
        if(last_select)
            return last_select->call_key(k,x,y);
        else
            return false;//false means we didn't use the key
    }
    Donc pour la lettre 'q' par exemple, soit le widget (pour toi ) l'utilise et du coup on ne veut pas sortir du programme, soit le programme s'en sert et donc on sort...

    Ca ferais donc en somme, une gestion bien séparée pour les événements des widgets ce qui est en effet pas plus mal.

    Voulant faire le plus simple possible j'avais fait un parcours global par rapport aux fonctions d'affichage de chaque widget mais j'avais pas pensé à ce problème.


    Ca me fera du boulot pour la semaine prochaine quand je me remettrait sur mon beau projet
    Il vaut toujours mieux séparer l'affichage du reste. Cela permet de faire un code plus propre et plus sympa lorsque tu veux gérer certains détails (mettre un pause en place par exemple).

    Si tu as d'autres remarques à faire hésite pas, merci
    Il faudrait que je regarde un peu plus ton code , avec tes informations, j'avais tout de suite capté le problème !

    Jc

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

Discussions similaires

  1. [ZF 1.7] Zend_Log problème avec la gestion des erreurs
    Par miya dans le forum Zend Framework
    Réponses: 9
    Dernier message: 26/05/2009, 18h33
  2. Problème avec la gestion des fichier dans une JList()
    Par chebmo1986 dans le forum Composants
    Réponses: 3
    Dernier message: 18/02/2009, 23h49
  3. Problème avec gotoAndPlay, gestion des animations
    Par Pimprenelle dans le forum ActionScript 3
    Réponses: 1
    Dernier message: 01/06/2008, 21h24
  4. Problème avec la "Gestion des bibliothèques dynamiques"
    Par GoustiFruit dans le forum Delphi
    Réponses: 15
    Dernier message: 31/05/2006, 09h54
  5. Problème avec la gestion des événements
    Par CynO dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 17/10/2005, 10h07

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