ゲームエンジンの基本:タイマー

私の友人のリクエストで公開された、あなたは記事が好きなら、あなたは彼に招待を送ることができます。

PMで石鹸と言うか、ここに書くことができます。 :)



この記事では、ゲームエンジンの作成を開始した方法、正確なタイマーを作成する問題に遭遇した方法、および解決方法を説明します。 ほとんどすべての人が遅かれ早かれこのような問題に直面することになると確信しているので、私の記事はタイマーを作成している人やそれについて考えている人に役立つでしょう。 私は、コードの純度も、特定の条件下で下される決定の理想性も主張しません。 それでは、私たちの代名詞を終わらせ、実際の問題に移りましょう。



目的:ゲームエンジンで使用する正確なタイマーを作成します(つまり、時間間隔の測定に加えて、一定時間後に発生するイベントの動作を確認する必要があります)。



まず、一般的な期間の測定に使用するものを決定する必要があります。 時間の正確性に関する最も論理的な決定は、QueryPerformanceCounter / QueryPerformanceFrequency関数を使用することです。 時間を測定する意味は、時間間隔の始まりを記憶し、現在の時間を確認して結果を返すことです-2つの測定値の差。 しかし、「長い」時間を作る必要があります。つまり、たとえば現在の時刻から正確に3秒が経過する時期を事前に知る必要があります。



タイマーがこのように機能するようにするには、次の操作を実行できます。イベントマネージャークラスで「イベント」を開始する前の時間と一緒に保存し、継続的に期間(次の開始=現在の終了)を測定し、最初に0である変数に時間間隔を追加します。そして、いずれかのイベントで変数の値がイベントの開始前の時間以上になるとすぐに、イベントを実行します。



イベントが開始する前に時間が経過すると、イベントが論理的に常にアクションが完了したことを意味するとは限らないため、イベントが開始する前に時間の長さと呼ばれます。 たとえば、私のエンジンでは、イベントを使用して1秒あたりの正確なショット数を確認します(各ショットの後、指定された時間後に撮影が禁止および許可されます。



これらの期間を一貫して継続的にするために、これらの期間を実際に確認して記憶する方法について考えるだけです。 ここでの論理的な解決策は、フレームレートを使用して、各フレームの時間の長さを測定することです。 QueryPerformanceCounter / QueryPerformanceFrequency関数はプロセッサに大きな負荷をかけるため、それぞれの後にSleepを実行してフレームレートを制限することは理にかなっています。 スリープ機能の粗さはここでは重要ではありません。なぜなら、時間は連続的に測定されるからです。つまり、測定されたセグメント間にギャップはありません。



次に、上記を示すための小さなコード:



フルタイマークラス:

de_timer.h:

Copy Source | Copy HTML<br/> #ifndef __DE_TIMER_H<br/> #define __DE_TIMER_H<br/> <br/> #include <windows. h ><br/> <br/> // <br/> class deTimer <br/>{<br/> LARGE_INTEGER start; // <br/> double frequency; // <br/> double tickLength; // <br/> double currentCheckTime; // <br/> double lastCheckTime; // <br/> // <br/> void init();<br/> // <br/> double getFrequency();<br/> // ( ) <br/> double readTimer();<br/> public :<br/> // <br/> void startTimer();<br/> // <br/> void updateTimer();<br/> // <br/> // : , <br/> // <br/> double getTimeInterval() { return currentCheckTime - lastCheckTime;}<br/>};<br/> <br/> #endif <br/> <br/>







de_timer.cpp:

Copy Source | Copy HTML<br/> #include "de_timer.h" <br/> <br/> // <br/> void deTimer::init()<br/>{<br/> // <br/> frequency = getFrequency();<br/> tickLength = 1 . 0 / frequency;<br/>}<br/> <br/> // <br/> double deTimer::getFrequency()<br/>{<br/> LARGE_INTEGER freq;<br/> <br/> if (!QueryPerformanceFrequency(&freq))<br/> return 0 ;<br/> return ( double )freq.QuadPart;<br/>}<br/> <br/> // ( ) <br/> double deTimer::readTimer()<br/>{<br/> // <br/> DWORD_PTR oldMask = SetThreadAffinityMask(GetCurrentThread(), 0 );<br/> // <br/> LARGE_INTEGER currentTime;<br/> QueryPerformanceCounter(&currentTime);<br/> // <br/> SetThreadAffinityMask(GetCurrentThread(), oldMask);<br/> // <br/> return (currentTime.QuadPart - start.QuadPart) * tickLength;<br/>}<br/> <br/> // <br/> void deTimer::startTimer()<br/>{<br/> // <br/> init();<br/> // <br/> DWORD_PTR oldMask = SetThreadAffinityMask(GetCurrentThread(), 0 );<br/> // <br/> QueryPerformanceCounter(&start);<br/> // <br/> SetThreadAffinityMask(GetCurrentThread(), oldMask);<br/> // <br/> lastCheckTime = currentCheckTime = readTimer();<br/> // ( ) <br/> srand(( int )start.QuadPart);<br/>}<br/> <br/> // <br/> void deTimer::updateTimer()<br/>{<br/> // <br/> lastCheckTime = currentCheckTime;<br/> // <br/> currentCheckTime = readTimer();<br/>}<br/> <br/>







sourceforge.net/projects/dustengineで現在の状態のエンジンコードの残りを見ることができます

タイマーとイベントマネージャーのコードは次のファイルにあります。

de_timer.h、de_timer.cpp、de_event.h、de_event_manager.h、de_event_manager.cpp

執筆時のエンジンバージョン:0.1



英語でのコメントにもかかわらず、私がコードを書いたことをすぐに予約してください(私はプロジェクトで英語を使う習慣を身につけています)。



UPD。 sf.netのexfixはwin7(!)(Vistaでも動作する可能性があります)専用です。winXPではwin98との互換性をインストールするときに動作します(奇妙ですが、本当です)。 これらはすべてwin7およびwin7でコンパイルされました。



All Articles