ゲームを作りながら学ぶ！JavaScript レベルアップ講座 part6

こんにちは、[Yui](https://twitter.com/yui_active)です。

今回はパーティメンバーのステータスを表示する部分を実装していきたいと思います。
JavaScript道場は[こちら](https://x-hack.connpass.com/event/200502/)。

今回の成果物はこちらです。

![スクリーンショット 2020-11-08 15.17.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670446/4d73ec05-d2a5-4737-aa8a-5dae53081c08.png)


# モンスターを3体表示する

まずは前回の記事を参考にして、モンスターを3体表示します。
ただ、今回から書くJavaScriptの量が増えてくるので、コードをHTML部分とJavaScript部分で分けておきましょう。

名前は何でも良いのですが、例えばgame.jsという名前のファイルを作ります。
そうするとHTML部分は以下のようになります。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Game App</title>
  <script src="game.js" defer></script>
</head>
<body>
  <canvas id="canvas" width="640" height="480" style="background-color: darkgrey;"></canvas>
</body>
</html>
```

game.jsは以下のように書きます。

```javascript:game.js

const canvas = document.getElementById("canvas")
const ctx = canvas.getContext("2d")
class Monster {
  constructor(posX, posY, image) {
    const img = new Image()
    img.src = image
    this.img = img
    this.posX = posX
    this.posY = posY
    this.sizeX = 100
    this.sizeY = 100
    img.onload = () => this.drawImage()
  }
  drawImage() {
    ctx.drawImage(this.img, this.posX, this.posY, this.sizeX, this.sizeY)
  }
}

new Monster(100, 200, "./img/bone.png")
new Monster(260, 200, "./img/pumpkin.png")
new Monster(420, 200, "./img/ghost.png")

```

イメージ画像に関しては今回[こちら](http://mwhidesp.konjiki.jp/a241-270.htm)からお借りしています。
お好きな画像をダウンロードして、今回のアプリのフォルダ内に格納してください。
ここではimgフォルダを新しく作成して、その中にそれぞれ画像を入れているので、URLは上記のようになっています。

ここまでは前回までの復習になりますので、特に解説も不要かと思います。

ただ、**グローバル関数をあまり使うべきではない**ので、``canvas``と``ctx``の定義部分に関してはクラス内に含めておきましょう。

```javascript
class Monster {
  constructor(posX, posY, image) {
    const canvas = document.getElementById("canvas")
    const ctx = canvas.getContext("2d")
    const img = new Image()
...
```

この場合、``drawImage()``内の``ctx.drawImage``に関しては``this.ctx.drawImage``と書かないといけないので注意してください。
もしこの辺のthisの使い方がわからない場合は[こちら](https://qiita.com/Yui_active/private/fa711873d8db71cf9330)の記事を再度ご確認ください。

こうして、game.jsは以下のようになりました。

```javascript:game.js
class Monster {
  constructor(posX, posY, image) {
    const canvas = document.getElementById("canvas")
    this.ctx = canvas.getContext("2d")
    const img = new Image()
    img.src = image
    this.img = img
    this.posX = posX
    this.posY = posY
    this.sizeX = 100
    this.sizeY = 100
    img.onload = () => this.drawImage()
  }
  drawImage() {
    this.ctx.drawImage(this.img, this.posX, this.posY, this.sizeX, this.sizeY)
  }
}

new Monster(100, 200, "./img/bone.png")
new Monster(260, 200, "./img/pumpkin.png")
new Monster(420, 200, "./img/ghost.png")
```

現時点で、モンスターが3体表示されていれば成功です。

また、必要であれば、JavaScriptのファイルを分けるなどしてください。

# パーティメンバーのステータスを表示する

それでは、パーティのHPなどを表示していきます。

パーティの情報を格納するためのクラスとして``PlayerCharacter``を新しく作ります。
今回はHP、MP、そして名前を表示させたいので、引数にname, hp, mpを用意します。

```javascript:game.js
class PlayerCharacter {
  constructor(name, hp, mp) {
    this.name = name;
    this.hp = hp;
    this.mp = mp;
  }
}

var chara1 = new PlayerCharacter("アベル", 100, 80);
var chara2 = new PlayerCharacter("カイン", 100, 55);
var chara3 = new PlayerCharacter("プリン", 100, 45);
```

これでchara1、chara2、chara3にそれぞれメンバーの情報が格納されました。
後はこの情報を表示していきます。

ただ、その際に毎回出力する場所（x,y）を手動で入力するのは面倒ですよね。

そういうわけで、メンバーの情報を``characterList``という配列に格納します。
そして、``forEach``でそれぞれ回します。

表示部分に関することや、メンバーの追加などをひとつのクラスでまとめたいので、新しくゲームを司るクラスとして``GameManager``を作成して、以下のように書きます。

```javascript:game.js

class GameManager {
  constructor() {
    const canvas = document.getElementById("canvas")
    this.ctx = canvas.getContext("2d")
    this.characterList = []; // メンバーのHP/MPなど...
  }
  addCharacter(character) {
    this.characterList.push(character);
  }

  showCharacterStatus() {
    this.ctx.clearRect(0,0,640,480)
    this.ctx.font = `28px serif`;
    this.ctx.fillStyle = "black"
    this.ctx.fillText("HP", 20, 50)
    this.ctx.fillText("MP", 20, 90)
    this.ctx.fillText("名前", 20, 130)
    this.monsterList.forEach((chara, index) => {
      this.ctx.fillText(chara.hp, 190 * index + 140, 50)
      this.ctx.fillText(chara.mp, 190 * index + 140, 90)
      this.ctx.fillText(chara.name, 190 * index + 140, 130)
    })
  }
}
```

これでGameManager内のaddCharacter(character)に先程作成したchara1〜3をそれぞれ入れて、最後にshowCharacterStatus()を実行すればメンバーのステータスが表示できますね。

```javascript:game.js
var gameManager = new GameManager();
gameManager.addCharacter(chara1);
gameManager.addCharacter(chara2);
gameManager.addCharacter(chara3);
gameManager.showCharacterStatus()
```

これで画面にはメンバー3体とそれぞれのステータスが表示されているかと思います。
今回レイアウトは最低限しか行っていませんが、レイアウト自体をもう少し整えるともっとゲームらしくなります。

それでは今回はモンスターの画像を3体表示するのと、パーティメンバーステータスをそれぞれ表示しました。

もしもう少しJavaScriptに関して学びたい場合はぜひ[JavaScript道場](https://x-hack.connpass.com/event/200502/)におこしください！