HTML5 を使ったシンプルな 2 D ゲームの作り方 (画像のロード)
2 回前の記事から、去年末に出演した schoo (スクー) さんの授業で使用したサンプルアプリをもとにした、HTML5 を使ったシンプルな 2 D ゲームの作り方を紹介しています。どんなゲームを作るのかは 1 回目の記事の中に実際に動作するゲームが埋め込んであるのでぜひ遊んでみてください。
さて、前回は Visual Studio 2013 でのプロジェクトの作成と必要なファイルの追加方法などを説明しましたが、3 回目となる今回は、いよいよ HTML タグと JavaScript コードを記述していきます。
Visual Studio でのプロジェクトの作成やファイルの追加、ゲームで使用する画像の入手が済んでいない方は、2 回目の記事の内容に従い準備を行ってください。
Canvas のタグの記述
実際のゲームを描画して動かすための Canvas タグを body 内に記述します。
Visual Studio ではコードスニペットという機能により canvas とタイプし、キーボードの [Tab] キーを押下するだけで canvas タグが追加されます。
続けて属性を追加します。以下の各属性を設定してください。
属性 | 値 |
id | bg |
widht | 320 |
heiht | 480 |
style | background-color:black; |
入力中はインテリセンスと呼ばれる入力支援機能が働くので、有効に利用してください。
最終的に canvas タグは以下のようになります。
<canvas id="bg" style="background-color: black" width=”320" height="480">
この Web ブラウザーは Canvas をサポートしていません。
最新のモダンブラウザを使用してください。
</canvas>
Canvas タグ内の文字列は、Canvas をサポートしていないレガシーな Web ブラウザーに表示されます。
この時点での default.html の HTML ソースは以下のようになっています。
<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<link href="css/main.css" rel="stylesheet" />
<script src="js/main.js"></script>
</head>
<body>
<canvas id="bg" height="480" width="320" style="background-color:black;">
この Web ブラウザーは Canvas をサポートしていません。
最新のモダンブラウザを使用してください。
</canvas>
</body>
</html>
Canvas のサイズ指定について
Canvas のサイズ指定は CSS ではなく、必ずタグの属性で指定する必要があります。
それは Canvas の描画領域のサイズは、書式ので指定される「表示されるサイズ」ではなく「描画を行うための領域の確保」だからです。
この描画領域の確保は、ブラウザが Canvas タグを解釈したと同時に行われます。よって、Canvas タグにサイズに対する指定が無いと、Canvas の既定の サイズである width 300px、height 150px で描画領域が確保されます。これに対し、CSS でサイズを指定すると、CSS で指定されたサイズで引き延ばすか圧縮された形になりアスペクト比が同じでない限り意図したとおりに描画されませんので注意が必要です。
例えば以下は、左側の画像が Canvas の width 属性と height 属性でサイズを指定したもの、右側の画像が style 属性で width と height を指定したものです。
右側の画像では、サイズとアスペクト比が意図しないものになっています。
Canvas への画像のロード
前回の記事で追加した画像を Canvas に表示するための JavaScript を記述します。
ソリューションエクスプローラーで js フォルダにある main.js をダブルクリックして開きます。
ネームスペース汚染を防止するおまじない
Canvas についての JavaScript コードを記述する前にネームスペース (名前空間) を汚染しないようにするための記述を行います。
ネームスペースの汚染とは、ライブラリやフレームワークが使用している変数を自分のコードで使用している変数で上書きしてしまうことです。
おまじないのようなものですが、きちんと理解したい方は以下のドキュメントの「名前空間を汚染しないための工夫」をご覧ください。
以下のように即時実行関数を記述し、その中にこれからのコードを記述していきます。
(function () {
//この中にコードを記述していく
})();
今回の紹介するゲームのコードは、ライブラリ等を使用していないので、ネームスペースの汚染をそれほど心配しなくても大丈夫ですが、今後のためにおまじない的に記述する習慣をつけておくことをお勧めします。ただし、これでネームスペースの汚染をすべて防げるわけでもないということも覚えておいてください。(※ ネームスペースの汚染を最小限にする方法もありますが、今回はコードの可読性、わかりやすさを優先するので割愛します。)
プログラム全体で使用する変数の宣言
前の手順で記述した即時実行関数の中に、プログラム (ゲーム) 全体で使用する変数の宣言をします。ここで宣言した変数は、即時実行関数内のどこからでも参照できます。
(function () {
//プログラム全体で使用する変数
var canvas = null;
var ctx = null;
var img_snow = null;
var img_snow_man = null;
})();
画像をロードするめための関数
画像をロードするための loadAssets 関数を記述していきます。
Visual Studio を使用している場合は、func とタイプし キーボードの [Tab] キーを 2 回押下すると myfunction という空の関数が定義されるので、関数名を loadAssets に書き換えます。以下のようになります。
function loadAssets () {
}
loadAssets 関数の中身を以下のように記述します。(コメントは記述しなくて大丈夫です)
Visual Studio が入力を助けてくれるのでぜひタイプして入力してみてください。
//HTML ファイル上の canvas エレメントのインスタンスを取得
canvas = document.getElementById(‘bg');
//2D コンテキストを取得
ctx = canvas.getContext('2d');
//image オブジェクトのインスタンスを生成
img_snow = new Image();
//image オブジェクトに画像をロード
img_snow.src = '/img/snow.png';
/*画像読み込み完了のイベントハンドラーに Canvas に
画像を表示するメソッドを記述 */
img_snow.onload = function () {
//canvas 上で image を描画
ctx.drawImage(img_snow, 0, 0);
};
次に HTML 上のエレメントのロードが完了した際に loadAssets 関数を呼び出すイベントハンドラを記述します。
コンテンツのロード完了時に動作する
イベントハンドラの実装
ページの準備が完了した際に発生するイベントとしては、windows オブジェクトの onload イベントが古くから使用されてきましたが、HTML5 からは DOMContentLoaded が使用できます。DOMContentLoaded イベントは、window.onload イベントと同じく、参照している CSS ファイルなどが読み込まれ、準備完了となった際に発生しますが、DOMContentLoaded イベントが発生するのは純粋に DOM のロード完了についてのみであり、window.onload イベントのように画像ファイルのロード完了までは待ちません。そのため DOMContentLoaded イベントを使用したほうが迅速に DOM への処理を開始することができます。今回の場合は当てはまりませんが、とくに画像の読み込みが遅いページでは、イベント発生までの時間が大きく異なります。
このへんの詳細については以下のドキュメントをご参照ください。
loadAssets 関数を呼び出す DOMContentLoaded イベントハンドラを以下のように記述します。
//DOM のロードが完了したら実行
document.addEventListener("DOMContentLoaded", function () {
loadAssets();
});
main.js ファイル全体の JavaScript コードは以下のようになります。
(function () {
//プログラム全体で使用する変数
var canvas = null;
var ctx = null;
var img_snow = null;
var img_snow_man = null;
//DOM のロードが完了したら実行
document.addEventListener("DOMContentLoaded", function () {
loadAssets();
});
function loadAssets() {
//HTML ファイル上の canvas エレメントのインスタンスを取得
canvas = document.getElementById('bg');
//2D コンテキストを取得
ctx = canvas.getContext('2d');
//image オブジェクトのインスタンスを生成
img_snow = new Image();
//image オブジェクトに画像をロード
img_snow.src = '/img/snow.png';
/*画像読み込み完了のイベントハンドラーに Canvas に
画像を表示するメソッドを記述 */
img_snow.onload = function () {
//canvas 上で image を描画
ctx.drawImage(img_snow, 0, 0);
};
};
})();
Web ページの表示
Visual Studio で Web ページを表示する方法はいくつかありますが、最も基本的な方法は、ソリューションエクスプローラーで Web ブラウザーで表示させるファイルを選択しておき、キーボードの [F5] キーを押下する方法です。
上記の方法のとおり、ソリューションエクスプローラーで default.html を選択し、キーボードの [F5] キーを押下します。
Internet Explorer が起動し、以下のように黒い Canvas の左上に雪の結晶の画像が表示されます。
エラーが発生した場合には、Visual Studio を使用してそのまま JavaScritp のコードをデバッグすることができます。
Vusial Studio のデバッグ機能については以下のドキュメントをご参照ください。
画像の表示位置の調整
画像の表示位置は、context オブジェクトの drawImage メソッドの引数で指定します。
このコードでは context オブジェクトは変数 ctx に格納されており、img_snow.onload イベントハンドラ内で drawImage メソッドを呼び出していますが、横位置(X 座標)、縦位置(Y 座標) を指定する第一、第二引数が両方とも 0 であるため画像が左上端に表示されています。
//canvas 上で image を描画
ctx.drawImage(img_snow, 0, 0);
これを画面の中央に表示するようにしてみましょう。
画像を Canvas の中央に表示するための X 座標は以下の式で求めることができます。
x = (Canvas の幅 / 2) - (画像の幅 /2 )
この式を使用して画像を Canvas の中央に表示するための getCenterPostion 関数を以下のように定義します。
//中央の Left 位置を求める関数
function getCenterPostion(containerWidth, itemWidth) {
return (containerWidth / 2) - (itemWidth / 2);
};
定義した getCenterPostion 関数の第一引数として Canvas の描画領域のサイズ、第二引数として表示する画像のサイズを指定することにより、対象画像を Canvas の中央に表示する際に指定すべき X の値が返ります。
getCenterPostion 関数を使用して img_snow.onload イベントハンドラ内を以下のように書き換えます。
img_snow.onload = function () {
img_snow._x = getCenterPostion(canvas.clientWidth, img_snow.width);
img_snow._y = 0;
//canvas 上で image を描画
ctx.drawImage(img_snow, img_snow._x, img_snow._y);
};
default.html を選択し、キーボードの [F5] キーを押下してページを実行すると、以下のように雪の結晶の画像が中央に配置されます。
雪だるま画像の追加
雪だるまの画像を追加します。やりかたは雪の結晶の画像を追加したのと一緒ですので、該当部分のコードをコピーして貼り付け、変数名 img_snow を img_snow_man に、画像のパスを ‘/img/snow_man.png’ に書き換えます。
具体的には以下のようになります。
//(※) この上 ↑ に雪の結晶画像をロードするコードがある
//雪だるま画像のロード
var img_snow_man = new Image();
img_snow_man.src = '/img/snow_man.png';
img_snow_man.onload = function () {
img_snow_man._x = getCenterPostion(canvas.clientWidth, img_snow_man.width);
img_snow_man._y = 0;
ctx.drawImage(img_snow_man, img_snow_man._x, img_snow_man._y);
};
雪だるま画像は、表示領域の底辺に画像の底辺がつくように配置する必要があります。
その際の Y 座標は、以下の式で求めることができます。
y = Canvas の高さ – 画像の高さ
これの式を使用して雪だるまを描画する img_snow_man.onload イベントハンドラ内を以下のように書き換えます。
img_snow_man.onload = function () {
img_snow_man._x = getCenterPostion(canvas.clientWidth, img_snow_man.width);
//雪だるま画像は、表示領域の底辺に画像の底辺がつくように
img_snow_man._y = canvas.clientHeight - img_snow_man.height;
ctx.drawImage(img_snow_man, img_snow_man._x, img_snow_man._y);
};
default.html を選択し、キーボードの [F5] キーを押下してページを実行すると、以下のように雪だるまの画像が Canvas の中央の底辺に配置されます。
main.js ファイル全体の JavaScript コードは以下のようになります。
(function () {
//全体で使用する変数
var canvas = null;
var ctx = null;
var img_snow = null;
var img_snow_man = null;
//DOM のロードが完了したら実行
document.addEventListener("DOMContentLoaded", function () {
loadAssets();
});
function loadAssets() {
//HTML ファイル上の canvas エレメントのインスタンスを取得
canvas = document.getElementById('bg');
//2D コンテキストを取得
ctx = canvas.getContext('2d');
//image オブジェクトのインスタンスを生成
img_snow = new Image();
//image オブジェクトに画像をロード
img_snow.src = '/img/snow.png';
/*画像読み込み完了のイベントハンドラーに Canvas に
画像を表示するメソッドを記述 */
img_snow.onload = function () {
img_snow._x = getCenterPostion(canvas.clientWidth, img_snow.width);
img_snow._y = 0;
//canvas 上で image を描画
ctx.drawImage(img_snow, img_snow._x, img_snow._y);
};
//雪だるま画像のロード
img_snow_man = new Image();
img_snow_man.src = '/img/snow_man.png';
img_snow_man.onload = function () {
img_snow_man._x = getCenterPostion(canvas.clientWidth, img_snow_man.width);
img_snow_man._y = canvas.clientHeight - img_snow_man.height;
ctx.drawImage(img_snow_man, img_snow_man._x, img_snow_man._y);
};
};
//中央に配置する画像の X 座標を求める関数
function getCenterPostion(containerWidth, itemWidth) {
return (containerWidth / 2) - (itemWidth / 2);
};
})();
まとめ
今回の記事では HTML に Canvas タグを追加し、JavaScript を使用してゲームで使用する画像を表示するところまでを紹介しました。
次回は今回表示した画像にアニメーションを実装していきます。