Thread: [SDL+OpenGL] Constant framerate code?

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    22

    Question [SDL+OpenGL] Constant framerate code?

    Hey people

    I've been making a game in SDL and OpenGL but I'm having some problems with the framerate... is there a way I can make the game run at, for example, 30fps on any machine? (smoothly if on fast PC and skipping frames if in slow PC?)... I know the theory behind, but I've been googling around and such and I haven't found any code to adapt to my game in any way :/.

    I've tried some codes around in google that look simple, but when I try them, the game either stutters or hangs up between the wait time. I don't want the game to stop every second, I want it to flow at the same speed in any machine...

    Any help is appreciated!

    - DARKGuy

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Showing results 1 to 25 of 91
    Search took 0.86 seconds. Search: Key Word(s): framerate
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158
    If your code waits too long, you probably forgot timeBeginPeriod(1) and timeEndPeriod(1)

  4. #4
    Registered User
    Join Date
    Aug 2004
    Posts
    731
    If you are using windows all you have to do is use high precision timing:

    QueryPerformanceCounter
    QueryPerformanceFrequency

    and with those calcuate how much time you have to sleep at the end of the frame. Use the Sleep function but subtract about 2 or more milliseconds from the total ms needed to wait. After that go into a tight loop (ie a while(timeleft > 1)) and use the high precision timers to tell when the time is up.

    Not only does that achieve VERY good timing (at least for all of my tests) but it cuts CPU usage down to about 20% for my test. Using timeBeginPeriod may help you with this or it may not. For me it creates hickups and I don't know why but without it my timing is accurate to a few microseconds. But of course you get those 56, 58, 59 fps (when the target is 60fps) frames. Can't help that because usualy the fps has droped below 60 and there isn't much you can do about that with timing.

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    22
    Salem: Heh, thanks - one of the first threads found were helpful though it the code didn't work as I expected

    pronecracker: are those SDL functions? I've never heard of them...

    Rune Hunter: Yup, I've tried similar stuff with SDL_ticks and SDL_delay (those do something similar to what you explain) but, I'm using Linux ^^;;; forgot to mention that XD.

    However, the framerate control in SDL_gfx looks good, I guess I'm gonna use that in the meanwhile, but I wanna know how do I make my own one that does exactly what this one does, without just copying code because that's not fair :/ yet I know the theory (what you've all explained me) but no way to code it :S

  6. #6
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158
    You forgot to mention that you are using Linux. Ain't that a bit stupid? timeBeginPeriod is a Windows function. QueryPerformanceCounter is a Windows function.

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    To get a game to run at the same speed on various machines you DO NOT clamp the framerate. This is for something entirely different. Clamping the framerate on a super rig is a waste of cycles and a disaster for slower machines.

    To get the game to run at the same speed you must use a timeDelta value that represents the number of milliseconds that have elapsed since the last frame or update. Perform all of your movement calculations using this value and every machine will run the game at the same speed (IE: it will take computer 1 just as long as computer 2 to walk from point A to point B). However computer 1 may be a dinosaur while computer 2 is a super uber rig. If you limit computer 2 to 30 FPS no matter what, the user of that system will not be happy with you.

    The only way to ensure objects move at the same speed on all machines is to take note of the time upon entering the game loop and then take the time at the end of the loop. Subtract them, convert to the proper data type if necessary, and use this value as your frameDelta. I assure you that in an online game everyone is not getting the same framerate, but everyone is playing the same game and everyone is moving at the relatively same speed on all machines. The slower computer will slow everyone down and will also show tons of on-screen lag as objects flitter and jump about while the faster computer will show very smooth motion.

    The idea is that even though the super rig is getting 120 FPS the timeDelta value is much less since it takes less time for the super rig to render thus each object moves less distance per game loop resulting in much smoother motion. So while the dinosaur is getting 30 FPS, the actual update or timeDelta is going to be quite large. This will cause objects to jump about and warp which is what we all know and hate........LAG. So essentially the super rig is taking more 'snapshots' per game loop than the slow computer. But they both take the same time to move from point A to point B in the game. So computer 1 takes 10 seconds to get from point A to point B, but it updates 1000 times during this period (assuming 100 FPS). Computer 2 takes 10 seconds to get from point A to point B, but it updates 300 times (assuming 30 FPS). Clearly computer 1 will show smoother motion than computer 2.


    If you clamp at 30 FPS this means you can at max get 30 FPS. So in dense areas of high detail graphics you will probably get much less. Even though the computer and video card may be able to handle more, you've essentially thrown the extra horsepower to the wind by clamping it. So in a very dense area you will have 0 frames to play with due to the clamping.
    Last edited by VirtualAce; 04-29-2007 at 07:50 AM.

  8. #8
    Registered User
    Join Date
    May 2006
    Posts
    22
    Wow Bubba, I guess you couldn't have explained it better! what I'm trying to do is to skip frames in slow machines and cap the framerate in fast machines - so both get the same framerate and the game when played online, both get the same speed, right? I've heard stuff about the timeDelta that causes problems in the future or it isn't as flexible as a framerate controller would be. However I guess I'm gonna give it a try and see how it goes - your explanation is very clear so I guess I can make code out of it and try, thanks for that!

  9. #9
    Registered User OnionKnight's Avatar
    Join Date
    Jan 2005
    Posts
    555
    I think I learned something as well. Instead of capping FPS you scale the time appropriatel instead so two machines can run on different FPS but at the same game speed.
    Instead of something like
    Code:
    #define FPS 60
    
    int t_prev = SDL_GetTicks();
    
    while (game_loop) {
        int t = SDL_GetTicks();
    
        if ((t - t_prev) > 1000/FPS) /* Ticks are in milliseconds so 1000 is used instead of 1 */
            next_frame();
    
        t_prev = t;
    }
    
    void next_frame (void)
    {
        some_object.x_pos += some_object.x_velocity;
    }
    you do
    Code:
    #define GAME_SPEED 60
    
    int t_prev = SDL_GetTicks();
    
    while (game_loop) {
        int t = SDL_GetTicks();
    
        next_frame((t - t_prev)*GAME_SPEED/1000.0);
    
        t_prev = t;
    }
    
    void next_frame (double dt)
    {
        some_object.x_pos += some_object.x_velocity*dt;
    }
    Instead of incrementing the frames one by one (like integers) you increment them using fractions which scales the changes (which is basically what you do when you increment the frames one by one except that you don't notice it since x*1 = x).

  10. #10
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I've heard stuff about the timeDelta that causes problems in the future or it isn't as flexible as a framerate controller would be.
    Please, do tell.

  11. #11
    Registered User
    Join Date
    May 2006
    Posts
    22
    Quote Originally Posted by Bubba View Post
    Please, do tell.
    Well, I found something here... -> http://math.smsu.edu/~erik/articles/timer/timer.html

    Also, I find it confusing to use a timedelta... the normal thing would be to work with frames! :/ ... or so I think... say, you want something to move from x=0 to x=10 in 5 frames.. there's no way you can calculate that with a timedelta =/ besides, would a timedelta help when the game gets online? what about slow computers vs fast computers? I'm looking for some kind of speed consistense between all types of machines... if they're slow then skip frames (or make it faster) and if they're too fast, slow it down to the constant speed...

  12. #12
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I think they present two methods both with their advantages and disadvantages, not saying which one you should use.

    So I leave it up to you to decide which to implement.

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    If you separate your world view from your screen view, then working with dT in the world makes much more sense.

    Say your 'car' is travelling at 1 metre per second.
    Now if you limit the frame rate to say 10Hz, that is basically saying move the car 10cm, then redraw it.

    But if you take the approach of using a dT, then you look at the dT (say 100ms), and move the car by it's velocity (1m/sec) by the dT (0.1 sec), and get the 10cm we had before.
    On a faster machine, dT is lower (say 50ms), and you move the car by it's velocity (1m/sec) by the dT (0.05 sec), and get 5cm of movement.

    It still travels the same distance in the world, in the same amount of real time, but the visual effect will be that much smoother on a faster machine.

    What is more, the dT approach is self-correcting. Zoom into a small part of the world, and there is less work to do, so you get more effective frames per second.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  14. #14
    Registered User
    Join Date
    May 2006
    Posts
    22
    Well... now that I think about it, I guess I'm gonna give the TimeDelta framerate thing a try, however I learn better with code - is OnionKnight's code a pseudo-code of a TimeDelta implementation?

  15. #15
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    I hadnt considered that method, but I think Ill use it in my game. Now the issue is synchronizing clients who have differnt ping times...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Proposal: Code colouring
    By Perspective in forum A Brief History of Cprogramming.com
    Replies: 28
    Last Post: 05-14-2007, 07:23 AM
  2. Values changing without reason?
    By subtled in forum C Programming
    Replies: 2
    Last Post: 04-19-2007, 10:20 AM
  3. Explain this C code in english
    By soadlink in forum C Programming
    Replies: 16
    Last Post: 08-31-2006, 12:48 AM
  4. Replies: 4
    Last Post: 01-16-2002, 12:04 AM
  5. constant code
    By Unregistered in forum Windows Programming
    Replies: 1
    Last Post: 12-06-2001, 04:25 AM