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() を何度も使用する場合は必須です。
また、厳密な時刻を取得したい場合、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秒ごとに関数を呼び出し、そのたびに何秒経過しているか求めています。
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、ブラウザ、そのときのパソコンの状態により、微妙に異なっているのです。