2011-09-09 11 views
10

ゲームループで一定速度を設定するという概念を理解しようとしています。頭が痛い。私はdeWiTTERS pageを読んでいますが、私はなぜ/どのように...私がそれを得るときに見ることができません...それはスリップします。時間ベースのループとフレームベースのループ

while(true) 
{ 
     player->update() ; 
     player->draw() ; 
} 

これは、プロセッサの速さに応じてできるだけ早く実行されます...私はそれを取得します。

すべてのコンピュータで同じ速度で動作させるには、ロジックが得られません。私が60fpsで走ろうとしているのであれば、16msごとにオブジェクトがフレームごと動くことを意味します、そうですか?私が得ないのは、update()またはdraw()がどうして遅すぎるかということです。

deWiTTERS例(私は60を使用):

const int FRAMES_PER_SECOND = 60; 
const int SKIP_TICKS = 1000/FRAMES_PER_SECOND; 

DWORD next_game_tick = GetTickCount(); 
// GetTickCount() returns the current number of milliseconds 
// that have elapsed since the system was started 

int sleep_time = 0; 

bool game_is_running = true; 

while(game_is_running) { 
    update_game(); 
    display_game(); 

    next_game_tick += SKIP_TICKS; 
    sleep_time = next_game_tick - GetTickCount(); 
    if(sleep_time >= 0) { 
     Sleep(sleep_time); 
    } 
    else { 
     // Shit, we are running behind! 
    } 
} 

彼はループが始まる前に、現在の時刻を取得し、なぜ私は理解していません。そして彼がSKIP_TICKSをインクリメントするとき、私は彼が次の16msの間隔に増加することを理解します。しかし、私は同様にこの部分を理解していない:

sleep_time = nextgametick - GetTickCount() 

Sleep(sleep_time)は何を意味するのでしょうか?プロセッサはループを離れて別のことをしますか?実行中の60fpsはどのように達成されますか?

+0

http://msdn.microsoft.com/en-us/library/ms686298%28v=vs.85%29.aspx – Lucian

+0

http://msdn.microsoft.com/en-us/library/ms724408%28v = vs.85%29.aspx – Lucian

+0

ありがとうございます.GetTickCount()は10〜16msの間に戻るか、そうですか?しかし代わりに、私は結果として324505599のようなものを見ています... "GetTickCount関数の解像度は、通常10ミリ秒から16ミリ秒の範囲内にあるシステムタイマの解像度に制限されています。" –

答えて

5

60FPでの単一フレーム間隔より短い時間でupdate_game()およびdisplay_game()関数が完了すると、ループはその間隔が稼働するまで次のフレームが確実に処理されないようにします。スレッド)を余分なフレーム時間から解放する。フレームレートが60FPSに制限されていることを確認しようとしているようです。

プロセッサはループを離れませんが、ループが実行されているスレッドは、スリープ時間が経過するまでブロックされます(コードの実行が継続できなくなります)。その後、次のフレームに進みます。マルチスレッドのゲームエンジンでは、このようにメインゲームループのスレッドをスリープさせると、設定に応じて物理、AI、オーディオミキシングなどを管理する他のスレッドでコードを実行するCPU時間が与えられます。

なぜループが始まる前にGetTickCount()が呼び出されますか? コード内のコメントから、GetTickCount()はシステム起動後のミリ秒数を返します。

だから、あなたはあなたのプログラム、 を開始し、我々はがループに入る前に)(のGetTickCountを呼び出していないことを言わせたときに、システムが30秒(30,000ms)のために実行されていることを言うことができます ではなく、初期化0

にnext_game_tick私たちは、アップデートを行うと通話(例として、彼らは6msのを取る)、その後を描く:ゲームループをSLEEP_TIMEが正のときに我々は(賢明)だけ寝るので

next_game_tick += SKIP_TICKS; // next_game_tick is now 16 
sleep_time = next_game_tick - GetTickCount(); 

// GetTickCount() returns 30000! 
// So sleep_time is now 16 - 30000 = -29984 !!! 

を、 速い可能な(潜在的に60FPSより速い) あなたが望むものではありません。

+0

しかし、両方の機能が16ms未満で完了すると、if(sleepTime> 0)が真ではない可能性があるため、スリープ状態にならない可能性があります。 –

+1

私はあなたのフォローアップの質問を理解しているかどうか分からないので、例として最初のフレームをとり、next_game_tickが0で始まるとしましょう。次に、更新と表示が6msで完了したとしましょう。 next_game_tickは16にインクリメントされます。ここでsleep_timeは16 - GetTickCount()= 16 - 6 = 10です。したがって、次のフレームに移動する前にスリープ状態にするのに10ミリ秒あります。 –

+1

ちなみにGetTickCount()の戻り値はコード内のコメントで説明されています;-) 'システムが開始されてからのミリ秒数'、つまりマシンが起動してからの経過時間です。 –