0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-01-14

こんにちは、Yuiです。

今回はプレイヤーの行動リストを表示してみたいと思います。

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

Image from Gyazo

行動リストを表示する

それでは前回作ったgame.jsに「たたかう」「ぼうぎょ」「まほう」「どうぐ」の4つのコマンドを追加していきます。

まずはその4つのコマンドを配列で格納します。

GameManagerクラスの中に、コマンドを表示する部分としてshowCommandとして新しいメソッドを追加します。

game.js

  showCommand() {
    this.actions = [
      { name: "たたかう" },
      { name: "ぼうぎょ" },
      { name: "まほう" },
      { name: "どうぐ" },
    ]
    this.actions.forEach((action, index) => {
      this.ctx.fillText(action.name, 50, index * 30 + 350)
    })
  }

現時点で「たたかう」「ぼうぎょ」「まほう」「どうぐ」の4つのコマンドが画面に表示されたかと思います。それでは次に▷をそのコマンドの隣に表示するようにしましょう。

this.ctx.fillText("", 20, 350)

このコードを上記のshowCommandの中に入れれば▷が「たたかう」の隣に現れたかと思います。

ただ、現時点では▷は動かしても動きませんね。
これは▷のy座標が350で固定されてしまっているからです。
そこで、y座標を矢印キーの動きに合わせて動かしていきたいと思います。

▷を動かす

さて、▷を動かすためには上述の通り現時点のy座標を流動的にする必要があります。
というわけでy座標にあたるものをthis.setActionとして、初期値を350で設定します。
初期値なので、GameManager内のconstructor()で設定します。

game.js
class GameManager {
  constructor() {
    const canvas = document.getElementById("canvas")
    this.ctx = canvas.getContext("2d")
    this.setAction = 350; //<=追加
    this.characterList = []; 
  }

...

そしてchooseCommandというメソッドを新しく作り、その中でthis.setActionの値を変更していきたいと思います。

game.js
  chooseCommand(e) {
    if (e.key === "ArrowDown" && this.setAction < 440) {
      this.setAction += 30;
      this.ctx.clearRect(20,300, 25, 480)
      this.ctx.fillText("", 20, this.setAction)
    }
    if (e.key === "ArrowUp" && this.setAction > 350) {
      this.setAction -= 30;
      this.ctx.clearRect(20,300, 25, 480)
      this.ctx.fillText("", 20, this.setAction)
    }
  }

このへんのロジックは前回やったスライムを動かすものと同じです。
this.setActionの値で制限をつけているのは、必要以上に▷が上がりすぎたり下がりすぎたりしないためです。

clearReactで消す部分に関しては、▷が表示されている部分だけで良いので、細かく範囲を調整しています。

あとは、この部分をaddEventListenerで制御すれば動きます。以下のコードをgameManager外の部分に書きます。

game.js
window.addEventListener("keydown", (e) => {
  gameManager.chooseCommand(e);
})

そしてそれに合わせてもちろん初期値で設定していたthis.ctx.fillText("▷", 20, 350)this.ctx.fillText("▷", 20, this.setAction)に変更します。
これでgame.jsの中身は以下のようになりました。

game.js

class GameManager {
  constructor() {
    const canvas = document.getElementById("canvas")
    this.ctx = canvas.getContext("2d")
    this.setAction = 350;
    this.characterList = []; 
  }
  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.characterList.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)
    })
  }
  showCommand() {
    this.actions = [
      { name: "たたかう" },
      { name: "ぼうぎょ" },
      { name: "まほう" },
      { name: "どうぐ" },
    ]
    this.actions.forEach((action, index) => {
      this.ctx.fillText(action.name, 50, index * 30 + 350)
    })
    this.ctx.fillText("", 20, this.setAction)
  }
  chooseCommand(e) {
    if (e.key === "ArrowDown" && this.setAction < 440) {
      this.setAction += 30;
      this.ctx.clearRect(20,300, 25, 480)
      this.ctx.fillText("", 20, this.setAction)
    }
    if (e.key === "ArrowUp" && this.setAction > 350) {
      this.setAction -= 30;
      this.ctx.clearRect(20,300, 25, 480)
      this.ctx.fillText("", 20, this.setAction)
    }
  }
}

//以下のモンスター表示部分もGameManager内にメソッド追加でできますが、現状は前回のままにしておきます。
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");

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);

var gameManager = new GameManager();
gameManager.addCharacter(chara1);
gameManager.addCharacter(chara2);
gameManager.addCharacter(chara3);
gameManager.showCharacterStatus();
gameManager.showCommand();

window.addEventListener("keydown", (e) => {
  gameManager.chooseCommand(e);
})

これで無事▷が動くようになったかと思います。
ただ、このままではクリックをしても何も起こりません。
そこで次回はクリック時のアクションを追加していきます。

おまけ

こちらのコードに関しては簡略的に書いているため、かなり雑な作りとなっています。
もう少しちゃんと書くのであれば、親となるクラスと子となるクラスを細かく分けて、jsファイルも分けてしまってからextendsで継承させて書いていくような書き方のほうが見やすいかと思います。

また、上述のコメントアウトでも書きましたが、モンスター表示部分(Monsterクラス)に関してはGameManager内にメソッドとして入れるなり、そもそもファイルを分けて親クラスGameManagerを継承するなり、色々書き方はありますが、現状ではこのままとしておきます。

ぜひ時間のある際にでも色々と書き換えてみて、試してみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?