除了使用 NSTimer 之外,在 iPhone 上创建游戏循环的更好方法是什么?

What is a better way to create a game loop on the iPhone other than using NSTimer?

提问人:Ashley Davis 提问时间:9/19/2008 最后编辑:The Archetypal PaulAshley Davis 更新时间:11/29/2010 访问量:14702

问:

我正在 iPhone 上编写游戏。我目前正在使用 NSTimer 来触发我的游戏更新/渲染。这样做的问题是(在分析之后)我似乎在更新/渲染之间浪费了很多时间,这似乎主要与我插入 NSTimer 的时间间隔有关。

所以我的问题是使用 NSTimer 的最佳替代方案是什么?

请为每个答案一个备选方案。

iPhone Objective-C

评论

0赞 Mark Bessey 9/19/2008
你看过 iPhone 开发者的例子吗?我认为有一些例子(例如Touch Fighter或CrashLanding)可能会很有启发性。
0赞 Ashley Davis 9/19/2008
我在互联网上看了很多例子并研究了替代方案。所以我已经知道有一些替代方案。我真正追求的是其他人认为最好的选择是什么?我正在从事一个非常短的项目,因此在调查上节省的任何时间都将是一个很大的帮助。

答:

4赞 Galghamon 10/22/2008 #1

我不是特别了解iPhone,但我可能仍然能够提供帮助: 与其简单地在循环结束时插入固定延迟,不如使用以下方法:

  • 确定一个您满意的刷新间隔,该刷新间隔大于通过主循环的单次刷新间隔。
  • 在循环开始时,获取可用分辨率的当前时间戳并存储它。
  • 在循环结束时,获取另一个时间戳,并确定自上次时间戳以来经过的时间(在循环之前初始化)。
  • 睡眠/延迟,表示您的理想帧时间与帧中已经经过的时间之间的差值。
  • 在下一帧,您甚至可以尝试通过与上一个循环开始时的时间戳进行比较来补偿睡眠间隔中的不准确之处。存储差值,并在此循环结束时从睡眠间隔中加/减它(睡眠/延迟可能太长或太短)。

你可能想要一个警报机制,让你知道你的时间是否太紧(即,如果你在所有补偿后的睡眠时间小于 0,这意味着你花费的时间超过了你的帧速率允许的时间)。效果将是你的游戏速度变慢。对于额外的点,如果检测到这种情况,您可能需要简化渲染一段时间,直到再次有足够的备用容量。

18赞 zoul 10/22/2008 #2

你可以用线程获得更好的性能,试试这样的东西:

- (void) gameLoop
{
    while (running)
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        [self renderFrame];
        [pool release];
    }
}

- (void) startLoop
{
    running = YES;
#ifdef THREADED_ANIMATION
    [NSThread detachNewThreadSelector:@selector(gameLoop)
    toTarget:self withObject:nil];
#else
    timer = [NSTimer scheduledTimerWithTimeInterval:1.0f/60
    target:self selector:@selector(renderFrame) userInfo:nil repeats:YES];
#endif
}

- (void) stopLoop
{
    [timer invalidate];
    running = NO;
}

在方法中,您准备帧缓冲区,绘制帧并在屏幕上显示帧缓冲区。(附言有一篇关于各种类型的游戏循环及其优缺点的好文章renderFrame

评论

0赞 tc. 11/29/2010
-1.UIView 不是线程安全的,因此您需要执行一大堆其他操作才能使其正常工作。UIGraphics 自 4.0 以来仅是线程安全的。
1赞 zoul 11/29/2010
@tc:你说得对,但海报上没有提到他使用的图形层。由于我们谈论的是游戏,因此我假设 OpenGL,这样的循环可以正常工作。
0赞 Jonas Byström 12/5/2012
@zoul:替代方案是否也适用于早期版本?我以为我没有在某个地方读到它。THREADED_ANIMATION
0赞 zoul 12/5/2012
你是说早期的iOS版本?是的,我在 2.x 或 3.x 左右的游戏中使用了类似的代码。
0赞 scriba 11/29/2010 #3

使用 CADisplayLink,您可以在 XCODE 中提供的 OpenGL ES 模板项目中找到方法(从此模板创建一个项目并查看 EAGLView 类,此示例基于 open GL,但您只能将 CADisplayLink 用于其他类型的游戏