我正在使用OpenGL ES为iPhone创建2D游戏。我使用NSTimer以0.002(60 fps)的间隔调用我的游戏循环,重复设置为“NO”(我在推荐的函数内再次运行NSTimer):
-(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上太慢了。
我知道必须有一些方法可以在两台设备上进行连续播放。 Doodle Jump似乎在两部手机上都能以平滑的方式运行。
答案 0 :(得分: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秒,则会不必要地将帧速率降低一半。
答案 1 :(得分:2)
实际上有两种帧速率:
我认为您正在寻找与显示帧速率分离的恒定逻辑帧速率,该速率可根据手机硬件的能力进行调整。与您的游戏循环相比,每个逻辑帧必须完成一个显示帧。
查看deWiTTERS Game Loop中描述的“使用最大FPS的恒定游戏速度”算法游戏逻辑将在3G和2GS上以相同的速度运行,但显示帧速率将调整为较慢2G CPU。虽然上面的文章没有介绍,但您也可以限制显示帧率以节省电池电量。