limiting frame rate

Member
Posts: 194
Joined: 2009.02
Post: #1
What's the best method for limiting a game's frame rate(to 30 fps) on the iphone?
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #2
Now why on earth would you want to do that? The screen is capable of 60hz. Don't artificially make your game look like a slideshow...
Quote this message in a reply
Member
Posts: 194
Joined: 2009.02
Post: #3
My game's frame rate can vary considerably and the moving objects in my game have timers which are based on absolute time. So when my game runs at 55 fps, the stuff in the game moves considerably faster than when it's running at 40 fps.
Quote this message in a reply
⌘-R in Chief
Posts: 1,237
Joined: 2002.05
Post: #4
Well that means you have a fundamental problem. If your game runs at 20 fps for some reason then it'll be wrong then too. You need to do your math properly and not use absolute units regardless of time.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #5
Frame-rate capping is reasonable solution, if not ideal. If you can't ensure a consistent 60 or 30fps rate, you can cap the maximum rate to whatever you can ensure. The lower, but consistent, rate may be less objectionable than intermittently dropping frames.

For a real world example, see one of the best games ever: Legend of Zelda: Ocarina of Time. It caps to 20 fps.

To implement this, you simply need to keep track of how much time has elapsed since your last framebuffer swap. If you've completed all the rendering, but you need to delay, don't present the framebuffer yet. Go to sleep (i.e. conserve battery) and wait for the next timer interrupt.

Of course ideally you'd optimize everything to hit 60fps all the time. But this can be quite difficult, regardless of how fast your hardware is Wink
Quote this message in a reply
Member
Posts: 749
Joined: 2003.01
Post: #6
I agree with arekkusu.

Doing time-dependent updates won't solve your problems if your framerate gets too low (the game would then run choppy). So you need to keep your framerates above a certain level anyway. At that point you might as well use that level as your consistent framerate.

©h€ck øut µy stuƒƒ åt ragdollsoft.com
New game in development Rubber Ninjas - Mac Games Downloads
Quote this message in a reply
Member
Posts: 194
Joined: 2009.02
Post: #7
Yeah I know absolute time is a less than elegant way to do things but I'm just trying to get this thing working and out the door asap.

arekkusu Wrote:Of course ideally you'd optimize everything to hit 60fps all the time. But this can be quite difficult, regardless of how fast your hardware is Wink

Thanks a lot arekkusu for your advice. I tried your suggestion but I'm not sure if what I am doing is exactly correct. The below code does properly constrain the frame rate to 33.3 fps but there is a noticeable feeling of latency while playing the game(beyond just the normal feeling of latency associated with any 30hz game). I'm hoping someone could point out any obvious flaws in my code, thanks.



Code:
double get_current_time(void)
{
    static mach_timebase_info_data_t sTimebaseInfo;
    uint64_t time = mach_absolute_time();
    uint64_t nanos;
    
        if ( sTimebaseInfo.denom == 0 ) {
        (void) mach_timebase_info(&sTimebaseInfo);
    }
    nanos = time * sTimebaseInfo.numer / sTimebaseInfo.denom;
    return (double)nanos * 1.0e-9;
}


void delay(void)
{
    static double    last_update_time = 0.0;
    double    curr_time = get_current_time();
    
    if (last_update_time == 0.0)
        last_update_time = curr_time;
    
    double    time_since_last_update = curr_time - last_update_time;
    
    
    
    if (time_since_last_update >= 0.03)
    {
        last_update_time = curr_time;
        
        return;
    }
    
    while ((get_current_time() - last_update_time)< 0.03)
    {
        time_since_last_update = get_current_time() - last_update_time;
    }
    last_update_time = get_current_time();
    time_since_last_update = get_current_time() - last_update_time;
    
}
Quote this message in a reply
Member
Posts: 245
Joined: 2005.11
Post: #8
This is your problem:
Code:
while ((get_current_time() - last_update_time)< 0.03)
    {
        time_since_last_update = get_current_time() - last_update_time;
    }

This while loop which blocks the thread, interfering with input events and wasting battery power.
What arekkusu said was "Go to sleep (i.e. conserve battery) and wait for the next timer interrupt." The easiest way would be to just return from your timer callback. That's what I would do on the Mac and I assume it would be fine on the iPhone.
You do have your main loop controlled by NSTimer, don't you?
If not, there may be a proper sleep function - or you could maybe try doing something with performSelector:withObject:afterDelay: instead.
Quote this message in a reply
Member
Posts: 194
Joined: 2009.02
Post: #9
Okay I think I understand, what I should be doing is this

Code:
- (void)drawView
{
    [EAGLContext setCurrentContext:context];
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);

    render_scene();    
        if (time_since_last_frame <0.03)
             return;    

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
Quote this message in a reply
⌘-R in Chief
Posts: 1,237
Joined: 2002.05
Post: #10
Najdorf Wrote:I agree with arekkusu.

Doing time-dependent updates won't solve your problems if your framerate gets too low (the game would then run choppy). So you need to keep your framerates above a certain level anyway. At that point you might as well use that level as your consistent framerate.


Huh? Apparently what I said was completely misinterpreted. Your game's math should not require your frame rate to be anything. You're asking for trouble. If it runs at any rate other than what is required, then the results are wrong.

Calculate your results using a fixed timestep value, but let the actual frame rate vary because it inevitably will. You can't guarantee your process will get consistent timing.


This is a good reference...

http://sacredsoftware.net/tutorials/Anim...tion.xhtml
Quote this message in a reply
Apprentice
Posts: 14
Joined: 2009.04
Post: #11
I'm with FreakSoftware here, it's really easy to calculate a floating point value how much seconds have passed since the last frame you drew and multiply all of your distances and other time dependent calculations with this number. That way you can also define your velocities in screen units per second, which is easier to wrap your head around.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #12
saltwater Wrote:it's really easy to calculate a floating point value how much seconds have passed since the last frame you drew and multiply all of your distances and other time dependent calculations with this number

Easy but nondeterministic. See the above link for an explanation of why and a deterministic approach.
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #13
With the iPhone you essentially have two devices, one which is normally at least twice as fast as the other. If you can't make 60hz on the 3G (which in my experience will always be the case) then the only way you can get relatively consistent behavior on both the 3G and the 3GS is to cap them both at a lower frame rate.

Although it might be entirely possible to make a better experience on the 3GS with double the frame rate and time based physics, the experience is different. So I can see why people may decide to ditch frames in favor of consistency.

If you can't even always make 30hz on the 3G (which in my experience will nearly always be the case) then you have to decide whether you are going to update the game world by the amount of time passed or by a constant or capped amount (so slowing down perceived time). I disagree with those saying that you absolutely must make this time based. That might be fine, but if the device is off getting Mail or any one of the large pauses that might occur, a half a second of movement might be all it takes to cause death, in a single 'frame'. Often it is better to just pretend that a 30th of a second passed. The player sees a pause instead of a jump, which can be just fine.

There isn't really a right way here, it's just a matter of doing whatever suits your game the best.

As far as actually achieving a smooth capped frame rate, good luck with that. I've tried just about every method imaginable, and not come up with a result I am happy with. It seems that no matter what you do you will get frequent bursts of dropped frames at a capped frame rate on the 3G.

Please do tell if you find a method that works!

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Member
Posts: 440
Joined: 2002.09
Post: #14
reubert Wrote:... if the device is off getting Mail or any one of the large pauses that might occur, a half a second of movement might be all it takes to cause death, in a single 'frame'.
You won't have this problem if you cap to a maximum delta (say 1/10th of a second). That way the game won't run in realtime while the device is bogging, but you still get all the benefits of using a fixed step in every other situation.
Quote this message in a reply
Member
Posts: 241
Joined: 2008.07
Post: #15
When you setup your run loop, if you're using NSTimer, simply set the "firing" interval to 1/X, where X is the FPS you wish to cap it at. I agree, you should go with X = 60, but set it to 30 and you have what you want.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Frame rate issues markhula 7 6,291 Jan 15, 2011 09:47 AM
Last Post: markhula
  Frame Rate Consistency daveh84 4 3,494 May 4, 2010 12:19 PM
Last Post: AnotherJake
  iPod low upgrade rate to 3.0 jjslay 4 2,979 Jul 31, 2009 09:38 AM
Last Post: bruss14
  frame rate for a Quartz game? aerospaceman 2 3,858 Jun 22, 2009 10:56 AM
Last Post: longjumper
  mac mini simulator - slow frame rate sumiguchi 3 3,707 Dec 18, 2008 08:56 AM
Last Post: SafariAl