スポンサーリンク

【JavaScript】シューティングゲームの作り方③⇒④の補足

javascript

※※※当記事は⇩第4回の補足となります※※※

・第1回(マウスで移動できる自機)
・第2回(キーを押したら弾を発射できる)
・第3回(敵機を画面に表示する)
・第3⇒4回への補足 コピペ用 コード一覧
・第4回(敵機の弾を発射できる)
・第5回(弾が衝突したら自機/敵機を消す)

当記事の内容

本記事では、第3回⇒第4回にコードの追加部分を説明します。
追加は8か所で⓪~⑦と下のように記載しています。

// 第4回で追加した箇所 ⓪//
var Enemy_Shot_Count = 100;
// 第4回で追加した箇所 ⓪//

当記事の活用方法

【// 第4回で追加した箇所 ⓪//】と囲まれた箇所が第4回で追加されたところです。
⓪~⑦の大体の場所はこちら

⓪:0~12行目
①:38~58行目
②:97~99行目
③:119~122行目
④:154~194行目
⑤:231~237行目
⑥:353~369行目
⑦:382~411行目

目印になれば幸いですm(__)m
早速ですが、第3回のコードを確認できた方は↓をコピペしていきましょう。

第4回で追加されたコード全文

// - 変数 - //
var Canvas;
var info;
var ctx;
var Run = true;
var mouse = new Point();
var fire = false;
var Chara_Shot_Count = 10;
var Enemy_Count = 10;
// 第4回で追加した箇所 ⓪//
var Enemy_Shot_Count = 100;
// 第4回で追加した箇所 ⓪//
var counter = 0;
var position = new Point();
var i;
var j;


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


Chara.prototype = {
  init:function(size){
  //サイズ設定
    this.size = size;
 }
}


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


// 第4回で追加した箇所 ①//
Point.prototype.distance = function(p){
var q = new Point();
q.x = p.x - this.x;
q.y = p.y - this.y;
return q;
};


Point.prototype.length = function(){
return Math.sqrt(this.x * this.x + this.y * this.y);
};


Point.prototype.normalize = function(){
var i = this.length();
if(i > 0){
var j = 1 / i;
this.x *= j;
this.y *= j;
}
};
// 第4回で追加した箇所 ①//


function Chara_Shot(){
    this.position = new Point();
    this.size = 0;
    this.speed = 0;
    this.alive = false;
}


Chara_Shot.prototype = {
    set:function(position,size,speed){
    //座標
      this.position.x = position.x
      this.position.y = position.y
     //サイズ
      this.size = size;
      //スピード
      this.speed = speedF;
          
    // 生存フラグを立てる
    this.alive = true;
    },


   move:function(){
    // 座標を真上にspeed分だけ移動
    this.position.y -= this.speed;


    // 一定以上の座標に到達⇒false
    if(this.position.y < -this.size){
        this.alive = false;
    }
   }
};


// Enemy
function Enemy(){
    this.position = new Point();
    this.size = 0;
    this.type = 0;
// 第4回で追加した箇所 ②//
    this.param = 0;
// 第4回で追加した箇所 ②//
    this.alive = false;
}


Enemy.prototype = {
  //setメソッド
  set:function(position,size,type){
    // 座標
    this.position.x = position.x;
    this.position.y = position.y;


    // サイズ
    this.size = size;


    // 生存フラグを立てる
    this.alive = true;


    // タイプ
  this.type = type;
    
// 第4回で追加した箇所 ③//
    // パラメーター
  this.param = 0;
// 第4回で追加した箇所 ③//
},


  //moveメソッド
  move:function(){
     // パラメータ インクリメント
    this.param++;
    
    // タイプに応じて分岐
    switch(this.type){
        case 0:
            // X方向 に進む
            this.position.x += 2;


            // 画面右端~左端に到達⇒生存フラグを降ろす
            if(this.position.x > this.size + Canvas.width){
                this.alive = false;
            }
            break;
        case 1:
            // マイナスX方向 に進む
            this.position.x -= 2;


            // 画面左端~右端に到達⇒生存フラグを降ろす
            if(this.position.x < -this.size){
                this.alive = false;
            }
            break;
    }
 }
};


// 第4回で追加した箇所 ④//
function EnemyShot(){
this.position = new Point();
this.vector = new Point();
this.size = 0;
this.speed = 0;
this.alive = false;
}


EnemyShot.prototype.set = function(p, vector, size, speed){
// 座標
this.position.x = p.x;
this.position.y = p.y;
  // ベクトル
  this.vector.x = vector.x;
this.vector.y = vector.y;


// サイズ
this.size = size;
  //スピード
this.speed = speed;
// 生存フラグを立てる
this.alive = true;
};


EnemyShot.prototype.move = function(){
// 座標をベクトルに応じてspeed分だけ移動させる
this.position.x += this.vector.x * this.speed;
this.position.y += this.vector.y * this.speed;


// 上下左右の端に到達したら生存フラグを降ろす
if(
   this.position.x < -this.size ||
   this.position.y < -this.size ||
   this.position.x > this.size + Canvas.width ||
   this.position.y > this.size + Canvas.height
){
this.alive = false;
}
};
// 第4回で追加した箇所 ④//


// - メイン - //
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);
  Canvas.addEventListener('mousedown', mouseDown);


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


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


    //自機ショット 初期化
  var charaShot = new Array(Chara_Shot);
 for(i = 0; i < Chara_Shot_Count; i++){
    charaShot[i] = new Chara_Shot();
}
  
  // 敵機 初期化
  var enemy = new Array(Enemy_Count);
for(i = 0; i < Enemy_Count; i++){
    enemy[i] = new Enemy();
}
  
// 第4回で追加した箇所 ⑤//
   // 敵機ショット 初期化 
  var enemyShot = new Array(Enemy_Shot_Count);
for(i = 0; i < Enemy_Shot_Count; i++){
enemyShot[i] = new EnemyShot();
}
// 第4回で追加した箇所 ⑤//
  
 // 画面を繰り返し呼び出す
    (function(){


      // カウンタをインクリメント
counter++;
      
        // 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();      
          
// fireフラグ trueなら処理が進む
if(fire===true){
    // すべての自機ショットを調査する
    for(i = 0; i < Chara_Shot_Count; i++){
        // 自機ショットが既に発射されているかチェック
        if(charaShot[i].alive === false){
            // 自機ショットを新しくセット
            charaShot[i].set(chara.position, 5, 10);


            // ループ抜ける
            break;
        }
    }
    // フラグをfalseにする
    fire = false;
}
         
// パスの設定を開始
ctx.beginPath();


// すべての自機ショット(=10)を調べる
for(i = 0; i < Chara_Shot_Count; i++){
    // 自機ショットが既に発射されているかチェック
    if(charaShot[i].alive===true){
        // 自機ショットを動かす
        charaShot[i].move();


        // 自機ショットを描くパスを設定
        ctx.arc(
            charaShot[i].position.x,
            charaShot[i].position.y,
            charaShot[i].size,
            0, Math.PI * 2, false
        );


        // パスをセーブ
        ctx.closePath();
    }
}


// 自機ショットの色を設定する
ctx.fillStyle = "red";


// 自機ショットを描く
ctx.fill();
      
// 100フレームに1度敵機を出現
if(counter % 100 === 0){
 // すべてのエネミー(=10)を調べる
    for(i = 0; i < Enemy_Count; i++){
     // エネミーが既に10体出現したかチェック
        if(!enemy[i].alive){
      // タイプを決定する
            j = (counter % 200) / 100;


           // タイプから初期位置を決める
            var enemySize = 15;
            position.x = -enemySize + (Canvas.width + enemySize * 2) * j;
            position.y = Canvas.height / 2;


            // エネミーを新規作成
            enemy[i].set(position, enemySize, j);


            // 1体出現したのでループ抜ける
            break;
        }
    }
}
// パスの設定を開始
ctx.beginPath();


 // すべての敵機(=10)を調べる
for(i = 0; i < Enemy_Count; i++){
// 敵機が既に10機出現したかチェック
if(enemy[i].alive){
// 敵機を移動
enemy[i].move();


// 敵機(=○)を描くパスを設定
ctx.arc(
enemy[i].position.x,
enemy[i].position.y,
enemy[i].size,
0, Math.PI * 2, false
);
        
     // 第4回で追加した箇所 ⑥//
// ショットを打つかどうかパラメータの値からチェック
if(enemy[i].param % 30 === 0){
// エネミーショットを調査する
for(j = 0; j < 100; j++){
if(enemyShot[j].alive === false){
// エネミーショットを新規にセットする
position = enemy[i].position.distance(chara.position);
position.normalize();
  enemyShot[j].set(enemy[i].position, position, 5, 5);


              // 1個出現させたのでループを抜ける
break;
}
}
}
     // 第4回で追加した箇所 ⑥//
        
// パスを閉じる
ctx.closePath();
}
}


// 敵機の色を設定する
ctx.fillStyle = "green";


// 敵機を描く
ctx.fill();
     
  // 第4回で追加した箇所 ⑦//
// パスの設定を開始
ctx.beginPath();


// すべてのエネミーショットを調査する
for(i = 0; i < Enemy_Shot_Count; i++){
// エネミーショットが既に発射されているかチェック
if(enemyShot[i].alive){
// エネミーショットを動かす
enemyShot[i].move();


// エネミーショットを描くパスを設定
ctx.arc(
enemyShot[i].position.x,
enemyShot[i].position.y,
enemyShot[i].size,
0, Math.PI * 2, false
);


// パスをいったん閉じる
ctx.closePath();
}
}


// エネミーショットの色を設定する
ctx.fillStyle = "red";


// エネミーショットを描く
ctx.fill();
  // 第4回で追加した箇所 ⑦//
      
        // フラグにより再帰呼び出し
        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;}
}


function mouseDown(event){
    // フラグを立てる
    fire = true;
}

コードをコピペが終わったら

お疲れ様でした…!
400行以上のコードでコピペするもの大変だったかと思います。


コピペできたら↑のように動くはずです。
そのまま第4回(敵機の弾を発射できる)に進んでいただければと思います。

コードや説明順序が前後しますが何卒よろしくお願いいたします。