Game Loop in Cocoa

robmcq
Unregistered
 
Post: #1
Does anyone know the best way to handle a game loop in Cocoa? A game loop being the loop of code where all of my game objects are updated. I thought using an NSTimer would be the best way but am unsure at this point. I could also use the GLUT but would rather keep this Cocoa oriented as possible. Does anyone have any ideas on this issue?

Thanks
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #2
An NSTimer is probably the best way,
have you timer call an animate function, and then it can optionally call [self setNeedsDisplay:YES] (if its an NSView subclass).

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Member
Posts: 257
Joined: 2004.06
Post: #3
I usually use NSTimer's since that's the easiest way for me to set up a game loop. The other option is deriving from NSApp and overridding some of it's functions.

The following discussion over at CocoaDev.com might be of interest to you as well.

The brains and fingers behind Malarkey Software (plus caretaker of the world's two brattiest felines).
Quote this message in a reply
robmcq
Unregistered
 
Post: #4
Now, the only thing beyond that is that I noticed some animation wierdness when I was using Aqua GUI widgets to control some openGL variables. The animation loop would cycle the colors of a cube I set up in open GL. I also had some sliders to the side of an NSOpenGLView that would control things like rotation around the cube and the light vector. The problem I encountered was that the animation would stop whenever I would hold onto the slider. It's as if the Timer gets preempted whenever there is a GUI event taking place (like a slider move). Is there any way to force the Timer to update the animation while the user is holding on to the slider?

Rob
Quote this message in a reply
Moderator
Posts: 508
Joined: 2002.09
Post: #5
For the few games I've written, I used an NSTimer. Set it's repeat time to something like 0.03.

The screensavers in OS X use an NSTimer.

While you could make your own runloop, I don't recommend it. Don't make it hard on yourself Smile

"When you dream, there are no rules..."
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #6
Code:
[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSEventTrackingRunLoopMode];
[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSModalPanelRunLoopMode];

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Moderator
Posts: 508
Joined: 2002.09
Post: #7
robmcq Wrote:Is there any way to force the Timer to update the animation while the user is holding on to the slider?

Yes and no, you can do updates while a user is moving the slider without a timer. Just give the slider an action like this:
Code:
[mySlider setAction:@selector(updateStuff:)];

then write the method

Code:
- (void)updateStuff:(id)sender {
  //update what you want
}

"When you dream, there are no rules..."
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #8
That would work too, Smile
Make sure you use smileys in the code though Rasp

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
robmcq
Unregistered
 
Post: #9
Cool. Thanks so much guys. I can't believe how quickly I got all of my questions answered. You have a great community here.

Rob
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #10
Using NSTimer is the easiest and quickest way to do it, but if you're doing anything complicated, it can cause quite a few problems. For example, if it's going to take a long time to draw the graphics or process some information on slower machines, your game can ground to a halt since it's then also waiting even longer to update the next screen after it's been working to update the current one.

If you're doing something that could possibly slow down to that point either this project or another project, you can do a while (true) loop in which you do the following:
Grab the next NSEvent using [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:true]. See if that event exists (checking if it's not nil), and if it does, process that event like you normally would based on its type.

After that, you will need to check the framerate every once in a while. To do this, set a certain number of frames you want to check (set a counter etc.), and have a struct timeval object (I call mine time). Then have 4 longs: current seconds, current microseconds, last seconds, and last microseconds. At first, call gettimeofday(&time, NULL); to get the time, then store time.tv_sec and time.tv_usec in the current seconds and microseconds, respectively. Then, every time it is to check the framerate, set the current time values to the old time values, then call getttimeofday again and put the time.tv_sec and time.tv_usec in the current seconds and microseconds again. Take the number of frames between each time you are sampling the framerate and divide that by the (current seconds - old seconds) + (current microseconds - old microseconds)*1e-6, and that gives you the framerate. Take 1 over the framerate, and multiply all your animations by that number, and the animations will stay constant, no matter the framerate. (this is assuming all your animations use seconds as their units of time, otherwise you might have to multiply by the framerate you're assuming, such as 30)

This definitely is more complicated, but it's also a lot more versatile. It's definitely a method worth looking.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  iPhone game loop agreendev 2 4,300 Jul 27, 2010 11:32 AM
Last Post: AnotherJake
  Trouble with the canonical game loop TomorrowPlusX 27 11,036 Aug 12, 2009 04:22 AM
Last Post: TomorrowPlusX
  Proper game update loop in Cocoa? LoneIgadzra 13 6,708 May 30, 2008 05:49 AM
Last Post: ThemsAllTook
  Yield in a Cocoa while loop Fenris 7 4,885 Dec 28, 2007 02:00 AM
Last Post: Fenris
  Controlling Game Loop Nick 2 3,260 Jul 21, 2007 07:12 PM
Last Post: Nick