ゲームプログラムのメインループ

HTML5のWebゲームに限らず、多くのゲームではキャラクタや背景などが常に「動いて」います。キー入力やタッチ操作でユーザーのキャラクタが移動したり弾丸を発射するのはもちろん、何も操作していなくても敵が移動したり背景がアニメ表示されたりしているわけですね。

このような「常に変化する状態」を実現するためには、ゲームの状態をプログラムで更新し表示する必要があります。つまり、ずっと処理を行い続けて更新された「現在の状態」を画面上に表示する必要があるのです。

そのように常に更新と描画を行うための仕組みとして、メインループ(ゲームループ)というものがあります。これは、文字通り「プログラムの中心となるループ(繰り返し構造)」を作って、その中でゲーム状態の更新と描画処理を行う仕組みです。

1.ループ開始
2.ゲームの状態を更新
3.現在の状態を画面に描画
4.1に戻る

という感じですね。

実際のゲームでは、ゲームの状態更新と描画を一定間隔で行うため4から1に戻る際に、適当なウエイト(待ち時間)を入れることで、時間調整を行います。たとえば、1秒間の画面更新回数(フレームレート)を30(30FPS)とするなら、約33ms毎に描画処理が行われるようにウエイトを調整します。

ただ、HTML5のプログラミング環境であるJavaScriptではメインループのように「常に動かし続ける」ループを実行すると、ブラウザが止まってしまうため、実際には「メインループの処理を実行する関数」を用意し、その関数を一定間隔で呼び出す形でメインループと同等の構造を実現することになります。

JavaScriptには、setTimeout()という指定時間が経過したら師弟の処理を行う関数が用意されているので、関数loopを33msのウエイトを入れて呼び出し続けるなら、以下のように書けます。

function loop() {

	ゲームの状態を更新
	現在の状態を画面に描画

	setTimeout("loop()", 33);

}

実際には、更新や描画の処理時間があるので、loop()の最初と最後で現在時間を計測して処理時間を算定し、その処理時間をウエイトから差し引けばより高い精度で更新周期(フレームレート)を安定させることができるでしょう。

ただし、JavaScriptの現在時刻を取得する機能の精度やsetTimeout()の精度の問題もあるので、どれだけの精度でフレームレートを制御できるかは環境にも依存します。また、時間がかかる「重い」処理が発生するゲームでは、1フレームの更新時間内に処理を完了させることができない場合もあるでしょう。

ちょっとしたミニゲームであれば、それほどフレームレートの精度も必要ないので、こうした点はあまり気にする必要はありませんけどね。多数のキャラクタを動かしながら凝ったアクションを楽しむ本格派のアクションゲームでは、フレームレートが乱れると一方向に移動し続ける間に「自分の移動速度」が不安定になったり敵がワープしているように見えたりするので、違和感を感じる可能性が出てきます。