4

iPhone用のOpenGL ESで2Dゲームを作成中です。繰り返しを「NO」に設定して、0.002 (60 fps) の間隔で NSTimer を使用してゲーム ループを呼び出しています (推奨どおりに関数内から 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 は、両方のスマートフォンでスムーズに同じフレームレートで実行されているようです。

4

2 に答える 2

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

レンダリングに 2 倍の時間がかかるデバイスでは、次の更新でオブジェクトが 2 倍移動するため、より高速なデバイスと同じ場所に移動します。

副次的な問題として、常に次のフレームを 0.002 秒先にレンダリングする必要はありません。現在のフレームのレンダリングにかかった時間を確認し、それを 0.002 から引き、それを使用して次のレンダリングをスケジュールします。当然、この数値の最小値はゼロになるため、遅いデバイスでは過去にスケジュールを開始しません。たとえば、レンダリング関数のレンダリングにちょうど 0.002 秒かかる場合、フレーム レートが不必要に半分に低下します。

于 2010-07-10T16:10:24.557 に答える
2

実際には、フレーム レートには次の 2 種類があります。

  • 表示フレームレート:画面が再描画されるレート
  • 論理フレーム レート:ゲーム ロジックが更新されるレート (ゲーム速度)

電話ハードウェアの機能に合わせて表示フレーム レートから切り離された一定の論理フレーム レートを探していると思います。論理フレームごとに 1 つの表示フレームを完了する必要があるゲーム ループと比較してください。

deWiTTERS Game Loopで説明されている「Constant Game Speed with Maximum FPS」アルゴリズムを確認してください。ゲーム ロジックは 3G と 2GS の両方で同じ速度で実行されているように見えますが、表示フレーム レートは低速の 2G CPU に合わせて調整されます。上記の記事では取り上げていませんが、ディスプレイのフレーム レートを制限してバッテリーを節約することもできます。

于 2010-07-10T16:15:02.110 に答える