fc2ブログ

Javaゲーム制作記

いろいろ作ってます  

ミリ秒のsleepで正確にFPSを固定する方法

いろいろな方法があるようですがどうも問題があったりしたので 自分なりのやり方を書いておきます。


いろいろ省略してありますがこんな感じのメインループを作ったとします。



休止の部分には、60FPSになるように 1000÷60=16.66666...≠16 ミリ秒休止をしています。

しかしこれではメイン処理に時間がかかったとき遅れてしまいます。
実行・休止全部含めて16ミリ秒でないといけないのです。

そこで、以下のように修正します。



これで大体の問題が解決しました。
しかし一つだけ問題が残っています。
動かしてみると分かると思いますが、実はこのコードは60FPSでは動きません
62、63FPSあたりをウロウロしているはずです。


この原因は、最初に 1000÷60=16.66666...≠16 としてしまった所にあります。
小数点以下を切り捨ててしまっているので、
図のように1ループにつき0.66666...ミリ秒の誤差が生じてしまっています。


(緑のブロックが1ループです)

これを無くす方法として、「誤差を次ループへ持ち越す」というものがあります。
休止すべき理想の時間(この場合16.66666...)と実際に休止した時間との差を、
次ループの休止時間から引いてやるだけです。
そうすることで、誤差を常に1ミリ秒以下の状態に抑えることができます。


(黄色の部分が持ち越された誤差です)

この方法では、小数点以下を保持しておく必要が出てくるため、整数型では足りなくなってしまいますが、
固定小数点数を使うことでこの問題を回避できます。
整数型に1000倍した数を格納しておいて、必要なときに1000で割って戻すというような方法です。

また、2の累乗の乗除算はビット演算化できるので、高速に処理することができます。


これらを元に、メインループを書き直すと以下のようになります。



これでようやく正確なFPSが出るようになりました。
fps = 60 の部分をいじれば好きなFPSに調節できます。
コードはご自由にお使いください。

※JavaにはSystem.nanoTime()というメソッドもありますが外部から操作されやすいため余りお勧めできません。
[ 2011/10/28 16:47 ] Java | Comment(3)
FPS固定の方法を探していたので参考になりました。
ありがとうございます。
[ 2011/12/17 19:58 ] [ 編集 ]
FPSが安定しなかったので参考にさせていただきました
ありがとうございます。
[ 2012/07/31 12:29 ] [ 編集 ]
承認待ちコメント
このコメントは管理者の承認待ちです
[ 2015/07/07 14:08 ] [ 編集 ]
コメントの投稿




※URL記述の際はttp://としてください


プロフィール

saharan

Author:saharan

Twitter
検索フォーム