3. プレイヤーの移動

はじめに

プレイヤーの移動を実装しました。 キー入力で上下左右と斜めにも移動できるようにして、ついでにSHIFTキーで走るようにしました。

停止アニメーションの作成

前回、Phaser Editorで walk-down,walk-up,walk-left,walk-rightというアニメーションを作成しました。

停止時に足を上げたポーズで止まってしまうことを避けるため、新たに停止時のポーズを1フレームのアニメーションとして作成し、stop-down,stop-up,stop-left,stop-rightという名前で保存しました。

アニメーションといっても1フレームなので動きはありません。将来的に、停止時はあくびをするなどのアニメーションを設定することもできます。

コード

キー入力の取得

input.keyboard.createCursorKeysでキー入力を取得します。

export default class StartScene extends Phaser.Scene {
  // ...
  private cursors!: Phaser.Types.Input.Keyboard.CursorKeys;
  // ...
  create() {
    this.cursors = this.input.keyboard!.createCursorKeys();
    // ...
  }
}

キー入力をベクトルに変換

キーの押下状態から、[vx,vy]という長さspeedのベクトルに変換します。 斜め移動のときは速くなりすぎないように正規化(normalize)をしておきます。

// キー入力から移動速度を取得する関数
function getVelocity(
  cursors: Phaser.Types.Input.Keyboard.CursorKeys,
  speed: number
): [number, number] {
  let vx = 0;
  let vy = 0;
  if (cursors.shift?.isDown) speed *= 2; // Shiftキーで速くなる
  if (cursors.left?.isDown) vx = -speed;
  if (cursors.right?.isDown) vx = speed;
  if (cursors.up?.isDown) vy = -speed;
  if (cursors.down?.isDown) vy = speed;
  // 斜め移動時の速さ補正(√2で速くなりすぎないように)
  if (vx !== 0 && vy !== 0) {
    const vec = new Phaser.Math.Vector2(vx, vy).normalize().scale(speed);
    vx = vec.x;
    vy = vec.y;
  }
  return [vx, vy];
}

ベクトルからプレイヤーの向きを取得

アニメーションのkeyを指定するために、プレイヤーの向きを文字列で取得します。

type Direction = "up" | "down" | "left" | "right";

// プレイヤーの移動方向を取得する関数
function getDirection(vx: number, vy: number): Direction | "stop" {
  if (vx === 0 && vy === 0) {
    return "stop";
  }
  if (Math.abs(vy) > Math.abs(vx)) {
    // 縦方向優先
    return vy < 0 ? "up" : "down";
  } else {
    // 横方向優先
    return vx < 0 ? "left" : "right";
  }
}

スプライトの移動とアニメーションの設定

シーンのコードが多くなってきたので、Playerクラスとして切り出しました。 やっていることは、PlayerのspriteのsetVelocityanims.playを呼ぶだけです。

アニメーションのkeyには、上下左右に動いている時はwalk-*を、止まっている時はlastDirectionを使ってstop-*を指定します。

export default class Player {
  update(cursors: Phaser.Types.Input.Keyboard.CursorKeys): void {
    // キー入力でそれぞれX/Y軸の速度を設定
    const [vx, vy] = getVelocity(cursors, this.playerSpeed);
    this.sprite.setVelocity(vx, vy);

    // アニメーション切り替え & lastDirection 更新
    const direction = getDirection(vx, vy);
    if (direction != "stop") {
      this.sprite.anims.play(`walk-${direction}`, true);
      this.lastDirection = direction;
    } else {
      this.sprite.anims.play(`stop-${this.lastDirection}`, true);
    }
    // ...
  }

まとめ

以下を実装しました。

  • プレイヤーが8方向に歩く
  • SHIFTキーで走る(倍速)
  • 停止する(停止ポーズ)
  • デバッグ情報の表示

だんだんソースコードが増えてきました。コードの公開方法を考えたほうがいいかもしれません。