iDevGames Forums
Game Timer - Printable Version

+- iDevGames Forums (
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Game Programming Fundamentals (/forum-7.html)
+--- Thread: Game Timer (/thread-10457.html)

Game Timer - larswik - Dec 1, 2012 06:55 PM

Hey, Quick question. I have C and Object C experience with a app in the app store. but I started on my first game to have fun learning about gaming. I started to write a little game where a ship shoots rocks falling from the top of the iphone screen, very simple. left and right UIButtons to move left and right and a UIButton to fire.

But I started with a default NSTimer and this caused slow downs in the game and jitter. So I spent the afternoon reading up on timers and what a lot there is to read.

So testing tonight I dropped everything in a while loop just to start learning. Now that I have it in a while loop it might run pretty fast, which is fine but while in the loop I have no access to my UIButtons? My guess is of course that the while loop won't release control while it is TRUE.

So how do I gain access to the UIButtons while the loop is running?
Code tags don't seem to work? sorry

[Moderator AnotherJake says: I edited them into your post for you. In the post editor, click on the "#" to use the tags.]

       [self runLoop];

    while( game_is_running ) {
        [self shipMove]; // Uses UIButtons to move left and right.
        [self moveShotPosition]; //Moves the shot int eh y direction
        [self moveRockPostion]; //moves the rock in the y direction down
        [self checkCollision]; // checks for collision of rock and ship or shot and rock
        if (!music.playing && lives > 0) { // If music stops, restart it.
            [music play];

RE: Game Timer - AnotherJake - Dec 1, 2012 08:38 PM

It doesn't work because the Cocoa UI operates using events. When you loop on your own like that, it prevents the normal event system from working. If you want to use Cocoa, you have to use a timer, not a while() loop.

RE: Game Timer - SethWillits - Dec 2, 2012 10:44 AM

(Dec 1, 2012 06:55 PM)larswik Wrote:  But I started with a default NSTimer and this caused slow downs in the game and jitter.

The timer itself isn't going to cause anything to slow down and jitter. Describe your approach and what you saw in more detail.

The reason the while loop doesn't let you use any of your buttons is because the main run loop isn't being allowed to run to service any events. You could throw some time into your loop to let the run loop do its things, but I don't recommend going down this road at all.

RE: Game Timer - larswik - Dec 2, 2012 02:02 PM

Thanks guy. This is the first weekend I have tried to dabble in games and it is a whole different world then the programming that I am use to. Doing research I came across a nice little IOS Class called 'CADisplayLink'

This solved all of the problems that I was having. But if I ever decided to port a game over to an android it might be better to set up some kind of a universal run loop.

Searching the web I come across things called "Delta Time" but most all loops, with delta time are in a while loop. Are there any good tutorials that breakdown and explain game timers? I had no idea how important a good game timer is.

RE: Game Timer - AnotherJake - Dec 2, 2012 02:35 PM

Getting your delta time correct isn't as easy to figure out at first as one might think. Many (most?) examples use delta time as the time between frames and then base the animation directly on that, which we often call variable rate timing. It turns out to be a no-no because it is variable (i.e. it changes from frame to frame), although it's the easiest to start with and you get fantastic results if your frame rate is steady. I mistakenly used this for many years. Unfortunately, if the frame rate hiccups, your game is susceptible to all sorts of math failures which are hard, if not impossible, to work around. I have seen some pretty complex examples, including a physics engine, which used delta time like this, and it was easy to break the simulation by simply resizing the window which disturbed the frame rate enough to break collision detection and explode springs, among other bizarre side-effects. This just isn't the right way to do it.

Much better is to use a fixed rate timing step, which is hard to grasp at first because it is a bit of a brain twister to implement, although the code is very simple. Read this. Unfortunately, you'll get some intermittent chop with this because your fixed rate update will never be exact with the actual frame rate, but your integration is far more reliable (integration meaning calculus integration for things like physics and collision detection). It is a necessary trade-off for anything more complex than pong or asteroids. Fortunately, when the game scene is busy, you never notice the intermittent chop. I recommend starting with this, if you can grasp it.

The very best is to use a fixed rate step with the above technique and then further interpolate that to match the frame delta. Read this. I call this sub-tick interpolation, and it's much harder to implement, depending on how complex your game is. It opens up the door to do more complicated things like client side prediction, game time manipulation (i.e. faster/slower playback). I don't recommend this to start with.

RE: Game Timer - SethWillits - Dec 2, 2012 02:46 PM

The first article is also here on iDG.

RE: Game Timer - larswik - Dec 3, 2012 12:27 AM

Thanks for the detailed info and the links. There is so much to know when it comes to game timers. I guess for simplicity sake while I take on game programming I will stick to the CALinkDisplay. I did some research on this today and it seemed very robust for this kind of work.

I am going to read the links you posted. But today, Sunday was a full day on learning about timers.

Thanks a lot!

RE: Game Timer - bmantzey - Dec 4, 2012 03:09 PM

I recommend using mach. Extremely accurate time deltas.

Here's my implementation of its use:


//  CPhysicsTimer.h
//  Created by Brandon Mantzey on 10/22/08.

#import <mach/mach.h>
#import <mach/mach_time.h>
#import <unistd.h>

#define NANO_TO_DOUBLE(X) (X*10e-10)

@interface CPhysicsTimer : NSObject
    unsigned short FPS;
    uint64_t TimeStart;
    uint64_t TimeDelta;
    uint64_t TimeLastFrame;
    uint64_t TimeElapsed;
    uint64_t ElapsedNano;
    uint64_t TimePrev;    
    double systemSpecificRatio;
@property unsigned short FPS;

// This function should also be called to initialize and restart/start the timer.
// In most cases, this function should only ever be called once.
-(void) Reset;

// !!!CALL ONLY ONCE PER FRAME!!!  If you call this more than once per frame, severe timing
// issues will occur.
// This function should be called once, only once, and every frame once only.
-(void) Update;

// Returns the time calculated since the Reset function was called.
-(double) GetTime;
// Returns the time difference between Update calls.
-(double) GetDeltaTime;



//  CPhysicsTimer.m
//  TrainLoaded
//  Created by Brandon Mantzey on 10/22/08.
//  Copyright 2008 Stratogon. All rights reserved.

#import "CPhysicsTimer.h"

@implementation CPhysicsTimer

    self = [super init];
    return self;

// Use to initialize & to start timer.
// All time calculations are calculated from game time at this point.
-(void) Reset
    TimeStart = mach_absolute_time();
    m_nFPS = 0;
// Use to update timer.
-(void) Update
    static int frames = 0;
    static mach_timebase_info_data_t sTimebaseInfo;
    if(TimeLastFrame == 0)
        TimeLastFrame = [self GetTime];
    uint64_t timeNow = [self GetTime];
    if(TimePrev == 0 || TimePrev == timeNow)
        TimePrev = [self GetTime];

    uint64_t diff = timeNow - TimePrev;
//    double testMacro = NANO_TO_DOUBLE(diff);
    if(sTimebaseInfo.denom == 0)
    ElapsedNano = diff * sTimebaseInfo.numer / sTimebaseInfo.denom;    
    // log how many frames since 1 second
    if(NANO_TO_DOUBLE(diff) > 1.0)
        m_nFPS = frames / (int)(NANO_TO_DOUBLE(diff));
        frames = 0;
        TimePrev = timeNow;
    // calculate delta time
    TimeDelta = (timeNow - TimeLastFrame);
    TimeLastFrame = timeNow;
// Returns ( in seconds ) the amount of time from last Reset call.
-(uint64_t) GetTime
    uint64_t time = mach_absolute_time();
    return (time - TimeStart);
-(double) GetTimed
    uint64_t time = mach_absolute_time();
    uint64_t diff = time - TimeStart;
    return NANO_TO_DOUBLE(diff);
// Returns ( in seconds ) the amount of time from last frame.
-(uint64_t) GetDeltaTime
    return TimeDelta;
-(double) GetDeltaTimed
    return NANO_TO_DOUBLE(TimeDelta);

// Returns the current number of FRAMES PER SECOND.
-(unsigned short) GetFPS
    return m_nFPS;

-(void) dealloc
    [super dealloc];


I haven't looked at that in years, so if you see something silly, take it with a grain of salt and don't beat me up too bad. lol Hope this helps.
@Jake - I just read your post, of course after posting mine. Are you saying that use of the class I just posted is a no-no for the reasons you described?

RE: Game Timer - AnotherJake - Dec 4, 2012 03:28 PM

(Dec 4, 2012 03:09 PM)bmantzey Wrote:  @Jake - I just read your post, of course after posting mine. Are you saying that use of the class I just posted is a no-no for the reasons you described?

Yes that is what I am saying -- by using a variable delta time, your integration is susceptible to instability and can break if the frame rate varies too much. Those two articles I linked to offer good insight on this issue.

Also, yes, mach time is the best on Apple platforms. Here's the most common way I've seen it used by several folks around here at iDG, which I, and probably everyone else, got from some Apple code sample:

#include <mach/mach.h>
#include <mach/mach_time.h>
#include <mach/mach_host.h>

double CurrentTimeInSecondsGet(void)
    static uint64_t        timebase = 0;
    uint64_t            time, nanos;
    double                seconds;
    if (timebase == 0)
        // calculate the time base for this platform only on the first time through
        mach_timebase_info_data_t    timebaseInfo;
        timebase = timebaseInfo.numer / timebaseInfo.denom;
    time = mach_absolute_time();
    nanos = time * timebase;
    seconds = (double)nanos * 1.0e-9;
    return seconds;

RE: Game Timer - bmantzey - Dec 4, 2012 03:31 PM

Yucky division.

Quote:timebase = timebaseInfo.numer / timebaseInfo.denom;

Thanks for the reply. I'll take a look at that.

RE: Game Timer - AnotherJake - Dec 4, 2012 03:35 PM

The division is only done once per application launch, since timebase will only == 0 immediately after initialization (note that timebase is a static variable, which means it persists like a global variable would). So it's no problem in terms of performance, if that's what you mean.