したらばTOP ■掲示板に戻る■ 全部 1-100 最新50 | メール | |

管理人の独り言(プログラミング関連)

5774さん:2008/08/11(月) 02:12:19
以下全て引用
-----
第4F回 正確な60FPSの実現(ウエイトタイマ構成法) 99/6/8

どことなくマニアックになってきた、この連載であるが、今回は、正確な60FPS(秒間60フレーム)を実現するためのウエイトタイマ(時間待ち)ルーチンについて説明する。

よく、タイミングはDirectDrawでflipすれば速いマシンなら60FPSになるので、それで調整するという人もいるが、これは、

1.遅いマシンでは60FPSにならない(タイミングが必要ならtimeGetTimeで調整すべき。第49回参照)
2.Flipは、使わないほうが無難。(第44回参照)
3.画面のリフレッシュレートは60Hzとは限らない。

という3つの理由で間違っている。

あと、正確に60FPS刻むような待ち時間を計算できない人がよくいるが、以下のソースを見れば、なんとなくコツがつかめるはずである。コツとしては、

1.システムに負荷をかけないよう、余分な時間はSleepする。(Sleepの精度を考慮に入れて、直前まではSleepさせない)
2.今回の待ち時間は、1000/FPSとやってしまうと、端数分だけおかしくなる
3.かと言って、精度を出すためにdouble型で今回の待ち時間を計算するのは少し、無駄

の3ポイントぐらいであろう。速いマシンで正確に60FPSを刻まないのは、この待ち時間の消費のさせかたが間違っているからである。描画(blt)の直前にこのルーチンを呼べば、必ず安定して、指定のFPSになる。


--------------------------------------------------------------------------------

void ys::ElapseTime(void){ // (C)yaneurao 1998-1999
// 厳粛かつ正確かつ効率良く時間待ちをする

if (iFPS == 0) return ; // Non-wait mode

static DWORD lastdraw = 0; // 前回の描画時刻
// (不運にも第一発目のtimeGetTime() == 0とかゆーこともあるが、それは構わない)

DWORD t = timeGetTime(); // 現在時刻

dwFPSWaitTT = (dwFPSWaitTT & 0xffff) + dwFPSWait; // 今回の待ち時間を計算

// dwFPSWaitは、待ち時間の小数以下を16ビットの精度で持っていると考えよ
// これにより、double型を持ち出す必要がなくなる。
// dwFPSWaitTT = 1000 * 0x10000 / FPS;である

DWORD dwWait = dwFPSWaitTT >> 16; // 結局のところ、今回は何ms待つねん?

// 1フレーム時間を経過しちょる。ただちに描画しなちゃい!
DWORD dwElp = (DWORD)(t - lastdraw); // 前回描画からいくら経過しとんねん?
if (dwElp>=dwWait) {
lastdraw = t;
return ;
}

// ほな、時間を潰すとすっか!

// まだ時間はたっぷりあるのか?
// 4ms以上消費する必要があるのならば、Sleepする
if (dwWait-dwElp >= 4) Sleep(dwWait-dwElp-3);
// いまdwWait>dwElpなのでdwWait-dwElp>=0と考えて良い

// 95/98/NTで測定したところSleep(1);で1ms単位でスリープするのは可能
// ただし、実装系依存の可能性もあるのでSleepの精度は3ms以内と仮定

while ((timeGetTime()-lastdraw)<dwWait) ;
// ループで時間を潰す(あまり好きじゃないけど)

// これで、時間つぶし完了!

lastdraw += dwWait; // ぴったりで描画が完了した仮定する。(端数を持ち込まないため)
}


--------------------------------------------------------------------------------

しかし、きちっと、このようなFPS調整のための時間待ちルーチンを書いている人を見たことがない。

小数点以下をdoubleで表記するのではなく、256倍や65536倍して整数で代用するのは、常用テクなのだが、意外と知らない人が多い。もっとも、なんでもかでも1命令1クロックで実行してしまう最近のCPUではあまり意味のないことなのかも知れない。しかし、最近のプログラマは、lineやcircleをアセンブラで実装した経験が無いのか?cos,sinを65536倍した整数テーブルをいじくり回すプログラムを書かないのか?そんな人たちが3Dでぐりぐり動くゲームを作っているのか?!まったくもって驚きである。8月に恐怖の大王が来るというよりは、65536倍衝撃的なんだってば!!


新着レスの表示


名前: E-mail(省略可)

※書き込む際の注意事項はこちら

※画像アップローダーはこちら

(画像を表示できるのは「画像リンクのサムネイル表示」がオンの掲示板に限ります)

掲示板管理者へ連絡 無料レンタル掲示板