2010-03-11 80 views
6

我是iPhone新手,但尝试构建2D游戏。我在下面的一本书,但它基本上创建游戏圈说:这是一个为iPhone游戏做游戏循环的好方法吗?

function gameLoop 
    update() 
    render() 
    sleep(1/30th second) 
    gameLoop 

的理由是,这将在30fps的运行。然而,这看起来有点心理上的问题,因为如果我的帧花费了1/30秒,那么它将以15fps运行(因为它将花费与更新一样多的时间)。

因此,我做了一些挖掘并找到了将同步调用我的gameLoop函数到刷新率(或其一部分)的CADisplayLink类。我找不到它的很多样本,所以我在这里发布代码审查:-)它似乎按预期工作,它包括将已用(帧)时间传递到Update方法,所以我的逻辑可以是帧率(但是我实际上无法在文档中找到如果我的框架花费的时间超过了允许的时间,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视图]?

+0

虽然这段代码有效,但它似乎有点结结巴巴。帧率不低,看起来不太平坦。我认为这可能是因为我正在同步帧速率,然后在我的游戏循环中更新*。渲染是在drawRect中完成的。 我想我的代码应该直接绘制在所谓的方法中(也许更新应该在绘制之后完成),但是我找不到任何CADisplayLink的好例子。 – 2010-03-12 07:06:23

+0

我改变了我的精灵的运动速度为每秒30像素,并且它看起来非常平滑(偶尔会丢失帧),所以我认为这只是我设定的速度 - 例如。每帧移动略多于一个像素,这意味着它最终会在一帧中跳跃两个像素,使其看起来不均匀。我想这是不可避免的。 – 2010-03-12 18:07:21

回答

2

你有Cocos2D在你的问题中列为标签,但你实际上没有使用任何Cocos2D代码。你有没有考虑过为你的游戏做一个Cocos2D实现?它会为您节省一些不必要的麻烦。

至于你的语法问题[myObject view]用于调用方法myObjectmyObject.view用于设置/获取作为属性公开的实例变量。我不记得您是否可以使用[myObject view]来检索实例变量,但如果这样做有效,那么我猜两者之间的唯一区别就是语法,您可以使用这两种方法来检索实例变量。

希望一些散漫对你有用。

+0

哎呀!告诉你我不知道我在做什么!现在删除标签。 在语法上做了一些阅读,现在理解它更好。似乎[myclass属性]和myclass.property可以做不同的事情。首先是一个属性(它可以执行代码,尽管在大多数情况下我怀疑它只是返回变量),而点直接访问变量(并且不具有自定义代码)。 似乎暴露私人领域和C#中的属性之间的差异,只是在这里他们可以看起来都有相同的名字! – 2010-03-11 20:46:15

+0

其实,现在我很困惑,因为我得到的错误: 访问未知'rect'getter方法 这使我认为使用点与使用get/set方法完全相同! – 2010-03-11 21:22:50

+0

如果使用圆点,则需要将要检索的实例变量定义为属性,然后将其合成。查找“@property”和“@synthesize”调用的语法。 getter/setter方法会为您隐式创建,但只能在使用@synthesize之后。这就是为什么你会得到一个未知的“矩形”吸气方法。 – 2010-03-11 21:40:16

-2

从Apple的许多GL例子中,我认为你应该使用计时器。

animationTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0/60.0) 
                target:self 
               selector:@selector(updateAndRender) 
               userInfo:nil 
               repeats:TRUE]; 
+0

我相信CADisplayLink是作为一种更好的方式添加的,但是因为它只是最近才被添加,似乎很少有文档/样本:( – 2010-04-13 19:41:24