その3へ戻る
その4 メインルーチンを作ろう
|
うおっほん。
今回は、メインルーチンを作ってみよう。
|
|
すかじい、「メインルーチン」って何?
|
すかじい
メインルーチンとは、プログラムの中心的な処理を行う部分のことじゃ。
いわばプログラムの司令塔じゃな。
|
え?まだ完成からは程遠いのに、
いきなり司令塔を作って大丈夫なの???
|
すかじい
ふぉっふぉっふぉ。そう思うのももっともじゃが、ソース自体は非常に短いんじゃ。
とりあえずソースを見てみようかの。
今回はHTML部分も含んでおる。
赤い部分が前回からの追加部分じゃ。
<html>
<head>
<title>テトリスもどき</title>
<script language="JavaScript">
<!--
// 使用する変数の宣言 --------------------------------------------------------
cr = "\r\n"
mojiretu= ""; // 画面に表示する文字列取得用
width = 8; // 画面の広さ
height = 20; // 画面の高さ
gameflag = false; // ゲーム中かどうかのフラグ
mode = 0; // 現在のゲームの状態チェック用変数
speed = 1000; // 次の処理へ進むスピード
score = 0; // スコア
level = 1; // レベル
// 仮想VRAM用2次配列
vr = new Array( width );
for ( i = 0; i < width; i++ ) {
vr[i] = new Array( height );
}
// 初期化用関数 -------------------------------------------------------------------
function Syokika() {
// 変数の初期化
gameflag = false;
mode = 0;
score = 0;
level = 1;
speed = 1000;
for ( i = 0; i < height; i++ ) {
for ( j = 0; j < width; j++ ) {
vr[j][i] = "□"; // 仮想画面クリア
}
}
// 仮想画面を表示する
Hyouji();
// 次画面をクリアする
mojiretu = "□□□□" + cr +
"□□□□" + cr +
"□□□□" + cr +
"□□□□";
document.game.tugi.value = mojiretu;
}
// 仮想画面を表示する関数
function Hyouji() {
// 画面に表示する文字列の作成
mojiretu = "";
for ( i = 0; i < height; i++) {
for ( j = 0; j < width; j++ ) {
mojiretu = mojiretu + vr[j][i];
}
if ( i != height - 1 ) {
mojiretu = mojiretu + cr;
}
}
// 画面の表示
document.game.gamen.value = mojiretu;
document.game.SCORE.value = score;
document.game.LEVEL.value = level;
}
// 各ボタンに対する関数
// 回転
function Moveturn() {
// ゲームが始まっていない時は、ゲームを始める
if ( !( gameflag ) ) {
gameflag = true;
Main();
}
}
// 左
function Moveleft() {
// ゲームが始まっていない時は、ゲームを始める
if ( !( gameflag ) ) {
gameflag = true;
Main();
}
}
// 右
function Moveright() {
// ゲームが始まっていない時は、ゲームを始める
if ( !( gameflag ) ) {
gameflag = true;
Main();
}
}
// 下
function Movedown() {
// ゲームが始まっていない時は、ゲームを始める
if ( !( gameflag ) ) {
gameflag = true;
Main();
}
}
// メインルーチン
function Main() {
// ゲームが始まっている時のみ処理をする
if ( gameflag ) {
// ゲームの状態によって、処理を変える
switch ( mode ) {
case 0:
break;
}
}
window.setTimeout( "Main()", speed );
}
// -->
</script>
</head>
<body onload="Syokika()">
<form name="game">
<center>
<table>
<tr><td>
</td><td>
<input type="text" name="SCORE" size="20">
</td><tr>
<tr><td valign="top">
<textarea name="tugi" rows="4" cols="10"></textarea><br>
Next<br><br>
<input type="text" name="LEVEL" size="5"><br>
Level
</td><td>
<textarea name="gamen" rows="20" cols="20"></textarea>
<table>
<tr align="center">
<td colspan="2">
<input type="button" name="TURN" value="TURN" onclick="Moveturn()">
</td>
</tr>
<tr align="center">
<td>
<input type="button" name="LEFT" value=" LEFT" onclick="Moveleft()">
</td>
<td>
<input type="button" name="RIGHT" value="RIGHT" onclick="Moveright()">
</td>
</tr>
<tr align="center">
<td colspan="2">
<input type="button" name="DOWN" value="DOWN" onclick="Movedown()">
</td>
</tr>
</table>
</td></tr>
</table>
</center>
</form>
</body>
</html>
ひろちゃん皇帝
本当だ。司令塔って言う割に、追加部分は少ないんだね。
すかじい
function Main() 部分で Main()関数を定義しているが、これがメインルーチンの全貌じゃ。
もっとも、今後処理が増えてくると、メインルーチンの中もいろいろと追加が出てくるがの。
そうは言っても、メインルーチンはできるだけシンプルにしておくのがベストじゃ。
ひろちゃん皇帝
なぜシンプルなのがいいの?
すかじい
メインルーチンが何をやっているのか解りやすく書くことが、ソース全体を読みやすくすることに繋がるからじゃ。
メインルーチンでは、関数をどういう順番で呼ぶのか?と言うことのみの処理に集中し、実際の処理は関数の中に書いていく、という作りが解りやすくてベストじゃ。
リナ姫
ということは、今後、このMain()関数からいろいろな関数が呼ばれる処理が追加されるのね?
すかじい
うむ。そういうことじゃ。
さて、ソースの説明を行う前に、イベントドリブンについて話しておこう。
JavaScriptを理解するうえで、重要な概念だ。
ひろちゃん皇帝
イベントドリブン???
すかじい
イベントドリブンとは、操作する人が何かを行った時だけ動作をする仕組みのことじゃ。
ボタンを押した時や、マウスを動かした時、などじゃな。
それ以外の時は、誰かが操作するまでず〜っと待機しておる。
ひろちゃん皇帝
え〜?それだったら、誰かが操作するまでゲームが進まなくなってしまうよ???
ブロックが勝手に落ちてきたりしなくなってしまうよ?
すかじい
いい質問じゃな。
つまりイベントドリブンはボタンが押された時だけ処理をする、というような処理には向いているのじゃが、継続的に処理を行う、ということには向いていないんじゃ。
そこで、setTimeout() という関数を使うことになる。
この関数は、指定した時間ごとに別の関数を呼ぶことができるので、誰かが操作しなくても関数を起動することができるんじゃ。
詳しい使い方は、ソースの説明の中で行うぞ。
では、ソースの説明に移ろう。
先ほど話したMain()関数がどうやって呼ばれるか解るかな?
ひろちゃん皇帝
え〜っと、前回作った初期化用の関数からは呼ばれていないなあ。
あっ!「各ボタンに対する関数」のところに Main() ってのがある!
すかじい
では、その「各ボタンに対する関数」は、どうやって呼ばれるのか解るかな?
リナ姫
それは、「その2」の時にちょっと出てきたわ。
HTML部分の各ボタンのINPUTタグに書かれていて、確かボタンが押された時にその関数が呼ばれるんだったわね?
ひろちゃん皇帝
そっか!それが「イベントドリブン」なんだ!!
すかじい
そのとおりじゃ。
各ボタンのINPUTタグにある「onclick=""」というのが、ボタンが押された時に処理を行うイベントドリブンの正体じゃ。
ちょっと流れを整理してみよう。
まず、最初の方で変数を追加しておるが、その中に「gameflag」という変数があり、Syokika()関数内で false に設定されておる。
これは、現在ゲーム中かどうかを判断するフラグとして使用しており、ゲーム中なら true 、違うなら false になる。
最初はゲームが始まっていないので、初期値は false になる。
次に、「TURN」「LEFT」「RIGHT」「DOWN」のどれかのボタンが押されると、それぞれのボタン用の関数が呼ばれる。
その各ボタン用の関数では、gameflag を見て、ゲームが始まっていない(false)ならゲームが始まったことにし、(true)その後 Main() 関数を呼んでおる。
Main() 関数についてじゃが、ゲームが始まっているかどうかチェックをして、ゲームが始まっている時のみ次の switch 文が実行される。
ひろちゃん皇帝
switch 文って何?
すかじい
if文などのように何かを判断する構文の一つで、switch に指定された値によって、その次の case 〜 break までの間が実行される。
現在は case 文が1つなので解りにくいが、今後 case 文が増えてくると、理解できるじゃろ。
今回追加した mode という変数が、Syokika() 関数で0に設定されているが、0の場合のみ、この case 0:〜 break; が実行されるのじゃ。
今は case 〜 break の間に命令が無いので、何も行われないがな。
リナ姫
一番最後にあるのが、さっき話していた setTimeout() 関数ね?
すかじい
そうじゃ。
window.setTimeout( "Main()", speed );
という書き方になっておるな。
最初の window は、今開いているwindowオブジェクトを表している。難しいので解らなくてもOKじゃ。オブジェクト指向を学べば解るようになるぞ。
setTimeout() 関数は、windowオブジェクトが最初から持っている関数じゃ。自分で作る関数では無いのじゃ。
だから、構文も決まっておる。
window.setTimeout( "Main()", speed ); のように、引数はJavaScriptの構文(文字列)と、その関数を呼ぶまでの待ち時間(数値)じゃ。
今回はJavaScriptの構文として、Main()関数を呼び出す処理が書かれておる。
また、待ち時間の単位は、ミリ秒じゃ。
ひろちゃん皇帝
え〜っと、今回追加した speed 変数は、Syokika() 関数で1000に設定されているから・・・。
次に Main() 関数が呼ばれるのは1秒後ってこと?
すかじい
そのとおり。
自分で自分の関数を呼び出しているから、この関数内で処理がぐるぐる回るのが解るじゃろ。
この Main() 関数を通ると、それ以後は speed の値ごとにMain()関数が呼ばれる、というわけじゃ。
今回のプログラムでは、前回と見た目は変わらないが、ボタンを押すと1秒ごとにMain()関数が呼ばれておるのじゃ。
その5 「次のブロック」を表示しようへ続く・・・
|