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

OpenGL Discussion :

SDL -> Bug de SDL_GetTicks() ?


Sujet :

OpenGL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Avatar de Zenol
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 812
    Par défaut SDL -> Bug de SDL_GetTicks() ?
    Bonjour, on ma dit de poster ici pour ce qui est lier a SDL&OpenGL en c++, c'est pourquoi je met ce message ici ^^

    Voila, j'ai créer une peutite classe qui automatise la création de sprit, et de sprit animer, en SDL. Seulement un bug troublen apparait : Duran la première seconde de l'aplication, le sprit animer n'est pas ralenti par mon SDL_GetTicks();. Enfaite, c'est come si SDL_GetTicks() était toujours plus grand que ma variable TimeM :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    while(1)
    {
    TimeM = 0;
    Si TimeM < SDL_GetTicks() - 1000 ->Animer le sprit & TimeM = SDL_GetTicks()
    }
    On dirais que le teste TimeM < SDL_GetTicks() - 1000 est toujours vrai duran la première seconde de l'animation, et puis ensuite tout repart n'ormalement, l'animation se décale chaque 1000ème de seconde...

    Si vous voulez, je peut vous donner le code de ma classe, mais il est un peut indigèste, si vous désirez la moindre portion de code, la moindre information, n'ésitez pas a demender
    Mes articles Développez | Dernier article : Raytracer en haskell
    Network library : SedNL | Zenol's Blog : http://zenol.fr

    N'oubliez pas de consulter la FAQ et les cours et tutoriels.

  2. #2
    Membre Expert
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 577
    Par défaut
    euh dis ton TimeM tu le réinitialise à 0 à chaque fois ?
    et SDL_GetTicks() renvoie une valeur en millisecondes, donc 1000 = 1 seconde, ton sprite est animé 1 fois par seconde ?

    à ta place je ferai comme cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    static TimeM = SDL_GetTicks(); /* initialise TimeM 1 première fois puis le garde en mémoire grace au mot clef static */
     
    while(1)
    {
       if(TimeM <= SDL_GetTicks())
       {
          ->Animer le sprite
          /* animation du sprite 10 fois par seconde (toutes les 100ms) */
          TimeM = SDL_GetTicks() + 100;
       }
    }
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  3. #3
    Membre éclairé
    Avatar de Zenol
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 812
    Par défaut
    Non c'est moi qui me suis tromper dans l'exemple, mon code c'est sa :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Srt::Sprit_Animer Obj;
    draw()
    {
    //........
    Obj.LoadPicture("Anim.bmp");
    Obj.Config()->Ani_x = 30;
    Obj.Config()->Ani = 10;
    Obj.Config()->Time = 1000;
    Obj.BlitSurface(screen);
    }
    et
    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
        //Dérivation en Sprit_Animer de Sprit
        class Sprit_Animer : public Sprit
        {
              public:
                  Sprit_Animer(Ani_Sprit *Conf);
                  virtual ~Sprit_Animer();
     
                  virtual bool BlitSurface(SDL_Surface *screen);
     
                  virtual Ani_Sprit *Config()
                  {return &Config_;}
                  //Desactivation
                  virtual SDL_Rect *PictureSize()
                  {return NULL;}
     
                  virtual SDL_Rect SetConfig( Ani_Sprit Cfg ){}//Desactivation              
                  virtual SDL_Rect SetPictureSize( SDL_Rect PS ){}//Desactivation
     
                  virtual Ani_Sprit *GetConfig()
                  {return &Config_;}
                  //Desactivation
                  virtual SDL_Rect *GetPictureSize()
                  {return NULL;}
     
              protected:
                  Ani_Sprit Config_;
                  Uint32 TimeM;
        };
     
        Sprit_Animer::Sprit_Animer(Ani_Sprit *Conf = NULL )
                     :Sprit()
        {
            if(Conf == NULL)
            {
                Config_.x = 0;
                Config_.y = 0;
                Config_.Width = 32;
                Config_.Height = 32;
                Config_.Time = 1000;
                Config_.Ani = 0;
                Config_.Ani_x = 0;
                Config_.Ani_y = 0;
                Config_.Ani_Act = 0;
            }
            else
            {
                Config_.x = Conf->x;
                Config_.y = Conf->y;
                Config_.Width = Conf->Width;
                Config_.Height = Conf->Height;
                Config_.Time = Conf->Time;
                Config_.Ani = Conf->Ani;
                Config_.Ani_x = Conf->Ani;
                Config_.Ani_y = Conf->Ani;
                Config_.Ani_Act = Conf->Ani_Act;
            }
            TimeM = 0;
        }
        Sprit_Animer::~Sprit_Animer()
        {
        }
        bool Sprit_Animer::BlitSurface(SDL_Surface *screen_r)
        {
             if(!TimeM){TimeM = SDL_GetTicks();}
     
             if(TimeM < SDL_GetTicks() - Config_.Time )
             {
                 ++Config_.Ani_Act;
                 TimeM = SDL_GetTicks();
                 if(Config_.Ani_Act > Config_.Ani - 1)
                     Config_.Ani_Act = 0;
             }
     
             Picture_Size.h = Config_.Height;
             Picture_Size.w = Config_.Width;
             Picture_Size.x = Config_.x + Config_.Ani_x*Config_.Ani_Act;
             Picture_Size.y = Config_.y + Config_.Ani_y*Config_.Ani_Act;
     
             SDL_BlitSurface( Picture, &Picture_Size, screen_r, &Sprit_Size );
        }
     
    }

    Sachan que draw est apeler en boucle, donc tout est come tu a notter...

    Pour resumer mon code est un peut come ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    static TimeM = 0;
    while(1)
    {
       if(TimeM <= SDL_GetTicks() + 1000)
       {
          ->Animer le sprite
          /* animation du sprite 1 fois par seconde (toutes les 1000ms) */
          TimeM = SDL_GetTicks();
       }
    }
    Sinon, a coi ser vaiment de définir static ici, et qu'adviendra t'il si je le défini dans ma classe?
    Mes articles Développez | Dernier article : Raytracer en haskell
    Network library : SedNL | Zenol's Blog : http://zenol.fr

    N'oubliez pas de consulter la FAQ et les cours et tutoriels.

  4. #4
    Membre éclairé
    Avatar de Zenol
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 812
    Par défaut
    Sinon, a coi ser vaiment de définir static ici, et qu'adviendra t'il si je le défini dans ma classe?
    Persone ne peut répondre a la question?


    Pour resumer mon code est un peut come ceci :
    Code:

    static TimeM = 0;
    while(1)
    {
    if(TimeM <= SDL_GetTicks() + 1000)
    {
    ->Animer le sprite
    /* animation du sprite 1 fois par seconde (toutes les 1000ms) */
    TimeM = SDL_GetTicks();
    }
    }
    Je présise que le bug ne dure que la 1ère seconde de l'aplication...
    Mes articles Développez | Dernier article : Raytracer en haskell
    Network library : SedNL | Zenol's Blog : http://zenol.fr

    N'oubliez pas de consulter la FAQ et les cours et tutoriels.

  5. #5
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Sinon, a coi ser vaiment de définir static ici, et qu'adviendra t'il si je le défini dans ma classe?
    Rien, dans ton cas c'est plus ou moins pareil, question de goût.

    Je présise que le bug ne dure que la 1ère seconde de l'aplication...
    Et si tu initialises TimeM à SDL_GetTicks() plutôt qu'à zéro ?

  6. #6
    Membre éclairé
    Avatar de Zenol
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 812
    Par défaut
    Techniquement c'est fesable, sauf que si je créer un objet de ma classe, et que je n'ai pas encore démarer l'aplication sa vas plenter... Bon je teste quand même :

    Resulatat : Sa fait pareille pendent la première seconde...
    C'est comme si pendent la première seconde la fonction n'en fesai que a sa tête... Tien j'ai une idée, je vais mêttre dans un log la valeur de TimeM dans le programe, histoire de voire ^^

    Bon apprès analise du fichier de log, je vien de comprendre le problème, un truc vraiment bête, je done la réponsse en petit, pour les curieux qui veulent chercher : le fichier de log : http://t4cwebserver.free.fr/stderr.txt

    La réponse : Enfaite je fesai SDL_GetTicks() - 1000 donc le résultat devais être négatife! Maleureusement je me retoruver avec un nombre poisitif qui valais le maximme de la variable int car aperement c'était signed... Enfin regardez les log, vous verez ^^
    Mes articles Développez | Dernier article : Raytracer en haskell
    Network library : SedNL | Zenol's Blog : http://zenol.fr

    N'oubliez pas de consulter la FAQ et les cours et tutoriels.

  7. #7
    Membre Expert
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 577
    Par défaut
    Donc au final le code que je te donnais résolvait ton problème car :

    1- TimeM était initialisé à SDL_GetTick()
    2- Je compare TimeM à SDL_GetTick() sans recalcul
    3- Lorsque j'anime le sprite, je mémorise dans TimeM SDL_GetTick() + 100 (+ 1000 dans ton cas) pour indiquer que la prochaine anim aura lieu dans 1000ms

    pour ce qui était du static, c'est utile dans une fonction où une variable est amenée à être réutilisée mais comme tu n'avais pas dis que tu l'utilisais dans une classe évidememtn cela change tout
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  8. #8
    Membre éclairé
    Avatar de Zenol
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 812
    Par défaut
    Donc enfaite le "1- TimeM était initialisé à SDL_GetTick() " je ne peut pas car je ne veut pas apeller SDL_GetTickets avent que SDL soit initialiser. Sinon, d'apprès ce que j'ai comprit, si static est mit dans une classe, cette variable est globale a tout les objets crées, ce qui constitue une économie de mémoire conséquente non? Comme j'aurais la même variable pour ma classe et ma classe dériver non?
    Mes articles Développez | Dernier article : Raytracer en haskell
    Network library : SedNL | Zenol's Blog : http://zenol.fr

    N'oubliez pas de consulter la FAQ et les cours et tutoriels.

  9. #9
    Membre Expert
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 577
    Par défaut
    Ok pour l'init de TimeM mais rien ne t'empêche d'initialiser SDL avant ou si tu préfères initialiser uniquement la partie timer avec :
    SDL_InitSubSystem(SDL_INIT_TIMER);

    pour ce qui est du static dans une classe attention car le membre aura la même valeur pour toutes les instances de la classe et si cette valeur change elle changera pour toutes les instance de la classe et ses dérivées
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  10. #10
    Rédacteur
    Avatar de bafman
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    2 574
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2003
    Messages : 2 574
    Par défaut
    cet exemple montre bien pourquoi il ne faut JAMAIS que les differentes classes gerent elles même le temp en interne...

    Et qu'est ce que tu fais le jour ou tu veut mettre ton jeu en pause (pour retourner au menu par exemple) ?
    quand tu relancera le jeu tu aura un temps ecoulé de x mille secondes alors que le temps ecoulé réelement dans le jeu sera de... 0 s...

    Pour bien gerer le temps dans une application, il faut que cette gestion soit centralisée, avec une simple methode qui calcule le temps ecoulé et qui le passe en parametre au jeu, ainsi tu est sure que tout les objets de ton jeu serons bien synchronisé (imaginons que l'anti-virus (quel lourd) se lance en plein milieu d'une frame, bloquant le jeu pendant 3 s... tu aura la moitié de tes objets qui seront decalé de 3 seconde par rapport au autre si chaqu'un gere sont propre temps )

    voila en gros (TRES gros et TRES generique ) le type d'architecture qu'il faudrait utiliser :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    class engine{
        int previousTime;
        int elapsedTime;
        void proccesTime(){
            int time = SDLGetTicks();
            elapsedTime = time - previousTime;
            previousTime = time;
        };
        void initTime(){
            previousTime = SDLGetTicks();
        }
    };
    ainsi la gestion du temps est centralisé dans une seule classe qui calcule le temps ecoulé, peut etre initialisée quand on veut et etre stoppé (il suffit de refaire appel a initTime pour relancer le decompte normal du temps)
    ensuite chaque objet devra avoir une methode update qui prend en parametre le temps ecoulé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    class Objet{
        virtual void update(int elapsedTime);
    };
    ainsi lors de la mise a jours, ce n'est plus l'objet lui même qui calcule le temps ecoulé mais le moteur qui ensuite l'envoie a chaque objet.
    En plus d'avoir une meilleur gestion du temps, tu y gagne en terme de code car tu n'a pas a reécrire la partie gestion du temps de chaque objet...
    * Il est infiniment plus simple de faire rapidement un code qui marche que de faire un code rapide qui marche
    * pour faciliter les recherches, n'oubliez pas de voter pour les réponses pertinentes
    Mes articles

  11. #11
    Membre éclairé
    Avatar de Zenol
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 812
    Par défaut
    Il y a un problème, je voulais faire gagner de la mémoire en mettent statique ma variable TimeM. Hor, avec le nouveau code, je ne peut plus la rendre static...

    Quand a la gestion du tmep, je suis bien obliger de la mêttre pour chaque objet, car il y a des vitesses d'animation diférente.
    Parcontre, l'idée de gérer le tmep dans une classe est intéréssent, je pourais créer une variable du genre Time::GetTicks qui contiendrais le temp, plutot que de faire apelle a SDL_GetTicks, et mêtre une fonction qui arrète de comptabiliser le temp dans Time::GetTicks
    Du genre :
    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
     
    class Time
    {
        public:
            unsigned int GetTicks
            unsigned int MemoTime;
            bool Pause;
            void Time()
            {
                GetTicks = SDL_GetTicks();
                MemoTicks = SDL_GetTicks();
            }
            void processTime()
            {
                if(!pause)
                {
                int time = SDL_GetTicks();
                GetTicks += time - MemoTime;
                MemoTime = time;
                }
            }
            void Pause()
            {
                Pause = !Pause;
            }
    }
    Mais ce que je voudrais résoudre c'est économiser 1 variable de temp par objet de ma classe... Quelquin a une idée e comment faire?
    Mes articles Développez | Dernier article : Raytracer en haskell
    Network library : SedNL | Zenol's Blog : http://zenol.fr

    N'oubliez pas de consulter la FAQ et les cours et tutoriels.

  12. #12
    Membre Expert
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 577
    Par défaut
    tu dois mémoriser le dernier temps relevé, tu n'as rien besoin d'autre que d'une variable, si tu veux gérer la pause en interne de la classe, utilises un masque :

    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
    class CTimer
    {
    public:
       CTimer() // constructeur
       {
          m_Time = SDL_GetTicks(); // initialise le temps
          m_Mask = ~0; // initialise le masque (inverse de 0 = 0xFFFFFFFF)
       }
       ~CTimer() {} // rien à détruire
       void Pause(void) // bascule le mode pause
       {
          m_Mask ~= m_Mask; // inverse le masque (0xFFFFFFFF -> 0x00000000 -> 0xFFFFFFFF ...)
       }
       Uint32 Process(void) // calcule et retourne le temps écoulé depuis la dernière fois
       {
          Uint32 tmp = m_Time; // mémorise le dernier temps
          m_Time = SDL_GetTicks(); // récupère le temps actuel
          return (m_Time - tmp) & m_Mask; // retourne le temps écoulé (si on est en pause, le masque est à 0 et donc le & fait qu'on renvoie 0)
       }
    protected:
       Uint32   m_Time;
       Uint32   m_Mask;
    }
    quand à économiser une variable, explique moi pourquoi te casser la tête à économiser 4 octets ?
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

Discussions similaires

  1. [SDL 1.2] Bug d'un Event SDL (clic de souris)
    Par Ryzen dans le forum SDL
    Réponses: 2
    Dernier message: 16/01/2015, 11h48
  2. [Cpp/SDL]Problème bug différent entre version install et debug
    Par Maldus dans le forum Développement 2D, 3D et Jeux
    Réponses: 4
    Dernier message: 09/02/2009, 12h12
  3. Bug de la SDL avec les grands curseurs
    Par Eusebe dans le forum SDL
    Réponses: 6
    Dernier message: 31/01/2008, 08h13
  4. Compilé avec VC++ sous vista avec sdl (bug)
    Par Narkoleptik dans le forum Visual C++
    Réponses: 3
    Dernier message: 06/03/2007, 18h47

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