frostar@wiki
FPS管理
最終更新:
frostar
-
view
- fpsとは
- frame per second(1秒間のフレーム数)のこと。
- もっと簡単にいうと、1秒間に何枚の画像を表示しているかということ。
- 1秒間に画像を少しずつ動かして表示することにより、動画のように見えるので、動画のなめらかさとも直結する。
- もちろんfpsが大きいほどなめらかになるが、描画処理というのは時間がかかるもので、徒に大きくしすぎても無駄になる。
- だいたい、ゲームだとfps60(1秒間に60回描画)位が普通っぽい。
- fpsとは
- 実際にfpsをどう管理するか。
- windowsのAPIにはTimerというものがあり、それを使う方法もあるが、精度が低いため、あまり向かない。
- 基本的には、マルチスレッド化して、そこでの無限ループで、fpsの管理と描画をすることになると思う。
- 実装
- 描画用スレッドの中身の概要。
DWORD ts=timeGetTime();//時間変数 DWORD te=ts; int count=0;//描画回数 double f = 1000.0/60;//1フレームの時間(1000.0/fps。この場合はfps60の場合) timeBeginPeriod(1);//timeGetTimeの精度変更 while(TRUE){ te = timeGetTime(); if((te-ts)>=f*count){//フレーム処理 //更新処理 if(!((te-ts)>=((count+1)*f))){//フレームスキップ処理 //描画処理 } count++; } if((te-ts)>=1000){ //1秒ごとにtsとcountの初期化 //(FPS描画) ts = timeGetTime(); count=0; } Sleep(1); } timeEndPeriod(1);//timeGetTimeの精度を元に戻す
- 関数説明
- timeGetTime、timeBeginPeriod、timeEndPeriodについては時間計測のページを参照
- 処理説明
- まず、最初の4行で使用する変数の定義と初期化を行い、whileループの中に入る。
- また、timeBeginPeriod(1)として、タイマ精度を1msに変更する(精度が低くても問題ないのであれば変更しなくてもよい)。
- timeBeginPeriodを使用すると、他のアプリケーションのタイマにも影響を及ぼすらしいので注意。
- 特に使わなくなった時にはtimeEndPeriodを確実に呼ぶこと(引数はBeginと同じ)
- whileループの最初では、変数teに現在の時間を入れる。
- 次の条件分では(te-ts)>=f*countを条件として、フレームの処理に入る。
- te-tsは開始時と現在の時間で、それがf*count、つまりフレーム処理予定の時間よりも大きいときはフレーム処理を行う。
- フレーム処理では、画面の更新処理と画面の描画処理を行う。
- 描画処理、フレームスキップについては後述。
- (te-ts)>=1000、つまり1000ms(1秒)経過するごとにtsの値の更新とcountの初期化を行う。
- ここで、初期化する前のcountの値はそのままFPSとなっている(厳密にいえばcount/(te-ts)なんだろうが)。
- そして、処理が終わったら1msのSleepをかける。
- 描画処理とフレームスキップ
- 描画処理は、処理内容によってはその処理だけで1フレームの時間をオーバーし、次の更新タイミングを超える場合がある。
- そのような場合には、描画処理を飛ばすことにより、フレームの整合性を保つ。
- これをフレームスキップという。
- 描画処理を飛ばしても、更新処理は行われるため、アニメーション自体の整合性も保たれるのである。
- フレームスキップを行う条件は!((te-ts)>=((count+1)*f))となっている。
- (count+1)*fは、次の更新タイミングであり、現在の時間が次の更新タイミングよりもオーバーしていないときに描画処理を行う。
- つまり、オーバーしているときは描画は行われないため、フレームスキップとなる。