Help us understand the problem. What is going on with this article?

【JavaScript】2人プレイのディフェンスゲームを作ってみた

はじめに

JavaScriptでcanvasを使って、2人プレイのディフェンスゲームを作ってみました。

プレイはこちらから→ディフェンスゲーム

環境

  • Windows 10 home
  • Google Chrome

ルール

2人プレイのゲームになります。
黄色の玉が画面右から左へ移動します。
画面左まで移動したときに、HPが減っていき、HPが0になるとゲーム終了です。
プレイヤー1と2は黄色の玉が画面の左へ移動するのを阻止する必要があります。
プレイヤー1は赤色の玉、プレイヤー2は青色の玉をそれぞれ操作し、黄色の玉に当たることで、黄色の玉を消すことができます。
このようにして、黄色の玉の移動を阻止していきましょう!
また、それぞれ黄色の玉に当たると得点も付くようにしているので、協力し合うことも、対戦で遊ぶこともできます。

操作方法

1P 矢印キーでの移動
上に移動
下に移動
右に移動
左に移動
2P WASDキーでの移動
W 上に移動
S 下に移動
A 右に移動
D 左に移動

プログラム

index.html
<style>body{margin:0;}</style>
<canvas class="canvas">
<script>
"use strict";
{
const WIDTH = 1200; //キャンバスの横軸
const HEIGHT = 600; //キャンバスの縦軸
const HTML_CVS = document.querySelector(".canvas"); //キャンバスの領域の取得
const CANVAS = HTML_CVS.getContext("2d"); //キャンバスの描画機能を有効

class Circle{ //円クラス
  constructor(canvas,x,y,r,color){
    this.canvas = canvas;
    this.x = x;
    this.y = y;
    this.r = r;
    this.color = color;
  }

  draw(){ //描画
    this.canvas.beginPath(); //パスの初期化
    this.canvas.fillStyle = this.color;
    this.canvas.arc(this.x,this.y,this.r,0*Math.PI,2*Math.PI,true);
    this.canvas.closePath(); //パスを閉じる
    this.canvas.fill();
  }
}

class Player extends Circle{ //プレイヤークラス
  constructor(canvas,x,y,r,color){
    super(canvas,x,y,r,color);

    this.speed = 20; //プレイヤーの移動の速さ
    this.score = 0; //プレイヤーの得点

    this.up = false;
    this.down = false;
    this.right = false;
    this.left = false;
  }

  move(){ //キー操作での動き
    if(this.up && this.y-(this.r+this.speed)>=0){this.y -= this.speed;}
    if(this.down && this.y+(this.r+this.speed)<=HEIGHT){this.y += this.speed;}
    if(this.right && this.x+(this.r+this.speed)<=WIDTH){this.x += this.speed;}
    if(this.left && this.x-(this.r+this.speed)>=0){this.x -= this.speed;}
  }

  toEnemyDistance(enemy){ //敵との距離を算出
    return Math.sqrt((enemy.x-this.x)**2+(enemy.y-this.y)**2);
  }
}

class Enemy extends Circle{ //敵クラス
  constructor(canvas,x,y,r,color){
    super(canvas,x,y,r,color);
    this.y = Math.floor(Math.random()*(HEIGHT-this.r*2))+this.r;
    this.speed = 12;
  }

  move(){ //右から左への動き
    if(this.x > 0+this.r){
      this.x -= this.speed;
    }
  }
}

class ScoreLabel{
  constructor(canvas){
    this.canvas = canvas;
    this.x = 10;
    this.y = 40;
    this.hp = 20;
  }

  draw(p1,p2){
    this.canvas.fillStyle = "white";
    this.canvas.font = "30px Arial";
    this.canvas.fillText("hp : "+this.hp +" / P1 : "+p1.score+" / P2 : "+p2.score,this.x,this.y);
  }
}

class Game{
  constructor(){
    HTML_CVS.width = WIDTH;
    HTML_CVS.height = HEIGHT;

    this.PlayerRadius = 60; //プレイヤーの玉の半径
    this.EnemyRadius = 10; //敵の玉の半径
    this.frameRate = 50; //フレーム数
    this.timeCounter = 0; //タイムカウンタ
    this.intervalTime = 0.2; //敵の生成間隔時間
    this.gameflag = true;

    this.player1 = new Player(CANVAS,this.PlayerRadius,this.PlayerRadius,this.PlayerRadius,"red"); //1P
    this.player2 = new Player(CANVAS,this.PlayerRadius,HEIGHT-this.PlayerRadius,this.PlayerRadius,"blue"); //2P
    this.enemy = [];
    this.scoreLabel = new ScoreLabel(CANVAS);

    window.setInterval(()=>{ //ループ処理(フレーム数はFRAME_RATE)
      CANVAS.fillStyle = "black";
      CANVAS.fillRect(0,0,WIDTH,HEIGHT) //キャンバスを描画

      if(this.gameflag){
        this.player1.draw(); //プレイヤー1の描画
        this.player1.move(); //プレイヤー1の動き

        this.player2.draw(); //プレイヤー2の描画
        this.player2.move(); //プレイヤー2動き


        for(let i=0;i<this.enemy.length;i++){
          this.enemy[i].draw(); //敵の描画
          this.enemy[i].move(); //敵の動き
          if(this.enemy[i].x <= 0+this.enemy[i].r){
            this.enemy.splice(i,1);
            this.scoreLabel.hp--;
          }
          if(this.player1.toEnemyDistance(this.enemy[i])<=this.player1.r+this.enemy[i].r){ //距離による当たり判定
            this.enemy.splice(i,1);
            this.player1.score++;
            continue;
          }
          if(this.player2.toEnemyDistance(this.enemy[i])<=this.player2.r+this.enemy[i].r){ //距離による当たり判定
            this.enemy.splice(i,1);
            this.player2.score++;
            continue;
          }
        }
        this.timeCounter++;

        if(this.timeCounter % (this.frameRate*this.intervalTime) == 0){
          this.enemy.push(new Enemy(CANVAS,WIDTH-this.EnemyRadius,HEIGHT/2,this.EnemyRadius,"yellow"));
        }

        this.scoreLabel.draw(this.player1,this.player2);
        if(this.scoreLabel.hp <= 0){this.gameflag=false;}
        }else{alert("ゲームオーバー!");} //アラートでゲームオーバーを表示

    },1000/this.frameRate);

    window.addEventListener("keydown",()=>{ //キーボードのキーを押したときに処理
      if(event.keyCode==38){this.player1.up=true;} //上矢印キー
      if(event.keyCode==40){this.player1.down=true;} //下矢印キー
      if(event.keyCode==39){this.player1.right=true;} //右矢印キー
      if(event.keyCode==37){this.player1.left=true;} //左矢印キー

      if(event.keyCode==87){this.player2.up=true;} //Wキー
      if(event.keyCode==83){this.player2.down=true;} //Sキー
      if(event.keyCode==68){this.player2.right=true;} //Dキー
      if(event.keyCode==65){this.player2.left=true;} //A印キー
    });

    window.addEventListener("keyup",()=>{ //キーボードのキーを離したときに処理
      if(event.keyCode==38){this.player1.up=false;} //上矢印キー
      if(event.keyCode==40){this.player1.down=false;} //下矢印キー
      if(event.keyCode==39){this.player1.right=false;} //右矢印キー
      if(event.keyCode==37){this.player1.left=false;} //左矢印キー

      if(event.keyCode==87){this.player2.up=false;} //Wキー
      if(event.keyCode==83){this.player2.down=false;} //Sキー
      if(event.keyCode==68){this.player2.right=false;} //Dキー
      if(event.keyCode==65){this.player2.left=false;} //Aキー
    });
  }
}

new Game(); //ゲーム開始
}
</script>

以上で終了です!
ここまで読んでいただき、ありがとうございました。

michimichix521
情報学を専攻している大学4年生です。ブロックチェーン技術と教育工学に関する研究をしています。ものづくり(プログラミング)の楽しさを教えるアルバイトをしています。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした