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!