如何在不使用NSTimer的情况下在iPhone上进行游戏循环

时间:2009-08-29 11:43:52

标签: iphone opengl-es loops

为了将我的游戏干净地移植到iPhone上,我正试图制作一个不使用NSTimer的游戏循环。

我在一些示例代码中注意到,如果使用NSTimer,您可以在开头设置它,例如

    self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES];

其中drawView看起来像:


- (void)drawView 
{
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    mFooModel->render();
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

当使用这种技术时,mFooModel渲染得很好,但我反而希望制作我自己的游戏循环,调用drawView而不是让NSTimer调用drawView 60次。我想要像:


while(gGameState != kShutDown)
{
    [self drawView]
}

不幸的是,当我这样做时,我得到的只是黑屏。为什么会这样?无论如何我可以实现我在这里描述的内容吗?

我想避免NSTimer的原因是因为我想在游戏循环中进行物理和AI更新。我使用自己的时钟/计时器来跟踪已经过的时间,以便我可以准确地完成这项工作。渲染尽可能快。我尝试使用this article

中描述的一些技术

这有点是一个冲动的问题(你在整天编码之后做的那个,卡住了,希望早上答案就在那里)

干杯。

5 个答案:

答案 0 :(得分:21)

iPhoneOS 3.1的另一个选择是使用新的CADisplayLink api。这将在需要更新屏幕内容时调用您指定的选择器。

displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(renderAndUpdate)];
[displayLink setFrameInterval:2];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

如果您需要更多示例代码,XCode中的新OpenGL项目模板也会使用CADisplayLink。

答案 1 :(得分:2)

如果您不想使用NSTimer,可以尝试手动运行NSRunLoop

static BOOL shouldContinueGameLoop;
static void RunGameLoop() {
    NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
    NSDate *destDate = [[NSDate alloc] init];
    do {
        // Create an autorelease pool
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        // Run the runloop to process OS events
        [currentRunLoop runUntilDate:destDate];
        // Your logic/draw code goes here
        // Drain the pool
        [pool drain];
        // Calculate the new date
        NSDate *newDate = [[NSDate alloc] initWithTimeInterval:1.0f/45 sinceDate:destDate];
        [destDate release];
        destDate = newDate;
    } while(shouldContinueGameLoop);
    [destDate release];
}

答案 2 :(得分:2)

虽然使用CADisplayLink是基于3.1的游戏的一个非常好的选择,但是 任何使用“计时器”的东西都是一个非常糟糕的主意。

最好的方法是将旧的“三重缓冲”解耦为GPU工作。

Fabien在他的Doom Iphone评论中有一个非常好的解释:
http://fabiensanglard.net/doomIphone/

答案 3 :(得分:2)

小心使用self作为displayLinkWithTarget的目标,手册说“新构建的显示链接保留了目标”。 马丁

答案 4 :(得分:0)

关于Fabien的CADisplayLink和Doom for iPhone文章,我给Fabien发了电子邮件,我认为最好的选择是主观的。性能方面的DisplayLink和三重缓冲应该相同,但DisplayLink仅适用于> OS 3.1。所以这应该是你的决定因素。