スポンサーリンク

【JavaScript】シューティングゲームを作り方①【初学者向け】

javascript
「javaScriptでシューティングゲームを作りたいけど、説明がどれも難しい…

シューティングゲーム、インベーダー・グラディウス・東方projectの弾幕STGなど様々な種類があり大変楽しいものです。

…ですが「基本を理解した上で解説しますが~」など初学者にとって難しい解説記事が多いのが現実です。

当記事は「初学者向け」「できるだけ丁寧に解説」が目標です。
理解の助けになれば幸いでございますので、よろしくお願いいたします。

gddfgf筆者
・独学でゲームを作っている男
・javascriptが大好きな男

概要

できるだけ丁寧な解説の為、パート分けをしています。パート毎に分けておりますが、どの回も「完成品の確認⇒コードの解説」の流れで進みます。

各回の一覧はこちら⇩

・第1回(今回)
・第2回(キーを押したら弾を発射できる自機)
・第3回(敵機を画面に表示する)
・第4回(敵機の弾を発射できる)
・第5回(弾が衝突したら自機/敵機を消す)

完成品の確認

この記事では、マウスで移動できる自機を作るまでが目標です。

マウスをのせて動かすと、自機である■(四角)が動きます。
早速コードを見ていきましょう!

index.html

<html>
    <head>
        <style>canvas {border: 1px solid gray;}</style>
    </head>
    <body>
        <canvas id="screen"></canvas>
        <p id="info"></p>
    </body>
</html>

ここでは『Canvas・pにidをふってる。後で使うんだな』だけ理解いただければ大丈夫です。

Canvasの中に自機・敵機・弾などを描画します。
pタグの中にはメッセージを反映させていきます。

main.js

// - 変数 - //
var Canvas;
var info;
var ctx;
var Run = true;
var mouse = new Point();

// - クラス - //
// Character
function Character(){
this.position = new Point();
this.size = 0;
}

Character.prototype.init = function(size){
this.size = size;
};

// Point
function Point(){
this.x = 0;
this.y = 0;
}

// - メイン - //
window.onload = function(){

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

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

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

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

// 自機初期化
var chara = new Character();
chara.init(10);

// 画面を繰り返し呼び出す
(function(){
// HTMLを更新
info.innerHTML = mouse.x + ' : ' + mouse.y;

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

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

// 自機の位置を設定
chara.position.x = mouse.x;
chara.position.y = mouse.y;

// 自機を描くパスを設定
ctx.rect(chara.position.x, chara.position.y,30,30);

// 自機の色を設定する
ctx.fillStyle = "black";

// 自機を描く
ctx.fill();

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


// 関数
function mouseMove(event){
// マウスカーソル座標の更新
mouse.x = event.clientX;
mouse.y = event.clientY;
}

function keyDown(event){
// キーコード取得
var ck = event.key;

// spaceKeyで画面が止まる
if(ck === " "){Run = false;}
}

今回の主役、javascriptのコードについて解説していきます。
ポイントは以下3つ

・変数
・クラス
・メインループ

まずは分かりやすい変数から見て行きましょう。

変数

// - 変数 - //
var Canvas; //canvas 取得
var info;  //p 取得
var ctx;  //2Dcontext⇒自機を描画するため
var Run = true;      //ゲームを停止する or しない
var mouse = new Point(); //マウスの座標取得

htmlのcanvasp を参照するための変数Canvasinfoのほかに3つ変数があります。
それぞれの解説はこちら⇩

・ctx:2Dcontext 自機を描画する
・Run = true   ゲームを停止する or しない
・mouse = new Point() マウスの座標取得

この中でmouse = new Point()は、マウスカーソルの座標位置を格納するためのインスタンスです。

mouse = new Point()

//38行目「Canvas内でマウスが動く⇒関数mouseMoveが発動」
Canvas.addEventListener('mousemove', mouseMove)

//60行目「クラスcharaのthis.positionを呼び出す ⇒ chara.x = mouse.x になる」
chara.position.x = mouse.x

//81行目「mouse.x はclientX(左上から見て、今どの座標にいるのか)と同値になる」
 mouse.x = event.clientX;

x座標を取得する処理だけを抜粋していますので、一度順番に読んでみてください。
コメントにjavascriptの中の〇〇行目と追記してます。

処理のゴールは「マウスの現在位置(=clientX)とmouse.xとchara.position.xを同じ値にする」です。

clientXについてはこちらの画像がイメージしやすいと思います。

続いて、Point()を含む2つ分のクラスについて見てみましょう。

クラス

// - クラス - //
// Point
function Point(){
this.x = 0;
this.y = 0;
}
// Character
function Character(){
this.position = new Point();
this.size = 0;
}

Character.prototype.init = function(size){
this.size = size;
};

Point():x/y それぞれの座標情報を格納するためのクラスです。
Character():自機について以下の処理をするためのクラスです。

・位置管理
・サイズ(=大きさ)

位置管理については、mouse = new Point()の説明を参照ください。

サイズは、
コンストラクタで0に初期化します。
prototype.initというメソッドで、引数としてサイズを受け取り、設定されるように作成しています。

prototypeの使用方法はこちらで詳しく解説しておりますので、あわせてご参考下さい。
【JavaScript】prototypeの使い方を初学者向けに解説

メインループ

// - メイン - //
window.onload = function(){

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

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

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

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

// 自機初期化
var chara = new Character();
chara.init(10);

// 画面を繰り返し呼び出す
(function(){
// HTMLを更新
info.innerHTML = mouse.x + ' : ' + mouse.y;

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

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

// 自機の位置を設定
chara.position.x = mouse.x;
chara.position.y = mouse.y;

// 自機を描くパスを設定
ctx.rect(chara.position.x, chara.position.y,30,30);

// 自機の色を設定する
ctx.fillStyle = "black";

// 自機を描く
ctx.fill();

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


// ----- event -----
function mouseMove(event){
// マウスカーソル座標の更新
mouse.x = event.clientX;
mouse.y = event.clientY;
}

function keyDown(event){
// キーコード取得
var ck = event.key;

// spaceKey フラグとまる
if(ck === " "){Run = false;}
}

70行近くのコードですが、2つに分かれて考えましょう。

・「画面を開いたら~しろ」を意味する:「=window.onload = function()」
・関数:mouseMove(event)とfunction keyDown(event)

上から準備に見ていきましょう。

スクリーンの初期化~自機の初期化

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

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

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

// html要素取得
info = document.getElementById('info');

// 自機初期化
var chara = new Character();
chara.init(10);

スクリーンの初期化はCanvasの横と縦の大きさを256と指定しています。

2dコンテキストはcanvasの中で線・図形(□や〇)を描画する時に使う準備です。

イベントの登録・html要素取得で「マウス動かしたら~」「キーを押したら~」の登録
自機初期化でインスタンスcharaを作成、大きさをinit(10)と指定します。

function(){}で画面を繰り返し呼び出す

// 画面を繰り返し呼び出す
(function(){
// HTMLを更新
info.innerHTML = mouse.x + ' : ' + mouse.y;

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

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

// 自機の位置を設定
chara.position.x = mouse.x;
chara.position.y = mouse.y;

// 自機を描くパスを設定
ctx.rect(chara.position.x, chara.position.y,30,30);

// 自機の色を設定する
ctx.fillStyle = "black";

// 自機を描く
ctx.fill();

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

ゲームを作る際には「1秒に〇〇回」「画面を更新して」「キャラクターが」「動いたり」「消えたり」するように見せる処理が必要です。

このような画面を繰り返し呼び出す では再帰的処理を行い、これを実現します。

//47~71行目
(function(){
////ここに何回も繰り返したい処理を入れる////

//72行目「もしrun=trueなら、1000/30の間隔で、上記の処理を繰り返し発動しなさい」
if(run){setTimeout(arguments.callee, 1000/30);} })(); }

arguments.callee()は「今、処理が進んでいる関数を参照する」の理解で大丈夫です。
これでRun=falseにならない限り、ゲームプレイを継続(=処理を継続)できます。

ここにHTMLを更新screenクリアパスの設定を開始自機を描くを入れることで自機や敵機が動くように見せることができます。

関数

// 関数
function mouseMove(event){
// マウスカーソル座標の更新
mouse.x = event.clientX;
mouse.y = event.clientY;
}

function keyDown(event){
// キーコード取得
var ck = event.key;

// spaceKey フラグとまる
if(ck === " "){Run = false;}
}

最後は関数の登録を2つだけ!もう少しだけ頑張りましょう!

function mouseMove(event)では、マウスカーソル座標の更新を行っています。
Client.X/Yを使うことでCanvas内の座標を取得することができます。

function keyDown(event)では、キーコード取得・spaceKeyで画面が止まるがやりたいことです。

(ck === ” “)の” “は「入力したものがスペースキーだったら」という意味です。スペースキーだったら{Run = false}で処理が止まるようになっています。

自分の好きなキーで設定したい方をこちらを活用ください。
keyCode一覧URL

    まとめ

    最後にポイントをおさらいしましょう。

    ①html:要素を2つ設定するだけ
    ②変数:Canvasを使用する準備・Point()でインスタンスを作成
    ③クラス:Point()で座標・Characterで自機サイズを設定
    ④関数:「マウスを動かしたら」「スペースキーを押したら」の為の関数

    ①②③全てに関係する「クラス」はゲームを作る時に特に便利な機能です。
    当記事がjavascriptでゲームを作ったりする時の理解の助けになれば幸いです。

    また、初学者向けのゲームの作り方と一行づつのコード解説をしております。
    【JavaScript】 15パズルの作り方を初学者向けに1行づつ解説![前編]【ゲーム】

    ゲームを作るのはとても勉強になりますし、モチベーション維持にもつながります。
    興味があればご活用ください。

    javascript
    スポンサーリンク
    笑いを愛する