-- / --
--
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

09 / 23
Mon

Java でゲームを作ることになって、 これまで勝手にやってくれていたことを自前でやらないといけなくなりました。 例えば、 FPS の維持とか。 StarRuby では、 メソッドの引数に FPS の値を渡してやるだけでよかったんですが、 Java では全部自分でやらないといけないんですよね。

ということで、 FPS を一定に維持してくれるクラスを作ってました。 仕組みはそんなに難しくないです。

クラスのフィールドとコンストラクタはこんな風になっています。

private Integer idealFps;
private Long realFps = 0L;
private Integer idealSleepTime;
private Long oldTime = 0L;
private Long errorTime = 0L;
private Long sleepTime = 0L;
public FpsSleep(Integer fps) {
  idealFps = fps;
  idealSleepTime = 1000000 / idealFps;
  oldTime = System.currentTimeMillis();
}

idealFps は設定する FPS、 idealSleepTime は 1 フレームの待ち時間 (ミリ秒) の 1000 倍です。 固定小数点数を扱うため、 時刻や時間を扱う変数には全て 1000 倍された数値が入れられます。 errorTime は待機時間の誤差です。 これについては後で説明します。

さて、 クラスの使い方ですが、 画像の描画やオブジェクトの更新を行う前に、 以下の start メソッドを呼び出します。

public void start() {
  oldTime = System.currentTimeMillis();
}

処理前の時刻を oldTime に保存してるだけです。 そして、 1 フレーム分の処理が終わったら、 以下の finish メソッドを呼び出します。

public void finish() {
  Long newTime = System.currentTimeMillis();
  sleepTime = (idealSleepTime + errorTime - (newTime - oldTime) * 1000) / 1000 * 1000;
  if (sleepTime < 1000) {
    sleepTime = 1000L;
  }
  errorTime = (idealSleepTime + errorTime - (newTime - oldTime) * 1000) - sleepTime;
  if (errorTime < 0L) {
    errorTime = 0L;
  }
}

まず、 現在時刻を newTime に代入します。 次に、 待機すべき時間を sleepTime に代入しています。 処理にかかった時間は newTime - oldTime で得られるので、 この分を 1 フレームの待ち時間である idealSleepTime からひいてやれば、 待機すべき時間が求まります。 最後の / 1000 * 1000 というのは、 百の位以下を切り捨てて 1000 の倍数にしているだけです。 実際に待機するミリ秒数は整数ですから、 1000 の倍数にしておかないといけませんからね。

さて、 では errorTime は何なのかというと、 1000 の倍数に切り捨てられた誤差が格納されています。 例えば FPS が 60 に設定されているとすると、 処理と待機を合わせて 1 フレームは 16.666 ミリ秒になります。 しかし、 実際に待つのは 16 ミリ秒なので、 1 フレームごとに 0.666 ミリ秒の誤差が生まれます。 この誤差によって、 FPS が正確に 60 に保たれなくなってしまうわけです。 そこで、 誤差の 0.666 ミリ秒を errorTime に保存しておいて、 次のフレームの待ち時間を計算するときに、 1 フレーム分を 16.666 ミリ秒ではなく、 誤差をたし合わせた 17.332 ミリ秒として計算するわけです。 すると、 ここでは 1 フレームは 17 ミリ秒となり、 誤差 0.332 ミリ秒がまた次のフレームに持ち越されます。

さて、 これで理論上はうまくいくはずなんですけどね、 FPS を 60 に設定して動かしてやって、 実際の FPS を計測すると 57 くらいで安定するんですよね。 何でですかね。 ちょっとよく分からないんですよね・・・。

スポンサーサイト

comment ×0
コメント
管理者にだけ表示を許可する
 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。