JavaScript

[連載] javascriptで作るシューティングゲーム的な何か(2)

More than 3 years have passed since last update.

さあ、はじめよう

はじめに

本稿は掲題の通り javascript を用いて[ シューティングゲーム的な何か ]を作ろうという試みについて解説するテキストの第二回です。

想定する読者

  • 割と暇である
  • プログラミングに興味がある
  • ゲーム作りに興味がある
  • javascriptの基本をマスターしたけど特に作るものがない
  • javascriptを使った動きのある処理を実装してみたい
  • canvas でなんか作ってみたい

本連載の狙い

本連載はどちらかというと初心者向けです。
このページに検索からやってきた「ゲーム作りてえええええ」と日に三十回くらい叫んでいる小中学生諸君は、まずjavascriptの基本をお勉強してから本連載を読みましょう。
また、最終的に出来上がる[ シューティングゲーム的な何か ]は、そんなに大層なものではありません。シューティングゲームがどのような感じで作られていくのか、その過程を眺めていろいろ考えていただくキッカケを作ることが本連載の狙いです。

また、本連載では伝わりやすさ優先でテキストを書きます。たとえば javascript には厳密にはクラスはありませんが、連載内でクラスという言葉を使って解説します。このあたりは理解しやすさや、雰囲気を伝えることを優先して書きます。

オンラインサンプル

本連載は全10回を予定しています。
各回にはその時点までの[ シューティングゲーム的な何か ]のサンプルが付属します。
各テキストからリンクを張っておきますので、オンラインで実際に動作確認が行えます。
サンプルプログラム一式については著作権とかライセンスとかそういったものは一切ありません。

ちなみに、最終的に完成する[ シューティングゲーム的な何か ]はこんな感じです。
マウスによる移動、クリックによるショットが可能です。ESC キーでプログラムを停止します。

javascriptで作るシューティングゲーム的な何か(1)
javascriptで作るシューティングゲーム的な何か(2)
javascriptで作るシューティングゲーム的な何か(3)
javascriptで作るシューティングゲーム的な何か(4)
javascriptで作るシューティングゲーム的な何か(5)
javascriptで作るシューティングゲーム的な何か(6)
javascriptで作るシューティングゲーム的な何か(7)
javascriptで作るシューティングゲーム的な何か(8)
javascriptで作るシューティングゲーム的な何か(9)
javascriptで作るシューティングゲーム的な何か(最終回)

書いてる人

書いてる人はdoxasという人です。
こんな企画もやってますので、少しでも javascript でシューティングゲームを作成することに興味がわいたら、ぜひ参加してください。待ってますよ!!

さて、つくろう

サンプルの実行結果
sample_002.jpg

前回はマウスカーソルの座標位置を検知して、リアルタイムに HTML に反映させるところまでやりました。
今回は、そのマウスカーソルの位置に、実際にキャラクターに見立てた図形を描いてみます。

canvas2d

canvas に対して図形を描くためには、canvas2d コンテキストについて知る必要があります。
簡単に説明すると、canvas2d コンテキストとは、canvas 上に任意の図形や文字、あるいは読み込んだ画像などを描くことができるオブジェクトです。
javascript から canvas2d を操ることで、canvas 上に様々なものを描き出すことができ、これを動的に動かすことでゲームを作ることもできるわけです。

canvas に関してはCanvas - HTML5.JPで非常に詳しく解説されていますので、参考にしましょう。
本連載では、登場するものに対しては最低限の解説はしますが、あまり突っ込んだ詳細には触れませんのであしからず。

canvas2d コンテキストの取得

それでは実際に canvas2d を使った処理を見ていきます。
基本的には前回のコードを踏襲して追記するという形になります。また、今回は index.html と common.js には修正はありません。すべての修正は main.js に対してのみです。

main.js の冒頭、グローバルな変数として canvas2d コンテキストを格納するためのコードを追加します。

main.jsグローバル変数宣言部分を抜粋
var screenCanvas, info;
var run = true;
var fps = 1000 / 30;
var mouse = new Point();
var ctx; // canvas2d コンテキスト格納用

変数ctxが追加されました。この変数に canvas2d コンテキストを取得します。
取得に際しては、canvas への参照を持っている変数screenCanvasgetContextというメソッドを利用します。このメソッドの引数に 文字列で '2d' を渡してやります。

canvas2dコンテキストを取得する記述例
ctx = screenCanvas.getContext('2d');

canvas2d コンテキストに対応していないブラウザもあるため、正しく canvas2d コンテキストが取得できたのかをチェックする仕組みを設けるのが普通です。
本連載では省略しますが、Canvas - HTML5.JP等を見れば詳細がわかるでしょう。

メインのプログラムを修正する

さて、それでは前項で紹介した canvas2d コンテキストの取得を含む、修正版のコードを見てみます。
main.js のなかの修正があった部分だけを抜粋します。

main.js追記箇所だけを抜粋
window.onload = function(){

    // スクリーンの初期化
    screenCanvas = document.getElementById('screen');
    screenCanvas.width = 256;
    screenCanvas.height = 256;

    // 2dコンテキスト
    ctx = screenCanvas.getContext('2d');

    // イベントの登録
    screenCanvas.addEventListener('mousemove', mouseMove, true);
    window.addEventListener('keydown', keyDown, true);

    // その他のエレメント関連
    info = document.getElementById('info');

    // レンダリング処理を呼び出す
    (function(){
        // HTMLを更新
        info.innerHTML = mouse.x + ' : ' + mouse.y;

        // screenクリア 
        ctx.clearRect(0, 0, screenCanvas.width, screenCanvas.height);

        // パスの設定を開始
        ctx.beginPath();

        // 円の色を設定する
        ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';

        // 円を描くパスを設定
        ctx.arc(mouse.x, mouse.y, 10, 0, Math.PI * 2, false);

        // 円を描く
        ctx.fill();

        // フラグにより再帰呼び出し
        if(run){setTimeout(arguments.callee, fps);}
    })();
};

スクリーンの初期化が終了したあと、canvas2d コンテキストを取得するコードが追加されています。これは先ほど説明した部分です。

そのあと、無名関数を呼び出している部分で、大きく追記が行われています。大まかに流れを説明すると、以下のようになります。

  • canvas をリセットするために一度クリアする
  • パスの設定開始を宣言
  • 色を決める
  • パスを設定して形を決める
  • canvas に描く

一番最初の canvas のリセットにはclearRectメソッドを使います。
このメソッドは引数を四つ指定します。第一、第二引数はクリアする領域の 左上角 の座標です。今回のサンプルの場合は canvas 全体をクリアしたいので共に 0 が指定されています。
第三、第四引数は、クリアする領域の 幅と高さ です。これらの引数はいずれもピクセル単位で指定します。

clearRectメソッド
ctx.clearRect(0, 0, screenCanvas.width, screenCanvas.height);

左上角の座標は言うまでもなく 0 ですね。そして幅と高さは先ほど canvas に対して設定した幅と高さがそのまま使えますね。

パスとはなんぞや

canvas2d においては、図形を描くために パス という概念を理解しておく必要があります。

パスというのは、わかりやすく言うと 下書き みたいなもので、canvas2d でなにか図形を描く際にはまず最初にパスでどこにどんな図形を描きたいのか指定してやり、パスの設定が終わったら描くための命令を発行してやります。
パスを設定する際には、まずパスの設定を開始しますよ! と宣言してやります。続けて好きなようにパスを設定し、パスの設定が終わったら描画命令を出して一気に canvas 上に図形を描きます。

ここまでを理解したうえで、先ほどのコードから該当部分だけを抜粋した箇所を見てみましょう。

パス関連の処理抜粋
        // パスの設定を開始
        ctx.beginPath();

        // 円の色を設定する
        ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';

        // 円を描くパスを設定
        ctx.arc(mouse.x, mouse.y, 10, 0, Math.PI * 2, false);

        // 円を描く
        ctx.fill();

パスの設定を開始する際には、必ずbeginPathメソッドをコールします。引数はありません。
これは簡単ですね。

どのようなパスを設定するのかは任意に決めることが可能です。代表的なパスの形状には、一直線のラインや、矩形、円形などがあります。これらのパスの設定について詳細が知りたい場合にはCanvas - HTML5.JPが非常に参考になります。

本連載では円形のみを使っていきます。
いろいろな図形を使ってもいいのですが、わかりやすさ重視でいきます。

円形を描くパスの設定にはarcメソッドを使います。引数がちょっと多いですが、円を描きたい場合には下記のサンプルコードを参考にしてください。重要なのは、第一、第二、そして第三引数までの指定の仕方です。

arcメソッド
ctx.arc(mouse.x, mouse.y, 10, 0, Math.PI * 2, false);

第一引数、そして第二引数には 円の中心部分の座標 を指定します。そして、第三引数がその円の 半径 です。
つまり上記の記述例のようにすると、マウスカーソルの位置を中心とした半径 10 の円が描かれるパスを設定できます。
その他の引数の解説はしませんが、そんなに難しくはないので興味がある方は調べてみてください。

パスの設定が済んだら、これで下書きは完成しました。あとは実際にパスどおりに描くように指令を出すだけです。
しかし、このまま描画命令を発行しても、真っ黒い図形が描かれるだけです。どうせなら、好きな色で図形を描きたいですね。

描かれる図形の色を指定する場合にはfillStyleプロパティに色を指定します。このプロパティには CSS の色指定がそのまま使えますので文字列で指定してやります。
たとえばredとしてみたり、本テキストのサンプルのようにrgbaを使った指定も可能です。
ここで指定した色で図形が描かれるわけですが、実際に図形を描くための描画命令となるのがfillメソッドです。

fillStyleプロパティに色を指定してやり、fillメソッドで描画する、という一連の流れになっているわけです。
このメソッドをコールすると、事前に設定してあったパスに、事前に指定してあった色で、図形が描かれるという仕組みになっているわけです。

まとめ

今回のサンプルでは、前回はただ単にマウスカーソルの座標を HTML に出力するだけだったプログラムが、実際に図形を canvas 上に描き出すように変化しました。
シューティングゲームとしては自機の表示ができるようになった、というふうに考えていいと思います。

オンラインサンプル.02で実際に今回のサンプルの動作を確認できます。
canvas 上でマウスカーソルを動かすと、マウスカーソルの位置に円形が描画されるようになっているはずです。