저는 dev에 익숙하지만 2D 게임을 만들려고합니다. 나는 책을 읽고 있었지만 게임 루프는 기본적으로 다음과 같이 말했습니다.아이폰 게임을위한 게임 루프를 만드는 좋은 방법일까요?
function gameLoop
update()
render()
sleep(1/30th second)
gameLoop
이것은 30fps에서 실행되는 것이 었습니다. 그러나 이것은 약간 정신적 인 것처럼 보였습니다. 제 프레임이 1/30 초가 걸리면 15fps로 실행될 것이기 때문입니다 (업데이트하는 데 많은 시간을 할애하기 때문에).
그래서 파고 들었고 내 gameLoop 함수에 대한 호출을 새로 고침 빈도 (또는 그 일부)와 동기화하는 CADisplayLink 클래스를 찾았습니다. 많은 샘플을 찾을 수 없으므로 여기에 코드 검토를 위해 게시하고 있습니다. :-) 예상대로 작동하는 것 같습니다. 그리고 경과 된 (프레임) 시간을 Update 메서드에 전달하여 내 논리가 프레임 속도가 될 수 있도록합니다. -independant (단, 프레임이 허용 된 시간보다 오래 걸리면 CADisplayLink가 수행 할 작업을 실제로 문서에서 찾을 수 없습니다. 따라 잡기 위해 최선을 다하고 충돌을 일으키지 않기를 바랍니다!).
//
// 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
상관 피드백
는PS :-) 이해 될 것이다. 보너스 포인트는 모든 책들이 "viewController.view"를 사용하는 이유를 말해 줄 수 있지만 다른 모든 것들은 "[object name]"형식을 사용하는 것처럼 보입니다. 왜 [viewController보기]가 아닌가?
이 코드는 작동하지만 다소 더듬어 보입니다. 프레임 속도는 낮지 만 부드럽게 보이지 않습니다. 내 게임 루프에서 프레임 속도를 동기화 한 다음 * 업데이트 *하기 때문일 수 있습니다. 렌더링은 drawRect에서 수행됩니다. 내 코드가 직접 호출해야한다고 생각합니다. (그리고 어쩌면 업데이트는 그리기 후에 수행해야합니다.) CADisplayLink의 좋은 예를 찾을 수 없습니다. –
필자의 스프라이트의 움직임을 초당 30 픽셀로 바 꾸었습니다. 매우 가끔씩 프레임이 떨어지는 것처럼 보였습니다. 그래서 나는 그것이 내가 정했을 때의 스피드에 불과하다고 생각합니다. 프레임 당 픽셀보다 약간 더 움직이면 결국 한 프레임에서 두 픽셀을 뛰어 넘어 고르지 않게 보일 것입니다. 나는 이것이 어쩔 수 없다고 생각한다. –