views:

5931

answers:

4

I am programming a game on the iPhone. I am currently using NSTimer to trigger my game update/render. The problem with this is that (after profiling) I appear to lose a lot of time between updates/renders and this seems to be mostly to do with the time interval that I plug into NSTimer.

So my question is what is the best alternative to using NSTimer?

One alternative per answer please.

A: 

Have you looked at the iPhone developer examples? I think there are some examples (Touch Fighter or CrashLanding, for example) that might be illuminating.

Mark Bessey
I have looked at many examples and researched alternatives on the internet. So I already know there some alternatives. What I am really after is what other people think the best alternative is? I am working on an extremely short project so any time saved on investigation will be a big help.
Ashley Davis
A: 

When you say you're losing time, what do you mean exactly? It's inevitable that there will be idle time where your game is sitting around waiting for the screen to refresh.

Ashley Davis
It varies a lot because your gameloop is going in and out of phase with the display. Just run the timer at the same freq as the screen's refresh-rate.
+2  A: 

I don't know about the iPhone in particular, but I may still be able to help: Instead of simply plugging in a fixed delay at the end of the loop, use the following:

  • Determine a refresh interval that you would be happy with and that is larger than a single pass through your main loop.
  • At the start of the loop, take a current timestamp of whatever resolution you have available and store it.
  • At the end of the loop, take another timestamp, and determine the elapsed time since the last timestamp (initialize this before the loop).
  • sleep/delay for the difference between your ideal frame time and the already elapsed time this for the frame.
  • At the next frame, you can even try to compensate for inaccuracies in the sleep interval by comparing to the timestamp at the start of the previous loop. Store the difference and add/subtract it from the sleep interval at the end of this loop (sleep/delay can go too long OR too short).

You might want to have an alert mechanism that lets you know if you're timing is too tight(i,e, if your sleep time after all the compensating is less than 0, which would mean you're taking more time to process than your frame rate allows). The effect will be that your game slows down. For extra points, you may want to simplify rendering for a while, if you detect this happening, until you have enough spare capacity again.

Galghamon
+11  A: 

You can get a better performance with threads, try something like this:

- (void) gameLoop
{
    while (running)
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        [self renderFrame];
        [pool release];
    }
}

- (void) startLoop
{
    running = YES;
#ifdef THREADED_ANIMATION
    [NSThread detachNewThreadSelector:@selector(gameLoop)
    toTarget:self withObject:nil];
#else
    timer = [NSTimer scheduledTimerWithTimeInterval:1.0f/60
    target:self selector:@selector(renderFrame) userInfo:nil repeats:YES];
#endif
}

- (void) stopLoop
{
    [timer invalidate];
    running = NO;
}

In the renderFrame method You prepare the framebuffer, draw frame and present the framebuffer on screen. (P.S. There is a great article on various types of game loops and their pros and cons.)

zoul