msty開発メモ

技術ネタを綴ります

【プログラミング】処理落ちに対応する考え方

実装されててアタリマエのことですが、されていないフリーゲームもちらほら見るので考え方とC言語でのサンプルだけちょっと紹介。



処理落ちに対応するには実に簡単で、小学校で習った「距離=速さ×時間」を使います。

この"時間"の部分ですが、ゲームであれば、1フレームごとに座標の更新(座標の再計算)が行われる処理が多いと思いますが、これは実に都合がよく、簡単に実装できます。



この場合での必要な要素は、

  • 1秒間の移動量(速さ)
  • 1フレームの処理時間(時間)

実際に見てもらったほうが早いと思うので
まずソースを貼ります

#include<Windows.h>

void Loop();
void Update();

long long deltaTime = 0;

int main() {
	Loop();
}

void Update() {
	static float score = 0;
	static float scoreAdd = 100;//1秒で増えるスコア

	score += scoreAdd*(deltaTime / 1000.0f);

}

void Loop() {

	//無意味な無限ループ(サンプルなので適当)
	while (1) {
		static long long start = 0;
		static long long end = 0;

		//処理開始時間を記録
		start = timeGetTime();
		{
			//1フレーム内で行う処理

			Update();

		}
		//処理終了時間を記録
		end = timeGetTime();

		//終了時間 - 開始時間 = 1フレームにかかった処理時間
		deltaTime = end - start;

	}


}

Loop関数から見ていきましょう。
まず、座標の更新などの処理を始める前に、処理開始時の時間を取得します。
その後に必要な処理を全て行います。
処理が全て終わったら、処理終了時の時間を取得します。

このふたつを使ってサンプルのように計算することで、1フレームにかかった時間を取得することができます。
これで距離の計算に必要な"時間"が用意できましたね。

次にUpdate関数を見ていきましょう。
今回は座標計算ではないですが、1秒ごとにスコアが100ずつ増えていくようにしています。

このサンプルでは1フレームの時間(ミリ秒)がそのまま整数値となっているので、それを秒に直しています。

このプログラム例だと、
現在のスコア += (1秒に増える時間) × (1フレームの処理にかかった時間) です。

例えば、現在のスコアを0、1フレーム100ミリ秒かかったとすると、

0 += 100 × 0.1;

となり、スコアが10加算されます。
10FPSだとこれが1秒間に10回起きるわけですから、結果的に1秒で100加算されます。

ここで注意しておきたいのが、理由がない限り、少数が扱えるデータ型にしてください。
整数型にしてしまうと、切り捨てなどが起きてしまい計算がおかしくなります。


そんなことよりラーメンとじゃがバター食べたいですね。