2010-07-10 82 views
4

我正在为OpenGL ES创建一个2D游戏。我打电话设置为“NO”重复使用的NSTimer在0.002(60 fps)的间隔我的游戏循环(从函数内再次我运行的NSTimer建议):如何在新旧iPhone上获得一致的速度?


-(void)gameLoop:(id)sender { 
    double currTime=(double)CACurrentMediaTime(); 
    m_FPS_framesThisSecond++; 
    float timeThisSecond=currTime-m_FPS_lastSecondStart; 
    if (timeThisSecond>1.0f) { 
     m_FPS=m_FPS_framesThisSecond; 
     m_FPS_framesThisSecond=0; 
     m_FPS_lastSecondStart=currTime; 
    } 

    [game update]; 
    [game render]; 

     //Continue the loop 
    [NSTimer scheduledTimerWithTimeInterval:0.002 target:self selector:@selector(gameLoop:) userInfo:nil repeats:NO]; 
} 

这将运行顺利地在我的3GS上,但是当我在2G上测试时,游戏运行速度慢得多,有时偶尔会出现空白帧。当我将间隔降低到0.033(30 fps)时。 3G上的速度太慢了。

我知道必须通过某种方式在两台设备上获得持续播放。涂鸦跳跃似乎运行平稳,并在两个手机相同的帧率。

+0

那么,还有什么时候离开硬件架构的肮脏的思想流派。自iOS4起,苹果公司(官方)放弃了对iPhone 2G(原始iPhone)的支持。也许,也许你可能会考虑做同样的事情,因为任何未来的OpenGL ES更新将只针对3G以上(看到苹果现在如何发布OpenGL ES2设备功能的系统 - 尽管3G不支持ES2) 。不要告诉你,你有一个不好的问题,(事实上,我为它+1)...只是说有时你需要考虑你的应用程序的未来。 – Jann 2010-07-10 22:33:22

+0

我肯定会忽视3GS之前的设备(我不知道有2G的任何人)。但同时,我想我应该将游戏速度与帧率分开。无论如何,OpenGL ES2将是我的下一个努力! – Scott 2010-07-11 01:49:45

回答

2

的基本问题是:

你的游戏需要,而不是由它多少次渲染来更新的基础上,因为它渲染的最后一次经过的时间量。假设您正在基于某个速度计算精灵的位置。新位置应根据渲染之间的时间进行计算,而不是假设自上次渲染以来经过0.002秒。这被称为FPS独立动画。

所以,这里是一个简单的例子:

// FPS dependent animation 
int x = sprite.x + sprite.velocity.x 

正确的方式做,这是使用时间从去年渲染,而更新比例。以下代码假定0.002是时基。

// FPS independent animation 
int x = sprite.x + sprite.velocity.x * time_since_last_render/0.002 

在其中渲染需要两倍长的设备,下次更新将尽量两次移动的对象,因此它在同一个地方,因为它会更快的设备上结束。

一个侧面的问题,你不应该总是在将来的0.002秒内渲染下一帧。您应该看到当前帧需要渲染多长时间,从0.002中减去该值并使用它计划下一个渲染。当然,这个数字的最小值为零,所以在慢速设备上你不会开始调度到过去。例如,如果您的渲染函数需要完全0.002秒的渲染时间,这会使您的帧速率降低一半。

+0

谢谢!我会通过简单地获得当前时间减去前一帧的时间之间的差异来计算time_since_last_render吗? – Scott 2010-07-11 01:44:21

2

实际上有两种类型的帧速率的:

  • 显示帧率:在该屏幕重绘
  • 逻辑帧速率:在该游戏逻辑被更新率(游戏速度)

我认为你正在寻找一个恒定的逻辑帧速率,从显示帧速率去耦,以适应手机硬件的上限能力。比较你的游戏循环必须为每个逻辑帧完成一个显示帧。

查看deWiTTERS Game Loop中描述的“Constant Game Speed with Maximum FPS”算法游戏逻辑在3G和2GS上都会以相同的速度运行,但显示帧速率将调整为较慢的2G CPU。虽然以上文章未涉及,但您也可以限制显示帧速率以节省电池电量。