SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

JavaScriptとCSSによるブロック崩しの作成

スクリプトを利用してHTMLオブジェクトのスタイル属性を動的に変更する


ブロック崩し

 最後に、オブジェクトの絶対位置指定を活用した、より動的なゲームを開発してみましょう。今回は、簡単な仕様のブロック崩しに挑戦します。ブロック崩しは、画面上で移動する小さなボールを、ユーザーがコントロールするバーを使って跳ね返しながら、画面上のブロックに玉を当ててブロックを消していくゲームです。

 ボールは、ユーザーがコントロールするバーやブロックに触れると跳ね返ります。画面の端に触れたときも跳ね返りますが、バーを通り越して画面の下端に玉を取りこぼしてしまった場合はゲームオーバーとなります。

 全てのブロックやバーの位置は絶対位置指定を使ってピクセル単位で設定します。特に、画面上を縦横無尽に動き回るボールを制御するには絶対座標指定が必須となります。

ブロック崩し
<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要素を自由にレイアウトする機能を使えば、このようにゲームの開発に応用することができます。手続きは多少面倒なものでしたが、イメージファイルを自由に画面上に配置できれば多くのゲーム開発の要求に応えることができます。ぜひ、挑戦してみてください。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
特集記事連載記事一覧

もっと読む

この記事の著者

赤坂 玲音(アカサカ レオン)

平成13年度「全国高校生・専門学校生プログラミングコンテスト 高校生プログラミングの部」にて最優秀賞を受賞。2005 年度~ Microsoft Most Variable Professional Visual Developer - Visual C++。プログラミング入門サイト WisdomSoft の管理人。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/311 2006/05/08 10:32

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー