s5. 処理速度を一定にする。
コンピュータは1秒間に何百万回も計算するのに、現在書いているコードを実行するとループは1秒間に60〜120位しか
ループしてない事に疑問を持った方もいらっしゃるでしょう。
ScreenFlip() ; この関数は画面のリフレッシュレートにあわせて裏画面を反映する関数です。
リフレッシュレートとは、モニタが1秒間に画面を書き換える回数です。
普通モニタは1秒間に60〜120回描画しています。モニタのリフレッシュレートにあわせて
裏画面を反映させないとチラチラして表示されてしまうことは想像できますね。
ですから、 ScreenFlip() ; を書くと、ループの回数がリフレッシュレートと同じになるのです。
(ただし、処理が重く、1回のループに1/60〜1/120秒以上かかっていたらリフレッシュレートと同じにはなりません)
リフレッシュレートは自由に変更できます。
デスクトップで「右クリック」>「プロパティ」>「設定」タブ>「詳細設定」>「モニタ」で変更できます。
普通モニタは60ヘルツつまり1秒間に60回更新します。良質なモニタなら120以上のリフレッシュレートも存在します。
ここで、キャラクターを動作させるのに今までcounterを使っていました。
int counter=0;
while(......){
counter++;
}
こんな風にcounterの数字によってキャラを移動させたりしていましたが、モニタのリフレッシュレートが早ければ
それだけ早くキャラが動いてしまいます。
ゲームをしてもらう人に「リフレッシュレートを60に設定してから遊んでください」というのはあまり実用的ではありません。
ですからこちらでゲームループ回数をのリフレッシュレート60に合わせましょう。
120ヘルツであっても100ヘルツであっても、処理が1回に1/60秒かかるまで待たせるのです。
1÷60=0.166666......
つまり、1回の処理に16(ms←ミリ秒)〜17(ms)かかればリフレッシュレート60に合います。
1回の処理にかかった時間を計測し、16ミリ秒より遅ければトータル16ミリ秒になるまでSleepするようにプログラムを書いてみます。
まず、この処理を担当する関数名をwait_fancとでも名づけましょう。
void wait_fanc(){
ローカル変数を宣言し、変数のデータが関数を抜けても失わせれないようstatic変数で宣言します。
static int t=0;
tには1回前の時間を格納します。GetNowCountで現在の時間が取得できますから
現在の時間 - 1回前の時間 を計測すれば1回の処理にかかった時間がわかります。
これをほかで用意することにしますint型変数waitに格納します。
wait = GetNowCount()-t;
t=GetNowCount();
waitがもし16ミリ秒より少なければ、トータル16ミリ秒になるまでSleepさせます。
if(16-wait>0)
Sleep(16-wait);
こうすることで、1回の処理が16ミリ秒に統一できました。
1000 ÷ 16 = 62.5
ですからだいたい1秒間に60フレームでゲームが作成できます。まとめると以下のようになります。
void wait_fanc(){ int term; static int t=0; term = GetNowCount()-t; if(16-term>0) Sleep(16-term); t=GetNowCount(); return; }
今回は次の節と一緒にサンプルプログラムを作っていますので、今回はサンプルプログラムがありません。
次の節を一緒に読んでください。
- Remical Soft -