I'm new to iPhone dev, but trying to build a 2D game. I was following a book, but the game loop it created basically said:
function gameLoop
update()
render()
sleep(1/30th second)
gameLoop
The reasoning was that this would run at 30fps. However, this seemed a little mental, because if my frame took 1/30th second, then it would run at 15fps (since it'll spend as much time sleeping as updating).
So, I did some digging and found the CADisplayLink class which would sync calls to my gameLoop function to the refresh rate (or a fraction of it). I can't find many samples of it, so I'm posting here for a code review :-) It seems to work as expected, and it includes passing the elapsed (frame) time into the Update method so my logic can be framerate-independant (however I can't actually find in the docs what CADisplayLink would do if my frame took more than its allowed time to run - I'm hoping it just does its best to catch up, and doesn't crash!).
//
// GameAppDelegate.m
//
// Created by Danny Tuppeny on 10/03/2010.
// Copyright Danny Tuppeny 2010. All rights reserved.
//
#import "GameAppDelegate.h"
#import "GameViewController.h"
#import "GameStates/gsSplash.h"
@implementation GameAppDelegate
@synthesize window;
@synthesize viewController;
- (void) applicationDidFinishLaunching:(UIApplication *)application
{
// Create an instance of the first GameState (Splash Screen)
[self doStateChange:[gsSplash class]];
// Set up the game loop
displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(gameLoop)];
[displayLink setFrameInterval:2];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void) gameLoop
{
// Calculate how long has passed since the previous frame
CFTimeInterval currentFrameTime = [displayLink timestamp];
CFTimeInterval elapsed = 0;
// For the first frame, we want to pass 0 (since we haven't elapsed any time), so only
// calculate this in the case where we're not the first frame
if (lastFrameTime != 0)
{
elapsed = currentFrameTime - lastFrameTime;
}
// Keep track of this frames time (so we can calculate this next time)
lastFrameTime = currentFrameTime;
NSLog([NSString stringWithFormat:@"%f", elapsed]);
// Call update, passing the elapsed time in
[((GameState*)viewController.view) Update:elapsed];
}
- (void) doStateChange:(Class)state
{
// Remove the previous GameState
if (viewController.view != nil)
{
[viewController.view removeFromSuperview];
[viewController.view release];
}
// Create the new GameState
viewController.view = [[state alloc] initWithFrame:CGRectMake(0, 0, IPHONE_WIDTH, IPHONE_HEIGHT) andManager:self];
// Now set as visible
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
- (void) dealloc
{
[viewController release];
[window release];
[super dealloc];
}
@end
Any feedback would be appreciated :-)
PS. Bonus points if you can tell me why all the books use "viewController.view" but for everything else seem to use "[object name]" format. Why not [viewController view]?
Having linked up and created an account, GameLoop will automatically detect the games installed on your iPhone or iPad and add them to your gaming library. If you play games on other platforms, you can also add most of those to your library as well by linking Xbox Live, Playstation Network, and Steam accounts.
The game loop is the overall flow control for the entire game program. It's a loop because the game keeps doing a series of actions over and over again until the user quits. Each iteration of the game loop is known as a frame.
The game loop itself is a controlled infinite loop that makes your game keep running; it's the place where all your little pieces will be updated and drawn on the screen.
The three main processes that occur in the game loop are input, update, and render.
You have Cocos2D listed as a tag in your question but you're not actually using any Cocos2D code. Have you considered doing a Cocos2D implementation for your games? It will save you some unneeded hassle.
As for your syntax question [myObject view]
is used for calling methods on myObject
while myObject.view
is used for setting/getting instance variables exposed as properties. I don't recall if you can retrieve instance variables using [myObject view]
as well but if that works then I guess the only difference between the two is the syntax and you could use both methods to retrieve instance variables.
Hope some of that rambling is useful to you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With