Problems calculating time between frames using SDL_GetTicks

?Hello all:

This is my current loop code(part of it):

// main loop
for(;:wink:
{

    // get time before frame
    this->beforeFrameTime = (float)SDL_GetTicks();

    // handle events
    this->handleEvents();

    // handle user staff
    // .................


    // do rendering stuff
    // ..................


    // increase frame count
    this->frame++;


    // regulate fps
    if((this->maxFPS > 0) && ((SDL_GetTicks() -

this->beforeFrameTime) < (1000.0 / this->maxFPS)))
{
// wait until the desired time has passed
SDL_Delay((Uint32)((1000.0 / this->maxFPS) - (SDL_GetTicks()

  • this->beforeFrameTime)));
    }

      // get time after frame
      this->afterFrameTime = (float)SDL_GetTicks();
    
      // time since last frame
      this->deltaTime = this->afterFrameTime - this->beforeFrameTime;
    
    
      // time since first frame
      this->elapsedTime = SDL_GetTicks() - initialTime;
    
      // fps
      if(this->elapsedTime > 1000)
      {
          this->FPS = (float)(this->frame / (this->elapsedTime /
    

1000.0));
}

} // end of main loop

Sometimes when I call engine->getDeltaTime(), it will return a delta
time of zero causing animations to brake. Specially things like:

x += dx * deltaTime;

Is there a way around this? Am I using SDL_GetTicks() the right way.
Thanks a lot in advance.

-r

Hmm… I don’t see any problems with your usage of SDL_GetTicks().

I don’t see right away where your problem comes from, assuming your
GetDeltaTime() doesn’t have a silly mistake like converting to seconds
and returning an int (seeing more code would help there), but I do have
a few other notes:

You can clean up (and speed up) a little by using a delayTime variable
to store the result of 1000.0 / this->maxFPS whenever maxFPS is
changed by the user.

In this line,

this->FPS = (float)(this->frame / (this->elapsedTime / 1000.0));

You’re getting the average frame rate since the loop started. That is,
each successive frame will have less impact on the frame rate,
hiding big changes (stabilizing the result). What is usually
more helpful is to get the current frame rate. Also, the cast is
redundant.

this->FPS = 1000.0f/this->deltaTime;

And use—

bool done = 0;

while(!done)


instead of ‘for(;;)’, if you prefer.

Hope it helps,

Jonny D


Change the world with e-mail. Join the i?m Initiative from Microsoft.
http://im.live.com/Messenger/IM/Join/Default.aspx?source=EML_WL_ChangeWorld

Hello !

bool done = 0;

You mean :

bool done = false;

CU

FYI - The SDL_gfx library has a nice set of functions for this:

The functions return 0 or value for sucess and -1 for error. All functions
use a pointer to a framerate-manager variable to operate.

void SDL_initFramerate(FPSmanager * manager);

Initialize the framerate manager, set default framerate of 30Hz and
reset delay interpolation.

int SDL_setFramerate(FPSmanager * manager, int rate);

Set a new framerate for the manager and reset delay interpolation.

int SDL_getFramerate(FPSmanager * manager);

Get the currently set framerate of the manager.

void SDL_framerateDelay(FPSmanager * manager);

Generate a delay to accomodate currently set framerate. Call once in the
graphics/rendering loop. If the computer cannot keep up with the rate (i.e.
drawing too slow), the delay is zero and the delay interpolation is reset.

Rogelio Nodal wrote:

Hello all:

This is my current loop code(part of it):

// main loop
for(;:wink:
{

    // get time before frame
    this->beforeFrameTime = (float)SDL_GetTicks();

    // handle events
    this->handleEvents();

    // handle user staff
    // .................


    // do rendering stuff
    // ..................


    // increase frame count
    this->frame++;


    // regulate fps
    if((this->maxFPS > 0) && ((SDL_GetTicks() -

this->beforeFrameTime) < (1000.0 / this->maxFPS)))
{
// wait until the desired time has passed
SDL_Delay((Uint32)((1000.0 / this->maxFPS) - (SDL_GetTicks()

  • this->beforeFrameTime)));
    }

      // get time after frame
      this->afterFrameTime = (float)SDL_GetTicks();
    
      // time since last frame
      this->deltaTime = this->afterFrameTime - this->beforeFrameTime;
    
    
      // time since first frame
      this->elapsedTime = SDL_GetTicks() - initialTime;
    
      // fps
      if(this->elapsedTime > 1000)
      {
          this->FPS = (float)(this->frame / (this->elapsedTime /
    

1000.0));
}

} // end of main loop

Sometimes when I call engine->getDeltaTime(), it will return a delta
time of zero causing animations to brake. Specially things like:

x += dx * deltaTime;

Is there a way around this? Am I using SDL_GetTicks() the right way.
Thanks a lot in advance.

-r


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

-------------- next part --------------
A non-text attachment was scrubbed…
Name: aschiffler.vcf
Type: text/x-vcard
Size: 142 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20080602/c4ebe2b9/attachment.vcf

Thanks all for the answers. I will post my whole loop code to make things
better. This code does not take into account the suggested changes yet:

// main loop
for(;:wink:
{

    // get time before frame
    this->beforeFrameTime = (float)SDL_GetTicks();

    // handle events
    this->handleEvents();

    // handle user staff
    if(this->frameFunction() == EGEDONE)
    {
        // exit start if user says he is done
        // by returning DONE
        break;
    }


    // frame is not over so call render function to
    this->renderFunction();


    // increase frame count
    this->frame++;


    // regulate fps
    if((this->maxFPS > 0) && ((SDL_GetTicks() - this->beforeFrameTime) <

(1000.0 / this->maxFPS)))
{
// wait until the desired time has passed
SDL_Delay((Uint32)((1000.0 / this->maxFPS) - (SDL_GetTicks() -
this->beforeFrameTime)));
}

    // get time after frame
    this->afterFrameTime = (float)SDL_GetTicks();

    // time since last frame
    this->deltaTime = this->afterFrameTime - this->beforeFrameTime;


    // time since first frame
    this->elapsedTime = SDL_GetTicks() - initialTime;

    // fps
    if(this->elapsedTime > 1000)
    {
        this->FPS = (float)(this->frame / (this->elapsedTime / 1000.0));
    }

    // clear the vector of keys that were pressed and released
    this->pressedKeyboardKeys.clear();
    this->releasedKeyboardKeys.clear();

    // clear the vector of mouse buttons that were pressed and released
    this->pressedMouseButtons.clear();
    this->releasedMouseButtons.clear();

    // reset mouse wheel up/down movement tracking variables
    this->mouseWheelMovedDown = false;
    this->mouseWheelMovedUp = false;


} // end of main loop

I have another function called getDeltaTime and here is the code for it:

float EGE::getDeltaTime(void)
{

// return delta time
return (this->deltaTime / 1000.0);

} // getDeltaTime

Now, the problem is that sometimes I get a delta time of zero. Now mi theory
was that some frames get render in such a small interval that when I call
SDL_GetTicks I get the same milliseconds like the previous call. So I was
wondering is there was something that I was doing wrong.
There reason for my concern is that code like this will fail.

image_xposition += dx * dt;

I hope my problem can be understood better now. Thanks for the help.

One misstake i saw was the fact that the timing functions didnt span over the entire loop, the bottom half went outside everything.
One way to fix that is to NOT grab a beforeFrameTime using SDL_GetTicks() but by just copying the previous frames afterFrameTime into beforeFrameTime.
I also made a more accurate fps calculation and moved all the time code to the start of the loop.

And regarding your problem with a 0 deltatime and that position += dx * dt; wont work then thats not a problem. It should not move if no time has elapsed.

// main loop
for(;:wink:
{
// backup the previous frames afterFrameTime

    this->beforeFrameTime = this->afterFrameTime;



    // get time after frame


    this->afterFrameTime = (float)SDL_GetTicks();



    // time since last frame

    this->deltaTime = this->afterFrameTime - this->beforeFrameTime;



    // time since first frame


    this->elapsedTime = SDL_GetTicks() - initialTime;



    // fps

    this->FPS = 1.0f / this->deltaTime;




    // handle events
    this->handleEvents();

    // handle user staff
    if(this->frameFunction() == EGEDONE)
    {

        // exit start if user says he is done
        // by returning DONE
        break;
    }


    // frame is not over so call render function to
    this->renderFunction();



    // increase frame count
    this->frame++;


    // regulate fps
    if((this->maxFPS > 0) && ((SDL_GetTicks() - this->beforeFrameTime) < (1000.0 / this->maxFPS)))

    {
        // wait until the desired time has passed
        SDL_Delay((Uint32)((1000.0 / this->maxFPS) - (SDL_GetTicks() - this->beforeFrameTime)));
    }

    // clear the vector of keys that were pressed and released
    this->pressedKeyboardKeys.clear();
    this->releasedKeyboardKeys.clear();

    // clear the vector of mouse buttons that were pressed and released

    this->pressedMouseButtons.clear();
    this->releasedMouseButtons.clear();

    // reset mouse wheel up/down movement tracking variables
    this->mouseWheelMovedDown = false;
    this->mouseWheelMovedUp = false;



} // end of main loop

// Tomaz - Lead 3D Tech Developer / Tension GraphicsDate: Mon, 2 Jun 2008 22:39:32 -0400
From: rnodal@gmail.com
To: sdl at lists.libsdl.org
Subject: Re: [SDL] Problems calculating time between frames using SDL_GetTicks.

Thanks all for the answers. I will post my whole loop code to make things better. This code does not take into account the suggested changes yet:

// main loop
for(;:wink:
{

    // get time before frame

    this->beforeFrameTime = (float)SDL_GetTicks();

    // handle events
    this->handleEvents();

    // handle user staff
    if(this->frameFunction() == EGEDONE)
    {

        // exit start if user says he is done
        // by returning DONE
        break;
    }


    // frame is not over so call render function to
    this->renderFunction();



    // increase frame count
    this->frame++;


    // regulate fps
    if((this->maxFPS > 0) && ((SDL_GetTicks() - this->beforeFrameTime) < (1000.0 / this->maxFPS)))

    {
        // wait until the desired time has passed
        SDL_Delay((Uint32)((1000.0 / this->maxFPS) - (SDL_GetTicks() - this->beforeFrameTime)));
    }


    // get time after frame

    this->afterFrameTime = (float)SDL_GetTicks();

    // time since last frame
    this->deltaTime = this->afterFrameTime - this->beforeFrameTime;


    // time since first frame

    this->elapsedTime = SDL_GetTicks() - initialTime;

    // fps
    if(this->elapsedTime > 1000)
    {
        this->FPS = (float)(this->frame / (this->elapsedTime / 1000.0));

    }

    // clear the vector of keys that were pressed and released
    this->pressedKeyboardKeys.clear();
    this->releasedKeyboardKeys.clear();

    // clear the vector of mouse buttons that were pressed and released

    this->pressedMouseButtons.clear();
    this->releasedMouseButtons.clear();

    // reset mouse wheel up/down movement tracking variables
    this->mouseWheelMovedDown = false;
    this->mouseWheelMovedUp = false;



} // end of main loop

I have another function called getDeltaTime and here is the code for it:

float EGE::getDeltaTime(void)
{

// return delta time
return (this->deltaTime / 1000.0);

} // getDeltaTime

Now, the problem is that sometimes I get a delta time of zero. Now mi theory was that some frames get render in such a small interval that when I call
SDL_GetTicks I get the same milliseconds like the previous call. So I was wondering is there was something that I was doing wrong.

There reason for my concern is that code like this will fail.

image_xposition += dx * dt;

I hope my problem can be understood better now. Thanks for the help.


Skaffa Messenger i mobilen!
http://windowslivemobile.msn.com/Homepage.aspx?lang=se-se

Well, as long as everything else is done properly, here are the only ways this can happen:
SDL_GetTicks() returns bad stuff. This isn’t likely.
maxFPS <= 0. I trust you, so this is not likely.
Another function is messing it up. Ditto the last one.
or

Casting (1000.0 / this->maxFPS) - (SDL_GetTicks() - this->beforeFrameTime) as a Uint32 gives a result of 0.
Now this might be it. You can generally be very sure of SDL_Delay() giving an actual delay. In fact, you should probably make sure that it doesn’t delay too much due to its poor resolution (email me for code if you want to fix that). If you’re calling SDL_Delay(), you’ll never get SDL_GetTicks() to equal your previous call. Unless, however, you’re casting it to an integer when you have a float originally (well, double), then you might be calling SDL_Delay(0)! That could possibly do it. The way to fix that is to make your test identical to your argument:
// regulate fps
if((this->maxFPS > 0) && ((SDL_GetTicks() - this->beforeFrameTime) < (Uint32)(1000.0 / this->maxFPS)))
{
// wait until the desired time has passed
SDL_Delay((Uint32)((1000.0 / this->maxFPS) - (SDL_GetTicks() - this->beforeFrameTime)));
}

Boy, I hope that’s it.
Jonny D_________________________________________________________________
Now you can invite friends from Facebook and other groups to join you on Windows Live? Messenger. Add now.
https://www.invite2messenger.net/im/?source=TXT_EML_WLH_AddNow_Now

WOW! Thanks a lot for the help guys. I have seriously learned knew stuff.
About the issue of getting a delta time of zero, it is normal, I completely
had it misunderstood. For example the whole issue of getting a delta time
that is zero, never happens if I enable multi sampling. Jonny D I would love
to take a look at that code. I’m making a 2D game engine that is going to be
open source so if my code gets better the community will benefit to. One
more time thanks a lot for your great help. I’m glad I went with SDL/OpenGL
as my backends.

-R