Frame Rate Consistency

Posts: 35
Joined: 2009.01
Post: #1

I'm trying to find out the best way to run a game loop for a consistent, smooth gameplay experience. I've tried 2 different ways of running my loop, and neither of them have proven ideal. I've timed my scene rendering code and each frame takes an average of 0.0044 seconds to render and the max I've seen is < 0.01. However, some problems have still arisen..

Method # 1 - The strict NSTimer loop
This is the method used in the apple example I downloaded. In this method, a repeating animation timer is instantiated with an interval of 1.0/60.0. We draw the frame when the timer fires. With this method, there was an occasional problem where somehow the timer would only end up firing half as often.

Method # 2 - The flexible NSTimer loop
In this method, I use a timer with a much shorter interval and when it fires, wait until 0.01667 seconds have elapsed before drawing. This eliminates the half-speed problem (which is a huge problem for my game because it essentially makes it twice as easy, as the game is reflex-oriented) but occasionally frames are now dropped. I use a fixed frame rate kSecondsPerFrame = 0.01667f so dropping a frame causes a screen "jerk".

Method # 3 - Not attempted... Using a dynamic frame rate?
I've used this method in the past but not with an NSTimer... Determining the elapsed time since the previous frame should be the best method, but I'm just concerned about a timer attempting to fire in the background... Does a higher timer interval reduce input responsiveness?

What methods have you guys used? Any suggestions?
Quote this message in a reply
Posts: 81
Joined: 2007.07
Post: #2
Use #1 and #3, just use the apple example code, except in your game logic don't use a hardcoded 1/60s time, measure the actual time passed and use it. It may be 1/60 or may not, either way it doesn't matter and will work as intended.
Quote this message in a reply
Posts: 3,591
Joined: 2003.06
Post: #3
Oh boy, there's been a lot of discussion about this. I don't have links to threads handy, sorry.

Basically what's up is that the frame rate of the screen is locked -- often referred to as the display's refresh rate. You can't change it. For LCDs, like the iPhone/iPad/iPod Touch/All new Macs, the display refresh rate is somewhere close to, but not very often exactly, 60 Hz.

So let's say you are able to always draw your scene so that it'll be on time every time with the display refresh. You'd probably want to find a way to try firing the timer so that it falls on the display's refresh. Thing is, timers just aren't accurate enough for this, in conjunction with all the other stuff that happens. So you skip a frame and you get a visual jerk in the animation.

Further, let's say your timer is a little faster than the display refresh. In the case of the iPhone, and Mac if you have VBL synch turned on, the gl context is blocked while waiting for the next refresh. That will automatically mean that mathematically you will only be able to draw at some evenly divisble multiple of the refresh rate. This would typically be noticed by an apparent dramatic drop from like 60 FPS to like 45 FPS or 30, or 20, etc.

One way around this is to fire the timer really fast so that you're almost always guaranteed to be blocking, waiting for the next draw. This works great on Mac using a 1 kHz timer, but not so well on iPhone, and is a rather inefficient usage of processing power (especially on iPhone).

Another way around this is to use a tight loop which essentially does the same thing as an over-revved timer, but doesn't waste system resources with the actual timer bit. This seems to be a pretty popular way to do things for many, although I still find it overkill myself, and stick with the good ol' 60 Hz timer. I'll get into that more in a bit.

Yet another approach is to use a display link, which operates very similar to a 60 Hz timer, but is more consistent on timing. On iPhone, many have claimed that it solved their timer problems, but it didn't help me since I wasn't having problems to begin with. On Mac the display link is ideal in terms of timing, but it requires you to understand how to do multi-threaded programming.

So there I discussed the main ways to get your code called for drawing. To recap:
- 60 Hz timer
- Over-revved timer (120 Hz on iPhone, 1kHz on Mac)
- Display link timer
- Tight loop

At this point it is important to note that none of those can take into account your game slowing down internally because of too much drawing or logic being processed. This is the main reason why games have inconsistent timing and why everyone has troubles at first. There is a really good way around this, and that is to separate your drawing code and your game logic -- that is: you need to separate your drawing code from your updating code. Check out:


Once you do at least the first technique at Sacred Software, you can further refine your animation with sub-interpolation in the gafferongames link. The sub-interpolation will give you the absolute best animation you could ask for and works fantastic with just about any main timing method, be it a timer or tight loop or display link, but it can take a bunch more code and organization to implement, depending on what you're doing. However, just using a constant update step is plenty sufficient for most games.

For the record, our game, Ace Omicron, which is available for iPhone and iPad uses only the standard 60 Hz timer. It doesn't even use the display link. I think it looks fine in terms of animation consistency. The one thing which does cause tiny inconsistencies is not the graphics at all, but rather the networking code in OpenFeint -- especially on older gen iPhones. If I don't use OpenFeint, it's as smooth as one would reasonably wish for. Even on iPad I can see tiny inconsistencies when running OpenFeint. Probably the only reasonable way to really get rid of that is to use sub-interpolation, but I didn't bother implementing it. Animation remains fairly consistent, even when drawing upwards of 8-10 thousand lit and depth-tested triangles and hundreds of blended sprites, and even a large blended sprite in the background (which is the max you'll see in Ace Omicron, and it still maintains around 20 FPS or higher when bogged down). My point being that the standard 60 Hz timer is plenty good enough for most stuff, if you know how to separate your update and draw.
Quote this message in a reply
Posts: 283
Joined: 2006.05
Post: #4
That's a great post Jake. It's a topic that seems like it should be so simple, but there are so many different opinions and subtleties that it can get confusing. You've cleared it up a lot, so thanks.
Quote this message in a reply
Posts: 3,591
Joined: 2003.06
Post: #5
Glad you found it helpful maximile Smile

I had a whole bunch more to say about it, but I tried to keep it as short as possible. Unfortunately, that means a bunch got glossed over. Like you said, it's not quite as simple as one might think, if you start looking at all the options.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Frame rate issues markhula 7 8,595 Jan 15, 2011 09:47 AM
Last Post: markhula
  limiting frame rate NelsonMandella 14 9,168 Sep 16, 2009 02:57 PM
Last Post: bmantzey
  iPod low upgrade rate to 3.0 jjslay 4 4,433 Jul 31, 2009 09:38 AM
Last Post: bruss14
  frame rate for a Quartz game? aerospaceman 2 5,052 Jun 22, 2009 10:56 AM
Last Post: longjumper
  mac mini simulator - slow frame rate sumiguchi 3 5,624 Dec 18, 2008 08:56 AM
Last Post: SafariAl