Good Game Loop with Physics Units
Hi all,
I'm trying to get back into programming games. I've isolated OpenGL as the source of my woes, and I've gone back to what I started with - Quartz! It's so user-friendly, and so simple to prototype stuff in Obj-C and Cocoa. My plan is to keep the model and controller abstract from the drawcode so that I can someday replace it with OpenGL code. That way I can still have fun while keeping the end-goal of a fast-drawing game alive...
Anyway, on to the beef. I think I've written a good animation loop that calls a physics method based on physics units. It should maintain a solid fps and smooth gameplay, methinks. Comments, please? It's very well commented - should be easy reading:
I'm trying to get back into programming games. I've isolated OpenGL as the source of my woes, and I've gone back to what I started with - Quartz! It's so user-friendly, and so simple to prototype stuff in Obj-C and Cocoa. My plan is to keep the model and controller abstract from the drawcode so that I can someday replace it with OpenGL code. That way I can still have fun while keeping the end-goal of a fast-drawing game alive...
Anyway, on to the beef. I think I've written a good animation loop that calls a physics method based on physics units. It should maintain a solid fps and smooth gameplay, methinks. Comments, please? It's very well commented - should be easy reading:
PHP Code:
- (void)animate:(id)timer
{
/* Store Current time to calculate delta time */
NSDate *timeOfAnimation = [NSDate date];
/* Testing for printing of FPS, printing, etc */
if ([timeOfAnimation timeIntervalSinceDate:oldFPSTime] > 1.0)
{
NSLog(@"**** FPS: %d ****", frameCounter);
[oldFPSTime release];
oldFPSTime = [timeOfAnimation retain];
frameCounter = 0;
}
/* Calculate amount of "time" that needs to be animated, persae */
currentInterval = ([timeOfAnimation timeIntervalSinceDate:previousAnimationTime]
+ physicsLeftover);
[previousAnimationTime release];
previousAnimationTime = [timeOfAnimation retain];
/* Check that no huge amount of time has passed since the last physics event
was run. This eliminates jerky movement when client's computer lags */
if (currentInterval > (MAX_PHYSICS_UNITS * physicsInterval))
{
currentInterval = (MAX_PHYSICS_UNITS * physicsInterval);
}
/* If the current delta time is long enough to warrant completing a physics unit,
do so until the current interval is so reduced that it no longer is large enough
to warrant an entire unit. Leave the leftover for the next time around the
animation loop. Increment the fps counter and draw. */
if (currentInterval >= physicsInterval)
{
while (currentInterval >= physicsInterval)
{
currentInterval -= physicsInterval;
[self runPhysics];
}
[view setNeedsDisplay:YES];
frameCounter++;
}
physicsLeftover = currentInterval;
}
On Keith's advisement (fancy that!) I rewrote a bit of it to get rid of the NSDate objects. No more allocation, deallocation, and a lot fewer square brackets. Hoorah! Code follows:
PHP Code:
- (void)animate:(id)timer
{
/* Store Current time to calculate delta time */
NSTimeInterval timeOfAnimation = [NSDate timeIntervalSinceReferenceDate];
/* Testing for printing of FPS, printing, etc */
if ((timeOfAnimation - oldFPSTime) > 1.0)
{
NSLog(@"**** FPS: %d ****", frameCounter);
oldFPSTime = timeOfAnimation;
frameCounter = 0;
}
/* Calculate amount of "time" that needs to be animated, persae */
currentInterval = ((timeOfAnimation - previousAnimationTime) + physicsLeftover);
previousAnimationTime = timeOfAnimation;
/* Check that no huge amount of time has passed since the last physics event
was run. This eliminates jerky movement when client's computer lags */
if (currentInterval > (MAX_PHYSICS_UNITS * physicsInterval))
{
currentInterval = (MAX_PHYSICS_UNITS * physicsInterval);
}
/* If the current delta time is long enough to warrant completing a physics unit,
do so until the current interval is so reduced that it no longer is large enough
to warrant an entire unit. Leave the leftover for the next time around the
animation loop. Increment the fps counter and draw. */
if (currentInterval >= physicsInterval)
{
while (currentInterval >= physicsInterval)
{
currentInterval -= physicsInterval;
[self runPhysics];
}
[view setNeedsDisplay:YES];
frameCounter++;
}
physicsLeftover = currentInterval;
}
Another interesting way was Keith's multithreaded example, where he runs the physics and graphics independently so one wont slow down the other.
Sir, e^iπ + 1 = 0, hence God exists; reply!
I found that this is one of those fundamental code snippets that either:
a) is out there, but completely complex due to someone trying to squish it down as much as possible
b) is out there, but completely without comments
c) is out there, but not in Objective-C and Cocoa
Might be handy to keep snippets like this in a database on the site...
a) is out there, but completely complex due to someone trying to squish it down as much as possible
b) is out there, but completely without comments
c) is out there, but not in Objective-C and Cocoa
Might be handy to keep snippets like this in a database on the site...
blobbo Wrote:Might be handy to keep snippets like this in a database on the site...Indeed. It'd be very handy.
you might use CFAbsoluteTimeGetCurrent() instead of NSDate. That returns a much more accurate time (the number of seconds the system has been running).
Heres a different type of game loop I created for the current game im working on:
The aim is to refresh the screen as fast as possible, for strobing effects etc. but to animate the game at a fixed fps, this will also animate several frames if it needs to as well. So a player cant cheat by running somthing in the background to slow the game down.
I think one other possible could be emulation because I hate how emulators slow down so much somtimes.
Code:
#define FRAMETIME 1/60
while(1) {
while(t2-t1 > FRAMETIME) {
t1 += FRAMETIME;
tick();
}
t2 = get_time();
draw();
}
}The aim is to refresh the screen as fast as possible, for strobing effects etc. but to animate the game at a fixed fps, this will also animate several frames if it needs to as well. So a player cant cheat by running somthing in the background to slow the game down.
I think one other possible could be emulation because I hate how emulators slow down so much somtimes.
Sir, e^iπ + 1 = 0, hence God exists; reply!
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| iPhone game loop | agreendev | 2 | 3,709 |
Jul 27, 2010 11:32 AM Last Post: AnotherJake |
|
| Physics in a Game World | mikey | 5 | 3,857 |
Sep 20, 2009 08:58 AM Last Post: mikey |
|
| Child Units | grazhoper | 1 | 2,332 |
Sep 2, 2009 12:25 AM Last Post: AnotherJake |
|
| Trouble with the canonical game loop | TomorrowPlusX | 27 | 9,072 |
Aug 12, 2009 04:22 AM Last Post: TomorrowPlusX |
|
| Proper game update loop in Cocoa? | LoneIgadzra | 13 | 5,712 |
May 30, 2008 05:49 AM Last Post: ThemsAllTook |
|

