2011年07月29日

C#とDXライブラリでゲーム制作 5回目

フレームレートの制御(FPS制御)

ゲームループをそのまま実装すると、パソコンの性能によってゲームの進行速度が変わってしまうという問題が発生します。制作者のPCの性能に合わせてゲームを作った場合、それよりも性能が高い・低いPCでは、ゲームの進行速度が違うため、ゲームとして成立しないことがあります。例えるなら、早送りやスローモーションでゲームをやるようなものです。

これを防ぐために、ループ内でスリープすることを考えます。例えば1ループにつき20ms(ミリ秒)のSleepを行えば、性能の高いPCでの問題は解決しそうです。しかし、「更新処理」や「描画処理」などにかかる時間の分は調整できません。アドベンチャーやシミュレーションであれば大きな問題にはならないかもしれませんが、アクションやシューティングでは致命的な問題になるかもしれません。それに、性能の低いPCでの問題は解決できません。

そこで「フレームレートの制御」を行います。

「フレームレートの制御」「フレーム制御」「FPS制御」などの名前で呼ばれるこの機能は、ゲームループと同じくゲーム制作における基本技術です。「FPS」は「Frames Per Second」のことで「フレームレート」を表す単位です。(したがって“FPS制御”という名前は間違っているような気がしますが、昔からこのような名称で呼ばれていました)

「フレームレートの制御」についての詳細は、この場では説明しきれないので割愛させていただきます。幸いにも解説しているサイトはいくらでもあるので、上記のキーワードで検索してみてください。

フレームレート制御の概略

フレームレートを制御するためには、「ディレイ」と「描画スキップ」の2つが必要です。1フレームの処理が早く終わって時間が余っている場合は「ディレイ」で調整します。1フレームの処理に時間がかかってしまい足りなくなっている場合は「描画スキップ」で時間を稼ぎます。これは1フレームの処理で最も時間がかかるのが「描画処理」であり、他の「入力処理」「更新処理」は大した時間がかからないためです。

具体的には、各フレームの開始時刻を演算で求め、その時刻まで間があれば「ディレイ」、そして次のフレームまで余裕があれば「描画処理」を行う。余裕がなければ「描画スキップ」という風にします。

これをゲームループに入れるとこのようになります。

while (true)    // 無限ループ
{
    次のフレームを待つ();
    入力処理();
    更新処理();
    if(描画する時間がある)
    {
        描画処理();
    }
    DX.ProcessMessage(); // Windowsメッセージの処理
    if(戻り値が-1)
    {
        break; // ループを抜ける
    }
}

「各フレームの開始時刻」はフレームレートに合わせて1フレームの時間を加算していくことで計算します。

「次のフレームを待つ」は現在の時刻を取得し、「次のフレームの時刻」になるまでスリープしながら待ち続けます。

「描画する時間がある」かどうかの判定は、現在の時刻から「次の次のフレームの時刻」まで時間があるかどうかで決めます。

フレームレート制御クラス

フレームレートを制御するためのクラス『FPSTimer.cs』を作ったので公開します。フレームレートの制御だけでなくフレームレートを測定する機能もつけました。本当に真面目にフレームレートを制御するには不十分ですが、個人で作るレベルのゲームであれば十分だと思います。

FPSTimer.cs

良かったらクリックしてください
にほんブログ村 IT技術ブログ プログラム・プログラマーへ  人気ブログランキングへ

posted by among at 21:00 | Comment(1) | TrackBack(0) | ゲーム制作
この記事へのコメント
System.Environment.TickCountで取得できる値の単位はμsではなくmsでは?

Environment.TickCount プロパティ (System)
http://msdn.microsoft.com/ja-jp/library/system.environment.tickcount.aspx

Posted by at 2013年09月05日 01:16
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/46903649

この記事へのトラックバック