こんにちは、Yuiです。
今回は前回描画したスライムを動かす方法について書いていきます。
JavaScript道場はこちら。
キーボードの↑↓→←キーで動かしています。
スライムのデフォルトの場所を中心にする
前回は(0,0)を始点にしてましたが、それだと少し見にくいのでスライムのデフォルトの位置を中央にしましょう。
絶対値で表しても良いのですが、今回はcanvasサイズから計算します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="canvas" width="640" height="480" style="background-color: black;"></canvas>
<script>
const CANVAS_SIZE_W = 640
const CANVAS_SIZE_HW = 320 // 画面の半分の広さ
const CANVAS_SIZE_H = 480
const CANVAS_SIZE_HH = 240 // 画面の半分の高さ
const CHARACTER_SIZE = 100 // キャラクターの大きさ
const CHARACTER_HSIZE = 50 // キャラクターの半分の大きさ
let CHARACTER_POS_X = CANVAS_SIZE_HW - CHARACTER_HSIZE
let CHARACTER_POS_Y = CANVAS_SIZE_HH - CHARACTER_HSIZE
const canvas = document.getElementById("canvas")
const ctx = canvas.getContext("2d")
const img = new Image()
img.src = "https://cache-www.dragonquest.jp/hoshidora/assets_190310/narikirislime/pc/slime.png"
img.onload = () => ctx.drawImage(
img,
CANVAS_SIZE_HW - CHARACTER_HSIZE,
CANVAS_SIZE_HH - CHARACTER_HSIZE,
CHARACTER_SIZE,
CHARACTER_SIZE
)
</script>
</body>
</html>
これでスライムが中央に来ました。
キーボードに反応してスライムが動くようにする
そして今回肝となるキーボードに反応する部分です。
そのためにはaddEventListener
を使います。
公式ドキュメントはこちら→https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener
今回はwindowが対象になりますので、window.addEventListener
という風に書きます。
以下を追加します。
window.addEventListener("keydown", (e) => {
if (e.key === "ArrowLeft") {
CHARACTER_POS_X -= 10
ctx.drawImage(
img,
CHARACTER_POS_X,
CHARACTER_POS_Y,
CHARACTER_SIZE,
CHARACTER_SIZE
)
}
if (e.key === "ArrowUp") {
CHARACTER_POS_Y -= 10
ctx.drawImage(
img,
CHARACTER_POS_X,
CHARACTER_POS_Y,
CHARACTER_SIZE,
CHARACTER_SIZE
)
}
if (e.key === "ArrowRight") {
CHARACTER_POS_X += 10
ctx.drawImage(
img,
CHARACTER_POS_X,
CHARACTER_POS_Y,
CHARACTER_SIZE,
CHARACTER_SIZE
)
}
if (e.key === "ArrowDown") {
CHARACTER_POS_Y += 10
ctx.drawImage(
img,
CHARACTER_POS_X,
CHARACTER_POS_Y,
CHARACTER_SIZE,
CHARACTER_SIZE
)
}
})
ここで、keydown
というのはkeyがdownしたとき、つまりキーを押してる状態のことをいいます。
そのときにどのキーが押されたかによって反応を変えたいのでeという変数に入れてあげます。
もし→がArrowRightなどと覚えている場合は良いのですが、もし覚えていない場合はここでconsole.log(e)
などをするとわかりやすいかと思います。
console.log(e)
をした状態で→のキーを押してログを出した状態です。
これを見ると→をクリックすると、e.keyがArrowRightになることがわかります。これを利用して↑↓→←で動きをそれぞれ付けたのが上記のコードです。
この状態で動かすとこのようになります。
スライムが動くことは動くのですが、軌跡まで残ってしまいます。
スライムが動くたびに毎回描画し直す
軌跡を消すために使うのがcanvasの中のclearRect
というメソッドです。
これは範囲を指定することで、その範囲内のものをすべてリセットすることができます。
そういうわけで、ctx.clearRect(0 ,0, CANVAS_SIZE_W, CANVAS_SIZE_H);
を以下のように追加します。
window.addEventListener("keydown", (e) => {
ctx.clearRect(0 ,0, CANVAS_SIZE_W, CANVAS_SIZE_H);
if (e.key === "ArrowLeft") {
CHARACTER_POS_X -= 10
ctx.drawImage(
img,
CHARACTER_POS_X,
CHARACTER_POS_Y,
CHARACTER_SIZE,
CHARACTER_SIZE
)
}
if (e.key === "ArrowUp") {
CHARACTER_POS_Y -= 10
ctx.drawImage(
img,
CHARACTER_POS_X,
CHARACTER_POS_Y,
CHARACTER_SIZE,
CHARACTER_SIZE
)
}
if (e.key === "ArrowRight") {
CHARACTER_POS_X += 10
ctx.drawImage(
img,
CHARACTER_POS_X,
CHARACTER_POS_Y,
CHARACTER_SIZE,
CHARACTER_SIZE
)
}
if (e.key === "ArrowDown") {
CHARACTER_POS_Y += 10
ctx.drawImage(
img,
CHARACTER_POS_X,
CHARACTER_POS_Y,
CHARACTER_SIZE,
CHARACTER_SIZE
)
}
})
これで軌跡が消え、いい感じにスライムが動くようになりました!
#クラス構文を使って書く
上記のままでももちろん良いのですが、今後スライムがたくさん出てきたときのために、クラス構文化して書いておきます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="canvas" width="640" height="480" style="background-color: black;"></canvas>
<script>
const CANVAS_SIZE_W = 640
const CANVAS_SIZE_HW = 320 // 画面の半分の広さ
const CANVAS_SIZE_H = 480
const CANVAS_SIZE_HH = 240 // 画面の半分の高さ
const CHARACTER_SIZE = 100 // キャラクターの大きさ
const CHARACTER_HSIZE = 50 // キャラクターの半分の大きさ
const canvas = document.getElementById("canvas")
const ctx = canvas.getContext("2d")
class Slime {
constructor(posX, posY) {
const img = new Image()
img.src = "https://cache-www.dragonquest.jp/hoshidora/assets_190310/narikirislime/pc/slime.png"
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)
}
move(e) {
ctx.clearRect(0 ,0, CANVAS_SIZE_W, CANVAS_SIZE_H);
if (e.key === "ArrowLeft") {
this.posX -= 10
}
if (e.key === "ArrowUp") {
this.posY -= 10
}
if (e.key === "ArrowRight") {
this.posX += 10
}
if (e.key === "ArrowDown") {
this.posY += 10
}
this.drawImage()
}
}
let s = new Slime(CANVAS_SIZE_HW - CHARACTER_HSIZE, CANVAS_SIZE_HH - CHARACTER_HSIZE)
window.addEventListener("keydown", (e) => {
s.move(e)
})
</script>
</body>
</html>
こうすることで、今後スライムを追加したい場合はnew Slime
と書くだけで生成することができますね!
クラス構文、便利ですね。
今回はスライム一個だけの設計なので、正直クラス構文にしてもしなくてもどちらでも問題は無いです。
ただ、今後ゲームを作っていく中で、敵をいくつか生成したりすることがあるかとおもいます。
そのたびに毎回同じコードを書くようでは効率が悪いので、使えるときはクラス構文でまとめておくのが楽でいいですね。
それでは今回はスライムを動かすところまでやりました。
それでは次回はパーティメンバーのステータスを表示する部分を実装していきます。