SDL Problems

Member
Posts: 215
Joined: 2008.06
Post: #1
I have been working on improving my game engine for a short while now, and I have run into something very strange while using SDL. My original setup had the rendering, AI, and physics engine in the SDL loop. My physics engine was called to update and passed timing information from the loop as below:

Code:
//...OTHER SDL CODE ABOVE
        //Standard SDL initialization calls.
        flags = SDL_OPENGL;
    drawContext = SDL_SetVideoMode(1024, 768, 0, flags);
    
        //Create a variable that can be used between calls of this loop and grab the
        //current clock time.
    static double timeBetweenUpdates = SDL_GetTicks();
    
    while (!done)    //SDL Loop
    {
        //Find the time difference from the last time grab
        double dif = -(timeBetweenUpdates - SDL_GetTicks());
        
        //Update that physics engine by the time interval
        [pe updateByInterval:dif];
        
        //Grab the new clock time
        timeBetweenUpdates = SDL_GetTicks();
        
        while (SDL_PollEvent(&event))
        {
            switch (event.type)
            {
//EVENT CODE BELOW...

I also had the standard drawScene() function that calls OpenGL and draws everything, generally at the end of the loop.

Where this gets weird is that I have recently condensed my game engine into a single collection that simply takes an update call and a time interval, very similar to original implementation. However, the new game engine does it's own drawing by calling the same render engine I had before hand, but no drawScene() function in the SDL loop.

With this new setup, an attempt to pass in the time change generates a 0.0 time interval more than 90% of the time. I put in multiple debug statements, stepped through the program step by step and found that doing the drawScene() function causes an interval of ~2 on a consistent basis. But the new implementation WITHOUT the drawScene() function consistently generates a time interval of 0.

The new program was literally copy-pasted into the new main file, so it looks almost identical. The updateAllByInterval call advances the entire encapsulated game engine that is ge.

Code:
//...OTHER SDL CODE
        flags = SDL_OPENGL;
    drawContext = SDL_SetVideoMode(1024, 768, 0, flags);
    
    static double timeBetweenUpdates = SDL_GetTicks();
    
    while (!done)
    {
        double dif = -(timeBetweenUpdates - SDL_GetTicks());
        
        [ge updateAllByInterval:dif];
        
        timeBetweenUpdates = SDL_GetTicks();
        
        while (SDL_PollEvent(&event))
        {
            switch (event.type)
            {
//MORE BELOW...

Here are samples of the output from both of the programs:

Quote:This one works correctly, and this is how it should look:

TBU before = 5607.000000
GetTicks BEFORE = 5607.000000
Dif init = 2.000000
Milliseconds Passed In = 2.000000
Milliseconds Converted = 0.002000
TBU change = 5609.000000
TBU change = 5609.000000
GetTicks after draw = 5609.000000
TBU before = 5609.000000
GetTicks BEFORE = 5609.000000
Dif init = 2.000000
Milliseconds Passed In = 2.000000
Milliseconds Converted = 0.002000
TBU change = 5611.000000
TBU change = 5611.000000
GetTicks after draw = 5611.000000

This one is the new implementation with encapsulated drawing that functions strangely:

TBU before = 8574.000000
Dif init = -0.000000
Milliseconds Passed In To GAME = -0.000000
Milliseconds Passed In To PHYSICS = -0.000000
Milliseconds Converted = -0.000000
TBU change = 8575.000000
GetTicks = 8575.000000
TBU before = 8575.000000
Dif init = -0.000000
Milliseconds Passed In To GAME = -0.000000
Milliseconds Passed In To PHYSICS = -0.000000
Milliseconds Converted = -0.000000
TBU change = 8577.000000


Anyone have any insight as to what is going on?

I found a temporary fix: By using an "if" statement on dif == 0, and setting dif to 2 on that, it seems to work alright. However, being the harmonious kind of programmer that I am, this solution is nails on a chalkboard and I would greatly appreciate any insight. Thank you!

Mac users swear by their computers, PC users swear at their computers. ~Unknown

iSayz
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #2
Your problem is you are assigning timeBetweenUpdates after your call to updateByInterval. Since there is almost no work between then and the next time the loop executes, checking the time difference, the time difference is almost always 0. This mostly worked before since you put your draw call at the end of the loop, so it was between where you assigned timeBetweenUpdates and when you got the time difference. However, you didn't get any of the time spent in your update call, so you would always get a time difference that was too small. I would recommend fixing it as follows:
Code:
unsigned int currentTime = SDL_GetTicks();
unsigned int diff = currentTime - timeBetweenUpdates;
timeBetweenUpdates = currentTime;
Notice how I have only 1 call to SDL_GetTicks(). That way you will be gauranteed to never "lose" any time that was spent between the 2 calls.

A couple of notes. SDL_GetTicks() returns an integer number of milliseconds from when SDL started. That is a pretty coarse time resolution for real time applications. I would recommend using a function such as gettimeofday(), which has a resolution of 1 microsecond. Also, I would recommend turning the time step into a floating point value only after you compute the integer difference. This will make sure you will never loose precision (since gettimeofday returns 2 32 bit integers, one for seconds and one for microseconds), and it will also mean that you will only need single precision floats rather than doubles.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #3
Peripherally related to your original problem: Using a variable interval for physics calculations makes your game non-deterministic, and is likely to explode at large intervals. The easy solution is to use a fixed interval, and run a variable number of iterations of fixed-interval steps to add up to the real interval.

More info here: http://www.sacredsoftware.net/tutorials/...tion.xhtml
Quote this message in a reply
Post Reply