Excalibur.jsでdino-runnerゲーム作った

Excalibur.js dino runnerサンプル画像

Caution

この記事はHexo(2023年4月17日以前)、またはGatsby(2024年4月13日以前)時代の記事だよ❗ 現在のブログとは見た目や機能が異なる可能性があるよ❗

Dinoくんがトコトコ走るゲーム。ゴール目指してジャンプしよう。 Excalibur.js 製。 遊んでみてね❗

iOSだけは動作が不安定で、タイトル画面から進めないかもしれない…すまない。

以下、雑談。今回は設計実装の話を多めにしようと思う。

常に走るのってどうやってるの❓

↓の acc の部分が該当。

  reset() {
    this.canJump = false;
    this.pos = new Vector(this.x, this.y);
    this.vel = Vector.Zero;
    this.acc = Vector.Right.scale(config.dinoXAcc);
    this.body.collisionType = CollisionType.Active;
    this.playRunAnimation();
  }

Excalibur.jsでは加速度にあたる acc を指定しておくと、勝手に加速する。 この値は勝手に0にリセットされたりしない。

一方、速度にあたる vel などは衝突判定の結果によって勝手に増減する。 覚えておくと良い。

ジャンプするときのパワーゲージってどうやって表示してるの❓

Canvasの .arc を上手に使っている↓。

  onPreUpdate(_engine: Engine, _delta: number): void {
    const canvas = new Canvas({
      cache: false,
      height: 32,
      width: 32,
      draw: (ctx: CanvasRenderingContext2D) => {
        if (!this.getProgressCallback)
          throw Error("Have not registered getProgress callback!!");

        ctx.strokeStyle = "chartreuse";
        ctx.lineWidth = 3;
        ctx.beginPath();
        ctx.arc(16, 16, 15, 0, Math.PI * 2 * this.getProgressCallback(), false);
        ctx.stroke();
      },
    });
    this.graphics.use(canvas);
  }

幅を持った円弧形状を書くのではなく、線として円弧を書くのがポイント。 これだと↑のように数行で済む。

地面の検出はどうやってるの❓

Dinoくんの足元に検出専用の Actor を作って検出する。 衝突開始時( collisionstart イベント)にONして、 衝突終了時( collisionend イベント)OFFすれば良い。

他にもExcalibur.jsの作者様に質問したら返ってきた回答が こちら

1番の precollisionSide を使う方法がスマートなので、そっちに切り替えようか検討中。 3番の Ray を使う方法は初見だった。これも使えないか考えてみる。

ソースコードは❓

github で公開してるので勝手に見て。