[
板情報
|
カテゴリランキング
]
したらばTOP
■掲示板に戻る■
全部
1-100
最新50
|
メール
|
1-
101-
201-
301-
401-
501-
601-
701-
801-
901-
1001-
1101-
1201-
1301-
1401-
1501-
1601-
1701-
1801-
1901-
2001-
2101-
2201-
2301-
2401-
2501-
2601-
2701-
2801-
2901-
3001-
3101-
3201-
3301-
3401-
3501-
3601-
3701-
3801-
3901-
4001-
4101-
4201-
4301-
4401-
4501-
4601-
4701-
4801-
4901-
5001-
5101-
5201-
5301-
5401-
この機能を使うにはJavaScriptを有効にしてください
|
管理人の独り言(プログラミング関連)
5
:
774さん
: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
(省略可)
:
※書き込む際の注意事項は
こちら
※画像アップローダーは
こちら
(画像を表示できるのは「画像リンクのサムネイル表示」がオンの掲示板に限ります)
スマートフォン版
掲示板管理者へ連絡
無料レンタル掲示板