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 :

gestion du temps


Sujet :

SDL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de lightbulb
    Homme Profil pro
    Inscrit en
    Septembre 2008
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 108
    Par défaut gestion du temps
    Salut tout le monde !

    Alors voila, je suis actuellement en train de développer le jeu de la vie en C/SDL. Pour ceux qui ne connaissent pas, il s'agit d'une génération cellulaire : Dans un tableau à deux dimensions(grille), en fonction de l'état d'une cellule (vide ou pleine (0/1)) on regarde le nombres de cases pleines autour de celle-ci et on la fait vivre(1), mourir(0) ou rester dans le même état. Exemple, si une cellule morte se retrouve entourée de plus de 3 cellules vivantes, elle vie aussi.

    Voila pour l'explication, maintenant passons au problème:

    Une fois que l'utilisateur à lancé la séquence de génération (évènement clavier) une boucle fait en sorte de générer toutes les X ms la séquence des fonctions combinées règles + affichage.

    Le problème est que même quand on génère on doit quand même gérer les évènements, ex : l'utilisateur clic droit avec la souris et cela génère des cellules aux différents endroits ou la souris passe quand le clic est maintenu.

    Mon problème est donc de trouver une solution pour d'une part exécuter les fonctions règles + affichage toutes les X ms et d'autre part permettre à l'utilisateur dans le même temps de de faire des actions de manière fluide.

    J'ai déjà tenté deux ébauches de solution avec leurs points faible et fort qui ne m'ont pas satisfaites. Elles sont complètement fonctionnelles, la partie intéressante ici se situe uniquement au niveau de la gestion du temps.

    Voici grossièrement comment se présente l'algo pour une première solution, le SDL_Delay(X):

    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
     
    int X;
    bool continuer=true;
    bool continuerbis=false;
    while(continuer) //boucle principale
    {
          //je passe le passage initialisation SDL... et les traitements annexes
     
          //L'utilisateur presse G, la touche pour générer
          continuerbis=true;
          while(continuerbis) //boucle principale pendant la génération, c'est celle qui nous intéresse
          {
                  while(SDL_PollEvent(&event))
                  {
                        //traitement du clic de la souris
                        //et des divers appuis clavier
                  }
                  SDL_delay(X);
                  if(continuerbis) //permet de ne pas générer pour rien si l'user a cliqué sur quitter par exemple
                    {
                            regles(param1,param2,paramN);
                            affichage(param1,param2,paramN);
                     }
     
     
     
           }
     
    }
    Point fort : Permet de mettre le programme en pause, économie de CPU, et génère au bon moment.
    Point faible : Empêche la fluidité du traitement des évènements qui sont désormais dépendant de ce temps X.
    Point très faible : Bloque complètement le programme pendant ces X ms empêchant l'utilisateur de quitter par exemple. Quand c'est 25ms ça gène pas, mais si l'utilisateur peut par exemple faire varier X (ms de pause) alors il se peut que le programme soit totalement indisponible pendant un temps pouvant dépasser les 1sec, ce qui rend la gestion des évènements inutile.


    Solution n°2 :
    Combinaison de la gestion du temps avec le SDL_PollEvent et SDL_GetTicks

    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
     
     
    int X,passedtime;
    bool continuer=true;
    bool continuerbis=false;
    while(continuer) //boucle principale
    {
          //je passe le passage initialisation SDL... et les traitements annexes
     
          //L'utilisateur presse G, la touche pour générer
          continuerbis=true;
          while(continuerbis) //boucle principale pendant la génération, c'est celle qui nous intéresse
          {
                  passedtime=SDL_GetTicks;
                  while(SDL_PollEvent(&event)||(SDL_GetTicks-passedtime<X) )
                  {
                        //traitement du clic de la souris
                        //et des divers appuis clavier
                  }
     
                  if(continuerbis) //permet de ne pas générer pour rien si l'user a cliqué sur quitter par exemple
                    {
                            regles(param1,param2,paramN);
                            affichage(param1,param2,paramN);
                     }
           }
     
    }

    Point fort : Gestion ultra fluide des événements et génération en temps voulu.
    Point faible : Consommation énorme en processeur car celui-ci va tourner dans la boucle while(SDL_PollEvent...) tant qu'on atteint pas les X ms. Alors c'est sure que dans ce cas, dès qu'il y a un évènement il peut pas le rater !!!

    Je cherche donc un compromis afin de réaliser la règle que je vais exprimer si dessous :

    Si il y a un évènement on le traite, mais si il n'y a rien on attend les X ms et on génère. Ces X ms ne doivent pas compromettre la gestion fluide des évènements.

    Une autre solution qui m'a traversée l'esprit serait de mettre un SDL_WaitEvent et de déclencher un évènement toutes les X ms qui serait l'exécution des fonctions règle + affichage. Mais je ne sais pas si c'est possible:

    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
     
    int X,passedtime;
    bool continuer=true;
    bool continuerbis=false;
    while(continuer) //boucle principale
    {
          //je passe le passage initialisation SDL... et les traitements annexes
     
          //L'utilisateur presse G, la touche pour générer
          continuerbis=true;
          while(continuerbis) //boucle principale pendant la génération, c'est celle qui nous intéresse
          { 
                 passedtime=SDL_GetTicks;
                 SDL_WaitEvent(&event)
                  {
                        //traitement du clic de la souris
                        //et des divers appuis clavier
                        //Toutes les X ms créer son propre évènement chargé d'exécuter les fonctions suivantes. Du genre :
                            if(SDL_GetTicks-passedtime>X)
                            {
                            //création de l'évènement
                            SDL_PushEvent() ; //on le place dans la file directement
                            regles(param1,param2,paramN);      //fonctions à
                            affichage(param1,param2,paramN); //executer
                            }
     
                  }
     
     
           }
     
    }
    Avantage : Faible utilisation du CPU, génération en temps voulu, suppression de la condition if ce qui allégerait le programme encore plus.
    Inconvénient : C'est possible ça?

    Voila, j'ai essayé d'être le plus clair possible ! Bien sûre ma dernière proposition n'est qu'une suggestion et je suis ouvert à toute autre proposition permettant de régler le problème !

    Merci pour l'attention que vous m'avez porté en lisant ce message, à bientôt !

  2. #2
    Membre Expert
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Par défaut
    Salut.

    Pas mal d'idées intéressantes

    Déjà le WaitEvent bloque le programme en l'absence d'évènement, c'est problématique.

    Par exemple tu peux faire un SDL_SetTimer pour appeler ta fonction toutes les X secondes (ça se fera automatiquement), et à côté faire un SDL_WaitEvent. Par contre tu devras faire en sorte que ta boucle principale et la fonction dans le timer ne changent pas la grille en même temps, c'est-à-dire utiliser des mutex, ... ça peut devenir compliqué.

    Sinon, une autre possibilité, en utilisant SDL_GetTicks:

    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
    Uint32 lastticks = SDL_GetTicks();
     
    while (1)
    {
        Uint32 newticks = SDL_GetTicks();
        if (newticks-lastticks > X) {
           lastticks =newticks;
           regles(param1,param2,paramN);
           affichage(param1,param2,paramN);
        }
     
        while (SDL_PollEvent(&event)) {
            //gestion des evenements
        }
        SDL_Delay(1);
    }
    Normalement le SDL_Delay(1) devrais carrément diminuer l'utilisation du processeur.

  3. #3
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Par défaut
    Salut,

    ouais la solution la plus simple est la dernière proposé par coyotte. Moi je l'implémenterai en peu différemment mais ca reviend strictement au même :

    En regle générale, il est toujours utile de connaitre la durée de la frame courante (en fait basé sur la durée de la frame précédente) et particulièrement pour les jeux. Ca permet de régir tous les déplacements, anims, timers... L'application devient alors totalement indépendante du framerate.

    Avec SDL ca donne un truc du style :

    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
     
    unsigned int deltaTime;
    unsigned int oldTime = SDL_GetTicks();
    unsigned int anEventTimer = 0;
     
    while(true)
    {
    deltaTime = SDL_GetTicks() - oldTime;
     
    // On limite le temps d'une frame a 1 ms parceque c'est généralement pas gérable en dessous
    if (deltaTime == 0)
    {
        SDL_Delay(1);
        deltaTime = 1;
    }
     
    oldTime = SDL_GetTicks();
     
    // traitement avec le deltaTime
    // pour faire un timer :
    if (anEventTimer >= AN_EVENT_TIME)
    {
        // réalisation de l'evenement
        anEventTimer = 0;
    }
    anEventTimer += deltaTime;
     
    // Eventuellement une pause dans l'application si le framerate n'est pas determinant, ca permet de limiter les ressources processeurs
    SDL_Delay(WAIT_TIME);
    }
    SPARK
    Moteur de particule C++ opensource avec modules de rendu OpenGL, Irrlicht et SFML

  4. #4
    Membre confirmé Avatar de lightbulb
    Homme Profil pro
    Inscrit en
    Septembre 2008
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 108
    Par défaut
    Re-bonjour !

    Merci pour vos réponses !

    Coyotte, j'avais déjà implémenté ton idée mais j'avais oublié de le préciser. Le problème c'est que même un SDL_Delay(1) empêche la fluidité de l'animation, en effet quand l'utilisateur fait glisser la souris j'ai l'impression qu'il faut une grosse ressource.

    J'ai donc trouvé une solution alternative qui consiste à soulager le processeur uniquement quand il n'y a pas d'évènements. J'ai géré l'ajout de cellule avec deux booléen, clic passe à true quand l'utilisateur à cliqué et dans ce cas SDL_MouseMotion le détecte et génère les cellule. Il n'y a vraiment que dans ce cas ou le proc est demandé au maximum j'ai donc rajouté cette ligne dans mon while(SDL_PollEvent(&event)||SDL_GetTicks-lasttick<X) :
    if(clic==false)
    SDL_Delay(1);

    Dans ce cas quand il n'y a pas d'évènements on soulage le proc, sinon on l'utilise plein pot. C'est la seule solution que j'ai trouvé pour une fluidité totale...

    Dans le même temps je pense implémenter une gestion des FPS grâce à la solution donné par Frifron, je vous tient ou courant !

    Merci

  5. #5
    Membre Expert
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Par défaut
    Citation Envoyé par lightbulb Voir le message
    Re-bonjour !

    Merci pour vos réponses !

    Coyotte, j'avais déjà implémenté ton idée mais j'avais oublié de le préciser. Le problème c'est que même un SDL_Delay(1) empêche la fluidité de l'animation, en effet quand l'utilisateur fait glisser la souris j'ai l'impression qu'il faut une grosse ressource.
    Salut,

    Franchement je ne pense pas, après c'est peut-être moi qui me trompe. Si tu es sous vista, essaye le gadget "compteur du processeur" pour voir l'évolution de la consommation du CPU en temps réel.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2008
    Messages : 52
    Par défaut
    Hello
    As tu essayé de gérer les événement dans un sous processus?
    de cette manière tu peux gerer la priorité, et donc lui afecter le temps imparti a velonter ?
    seulement je sai pas si c est possible en sdl (je débute dans cette lib) mai en c++ sa roule voir même le C

Discussions similaires

  1. FB/IB gestion du temps
    Par lio33 dans le forum Débuter
    Réponses: 4
    Dernier message: 04/10/2005, 10h55
  2. [MFC] Gestion du temps
    Par Kevgeii dans le forum MFC
    Réponses: 7
    Dernier message: 02/07/2005, 14h21
  3. Aide pour l'analyse d'un problème de gestion de temps
    Par PAINCO dans le forum Décisions SGBD
    Réponses: 8
    Dernier message: 03/06/2005, 15h49
  4. [VB.NET] Gestion en temps réel d'une bdd access
    Par qwiskas dans le forum Windows Forms
    Réponses: 6
    Dernier message: 12/02/2005, 19h37
  5. fonction de gestion du temps
    Par fati dans le forum C
    Réponses: 5
    Dernier message: 26/12/2002, 16h32

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