GO TO TOP
ゲーム制作講座

制作講座目次 / PREV(画像を使いこなせ) / NEXT(ゲームを作る順序) / トップページ / text mode
basic
5.タイマーを使いこなせ

★自動でゲームを動かす

今まで作ってきたゲームは、プレイヤーの入力に応じて異なった反応をするといったものでした。アドベンチャーゲームならそれで問題ありませんが、アクション性の高いゲームだと、「○秒間」「○分以内に」のような処理が必要になります。そこで、一定間隔の時間で関数を実行する「タイマー」の機能を使います。

タイマーの設定方法は、

timer=setInterval("関数名()",時間間隔);

のようにします*1(timerは変数。事前に定義しておきます)。関数名のところに一定間隔で実行したい関数名を入れ、時間間隔のところではどれくらいの間隔で実行するかを決めます(単位はミリ秒=1/1000秒)。
たとえば制限時間つきのゲームで、残り時間を表示させたい場合は、一定間隔で実行する関数内で残り時間の処理をすればいいのです。

*1 一定間隔で実行する命令には、setTimeoutもありますが、ここでは省略します。ちなみにsetIntervalのほうが間隔が狂いにくいと言われています。

<script language="JavaScript">
var timer=0;
var nokorijikan=10;
var countFlag=true;

function countdown(){
	if(countFlag){
		timer=setInterval("nokoridown();",1000);
		countFlag=false;
	}
}
function nokoridown(){
	nokorijikan--;
	if(nokorijikan<0){
		alert("どか〜ん");
		clearInterval(timer);
	}
	else document.form1.elements[0].value=nokorijikan;
}
</script>
<body>
<form name="form1">
のこり <input type=text> 秒<br>
<input type=button value="カウントダウン開始" onClick="countdown();"><br>
</form>

上のプログラムで nokorijikan が0の時に、clearInterval(timer) がありますが、これは動かしているタイマーを止める命令です。この命令は、特に setInterval() を何度も使用する場合は必須です。

★タイマーの間隔

タイマーで設定する時間間隔は、1000分の1秒単位で指定できますが、実際のコンピュータが処理できる時間間隔には、限界があります。
私自身の経験からでは、10ミリ秒単位の数値を指定してもほとんど意味がありません(たとえば、100ミリ秒と110ミリ秒では動きはほとんど変わらない)。速度の遅いパソコンのことも考慮すれば、100ミリ秒単位の数値を指定するのが無難です。

また、厳密な時刻を取得したい場合、setInterval で細かい値を指定するよりも、getTime を使用したほうが楽です。getTime は1970年1月1日00:00から何ミリ秒たったかを出力する関数です。通常は、new Date() と一緒に使います。

<script language="JavaScript">
var timer=0;
var nokorijikan=10;
var countFlag=true;
var starttime=0;

function countdown(){
	if(countFlag){
		var startdate=new Date;//開始時間を取得
		starttime=startdate.getTime();
		timer=setInterval("nokoridown();",100);
		countFlag=false;
	}
}
function nokoridown(){
	var nowdate=new Date;//現在時間を取得
	var nowtime=Math.floor(nokorijikan-(nowdate.getTime()-starttime)/1000);
	if(nowtime<0){
		alert("どか〜ん");
		clearInterval(timer);
	}
	else document.form1.elements[0].value=nowtime;
}

</script>
<body>
<form name="form1">
のこり <input type=text> 秒<br>
<input type=button value="カウントダウン開始" onClick="countdown();"><br>
</form>

上の例では、startdate や newdate に new Date を入れることで、そのときの時刻をミリ秒単位で記録します。そして、変数名.getTime() を使うことでその変数のミリ秒を呼び出します。
このとき出力される形式は、整数で「1006067032580」のような形です。カウントダウン開始ボタンを押した瞬間と、0.1秒ごとにnokoridown() が呼び出された瞬間の時刻の差を求めて、残り時間を出しています。この時、1000で割ることで時刻の差を1秒単位に直しています。
setIntervalは1秒ごとに呼び出していても、実際は関数内の処理などで1秒以上かかっている事が多く、また、ブラウザごとに呼び出される時間間隔が異なるため、0.1秒ごとに関数を呼び出し、そのたびに何秒経過しているか求めています。

★Count-Bomb

上の例の応用として、私の作ったゲームの「Count-Bomb」があります。そのソースをちょっと見てみましょう。

function tenmetu(){
	if(tenmetucnt<7){
		if(tenmetucnt%2==0)
			eval('moveLAYER("t'+timernum+'",90,'+ttop[timernum]+');');
		else eval('moveLAYER("t'+timernum+'",-90,'+ttop[timernum]+');');
		tenmetucnt++;
	}
	else{
		clearInterval(myID);
		startdate=new Date;
		myID=setInterval("cdown();",100);
	}
}

function cdown(){
	if(nowtime<3 || (timernum==5 && nowtime<5 ))
		eval('moveLAYER("t'+timernum+'",-90,'+ttop[timernum]+');');
	if(nowtime<-9) stoptime(nowtime);
	else dispcdown();
}

function dispcdown(){
	dispdate=new Date;
	nowtime=Math.floor(10000-(dispdate.getTime()-startdate.getTime())/itval[timernum])/1000;
	dispfloat=Math.floor(Math.abs(nowtime%1*100));
	if(dispfloat<10) dispfloat="0"+dispfloat;
	if(nowtime<0) dispint="-"+Math.floor(Math.abs(nowtime));
	else dispint="0"+Math.floor(nowtime);
	〜以下略〜
}

function stoptime(n){
	if(nowtime<10){
		clearInterval(myID);
		dispcdown();
		eval('moveLAYER("t'+timernum+'",90,'+ttop[timernum]+');');
		eval('moveLAYER("bt'+timernum+'",-160,'+bttop[timernum]+');');
		//誤差合計を求める
		totalerror+=Math.abs(nowtime);
		totalerror=Math.floor(totalerror*100)/100;
		status="誤差合計:"+totalerror;
		myID=setInterval("lightdown();",300);
	}
}

灰色でかかれた部分は、読み飛ばしてください。

カウントダウンが始まると、関数 tenmetu() が実行されます。ここでは、文字を何回か点滅してから実際のカウントダウンが始まります。cdown() が0.1秒ごとに実行されます。
cdown() では、カウント3以上ならデジタル表示をするため、dispcdown() へ移動します。dispdown() では、先ほど使ったテクニックを用いて、厳密な残り時間を求めています。なお、1カウント=1秒ではないので、itval[timernum] で割って補正をしています。
ストップボタンを押すと、stoptime(n) が実行されます。実行されると、まずは clearInterval でタイマーを止め、デジタル表示、誤差計算をしています。

さて、実際にこのゲームで遊ぶと分かるのですが、0.1秒ごとに表示させている割には、デジタル表示がきっちり0.1カウントずつ下がるというようなことが(1カウント=1秒のデジタルでも)ありません。
これは、先ほど述べたように厳密に0.1秒ずつ実行されていないからで、OS、ブラウザ、そのときのパソコンの状態により、微妙に異なっているのです。

★ここまでのまとめ

Basic Course では、JavaScript の本に書かれていることのうち、ゲームに直接関係しそうな所をかいつまんで紹介しましたが、いかかだったでしょうか。ブラウザゲームがこれだけで構成されているわけではありませんが、この5項目が基本となって、いろいろなゲームが作られています。
ここの説明が、よく分からなかった人がいるかもしれませんし、説明不足(もしくは説明下手)な所もあったかもしれません。そんなときは、市販の解説書を読みましょう。少なくともこのページを見てくれた人なら、本のどこを読めばいいか分かるはずです。1から本を読むことと比べれば、かなり楽に読めるはずです。
また、Basic Course ではゲームを作るための技術についてはいろいろ書いていましたが、具体的に作る順序や、ゲームプログラムならではのノウハウなどはここでは書かれていませんので、次の Advanced Course や Tips and Columns で書いていきたいと思います。


制作講座目次 / PREV(画像を使いこなせ) / NEXT(ゲームを作る順序)
記事の無断転載を禁ず(リンクは歓迎)
質問があればメールでどうぞ
(送ってくれた質問は、FAQとしてここに載せることがあります。質問者の名前は公開しません。)