Androidでゲームを制作する為に、FPSを一定に保つクラスを作成しました。
(フレームスキップの機能はありません)
スレッドの中で処理を無限ループさせている形を想定しています。
package 好きなパッケージ名で組み込んでください;
import java.util.concurrent.TimeUnit;
import android.util.Log;
/**
* FPSの表示・調整するクラス
*/
public class FPSManager {
// 1秒(ナノ秒単位)
private static long ONE_SEC_TO_NANO = TimeUnit.SECONDS.toNanos(1L);
// 1ミリ秒(ナノ秒単位)
private static long ONE_MILLI_TO_NANO = TimeUnit.MILLISECONDS.toNanos(1L);
private int maxFps;
private int[] fpsBuffer;
private int fpsCnt;
private long startTime;
private long elapsedTime;
private long sleepTime;
private long oneCycle;
/**
* コンストラクタ
* @param fps 動作FPS
*/
public FPSManager(int fps) {
maxFps = fps;
fpsBuffer = new int[maxFps];
fpsCnt = 0;
startTime = System.nanoTime();
oneCycle = (long)(Math.floor((double)ONE_SEC_TO_NANO / maxFps));
}
/**
* 状態更新
* @return sleepする時間(ナノ秒)
*/
public long state() {
fpsCnt++;
if (maxFps <= fpsCnt) {
fpsCnt = 0;
}
elapsedTime = System.nanoTime() - startTime;
sleepTime = oneCycle - elapsedTime;
// 余裕が無い場合でも1ミリ秒はsleepさせる
if (sleepTime < ONE_MILLI_TO_NANO) {
sleepTime = ONE_MILLI_TO_NANO;
}
int fps = (int)(ONE_SEC_TO_NANO / (elapsedTime + sleepTime));
fpsBuffer[fpsCnt] = fps;
startTime = System.nanoTime() + sleepTime;
return sleepTime;
}
/**
* FPSの取得
* @return 現在のFPS
*/
public int getFps() {
int allFps = 0;
for (int i = 0; i < maxFps; i++) {
allFps += fpsBuffer[i];
}
return allFps / maxFps;
}
}
使い方。
まずは初期化。
// FPS:30で動作させる
FPSManager fpsM = new FPSManager(30);
一定間隔で実行したいThreadのRun()メソッド内で
TimeUnit.NANOSECONDS.sleep(fpsM.state());
を呼ぶ。
以上。
[…] 現在開発中のシューティングゲームでは、スレッドの速度制御がかなり大切になります。 どの機種で動作させても速度は一定である必要があります。その為のクラスを作ろうとしたのですが、ネットを探すと見つかったので、 こちらのFPSを一定に保つクラスを使っています。 […]
Pretty great post. I just stumbled upon your blog and wanted to mention that I have really loved browsing your weblog posts. After all I will be susibrcbing on your feed and I’m hoping you write once more very soon!