ブロック崩し
最後に、オブジェクトの絶対位置指定を活用した、より動的なゲームを開発してみましょう。今回は、簡単な仕様のブロック崩しに挑戦します。ブロック崩しは、画面上で移動する小さなボールを、ユーザーがコントロールするバーを使って跳ね返しながら、画面上のブロックに玉を当ててブロックを消していくゲームです。
ボールは、ユーザーがコントロールするバーやブロックに触れると跳ね返ります。画面の端に触れたときも跳ね返りますが、バーを通り越して画面の下端に玉を取りこぼしてしまった場合はゲームオーバーとなります。
全てのブロックやバーの位置は絶対位置指定を使ってピクセル単位で設定します。特に、画面上を縦横無尽に動き回るボールを制御するには絶対座標指定が必須となります。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis"> <title>サンプル 05</title> <script language="javascript"> var panelX, panelY, panelWidth, panelHeight; var blocks; var towardX = true; var towardY = true; var MOVE = 3; var FRAMETIME = 10; var gameover = false; function next() { var x, y; x = parseInt(boll.style.left); y = parseInt(boll.style.top); //ボールの移動処理 if (towardX) boll.style.left = x + MOVE; else boll.style.left = x - MOVE; if (towardY) boll.style.top = y + MOVE; else boll.style.top = y - MOVE; //ボールがユーザーのバーに当たったかどうか if (touch(userBlock)) { towardY = false; } //ボールがブロックの当たったかどうか for(var i = 0 ; i < blocks.length ; i++) { if (blocks[i].style.visibility == "hidden") continue; if (touch(blocks[i])) { blocks[i].style.visibility = "hidden"; towardY = true; } } //ボールが壁に当たったかどうか if (x <= panelX) towardX = true; else if(x + boll.width >= panelX + panelWidth) towardX = false; if (y <= panelY) towardY = true; else if(y >= panelY + panelHeight) { //ゲームオーバー gameover = true; } if (!gameover) setTimeout("next()", FRAMETIME); } function touch(block) { var bollX, bollY, blockX, blockY; bollX = parseInt(boll.style.left); bollY = parseInt(boll.style.top); blockX = parseInt(block.style.left); blockY = parseInt(block.style.top); if ( (bollX + boll.width) >= blockX && bollX <= (blockX + block.width) && (bollY + boll.height) >= blockY && bollY <= (blockY + block.height) ) { return true; } return false; } function loaded() { panelX = panel.offsetLeft; panelY = panel.offsetTop; panelWidth = parseInt(panel.style.width); panelHeight = parseInt(panel.style.height); boll.style.position = "absolute"; boll.style.left = panelX + 150; boll.style.top = panelY + 200; userBlock.style.position = "absolute"; userBlock.style.left = panelX + 280; userBlock.style.top = panelY + 450; blocks = Array(); for(i = 0 ; i < 10 ; i++) { blocks[i] = document.all("block" + i); blocks[i].style.position = "absolute"; } var w = panelX + 20; var h = panelY + 10; for(var i = 0 ; i < 10 ; i++) { blocks[i].style.left = w; blocks[i].style.top = h; w += blocks[i].width + 20; if ((w + blocks[i].width) > panelWidth) { w = panelX + 20; h += blocks[i].height + 5; } } next() } function mouseMoved() { var x = event.x - userBlock.width / 2; if (x < panelX) userBlock.style.left = panelX; else if (x + userBlock.width > panelX + panelWidth) userBlock.style.left = panelX + panelWidth - userBlock.width; else userBlock.style.left = x; } </script> </head> <body onLoad="loaded()"> <h1>サンプルプログラム 5</h1> <div style= "background-image=url(back.jpg); width:640px; height]:480px" id="panel" onMouseMove="mouseMoved()"> <img src="boll.jpg" id="boll"> <img src="block.jpg" id="userBlock"> <img src="block.jpg" id="block0"> <img src="block.jpg" id="block1"> <img src="block.jpg" id="block2"> <img src="block.jpg" id="block3"> <img src="block.jpg" id="block4"> <img src="block.jpg" id="block5"> <img src="block.jpg" id="block6"> <img src="block.jpg" id="block7"> <img src="block.jpg" id="block8"> <img src="block.jpg" id="block9"> </div> </body> </html>
ドキュメントが読み込まれると、最初にbody要素のonLoadイベントが発生してloaded()関数を呼び出します。この関数は、ユーザーのバーや各種ブロック、玉を絶対位置指定で初期位置に設定します。最後に、next()関数を呼び出してゲームを開始します。
ゲームは、next()関数を呼び出すごとに玉が次の位置に移動して進みます。玉が流れるように移動するには、極めて短い間隔で、何度もnext()関数を呼び出さなければなりません。これは、windowオブジェクトのsetTimeout()メソッドで行うことができます。このメソッドは、指定した時間が経過した後に指定したコードを実行するというメソッドです。
iTimerID = window.setTimeout(vCode, iMilliSeconds [, sLanguage])
vCodeには、時間が経過した後に呼び出す関数へのポインタを指定するか、または実行するコードを文字列で指定します。iMilliSecondsにはミリ秒単位の数値で、指定したコードを実行するまでの時間を指定します。sLanguageにはスクリプト言語名を "JScript"、"VBScript"、"JavaScript" のいずれかから選択できますが、省略可能です。
vCodeには、通常は時間が経過してから実行するスクリプトコードを文字列で指定します。特に引数などを渡す必要が無い場合は関数へのポインタ(関数名だけ)を指定できますが、古いInternet Explorerでは対応していません。
このメソッドの戻り値は、setTimeoutの設定をキャンセルするときに利用するタイマーIDが返ります。もし、設定したタイマーを解除したい場合はclearTimeout()メソッドで解除してください。
window.clearTimeout(iTimeoutID)
プログラムでは、next()関数が実行されるたびに次に実行するnext()関数をsetTimeout()で設定しています。これによって、ボールはゲームオーバーになるまで永遠と画面内を行き来します。バーはゲームパネル上でマウスカーソルが移動すると、それに合わせて位置を変更します。ボールが画面下部に落ちた時点でゲームオーバーとなります。
ボールが画面上部に配置されているブロックに接触するとブロックは画面から削除されます。この処理は、ブロックオブジェクトのstyle.visibilityプロパティを使って "hidden"、すなわち不可視状態にさせることで実現しています。
最後に
今回はブロック崩しを作りましたが、HTML要素を自由にレイアウトする機能を使えば、このようにゲームの開発に応用することができます。手続きは多少面倒なものでしたが、イメージファイルを自由に画面上に配置できれば多くのゲーム開発の要求に応えることができます。ぜひ、挑戦してみてください。
