Canvasで完成させるゲームループ設計|Fixed Time Stepと描画統合

Canvas Architectureのアイキャッチ画像

1.JavaScriptアニメーションを「本格描画」に進化させる

これまでの記事で、

までやりました。

ここまでで実はもう「ゲームループの骨格」は完成しています。

今回はそこに Canvas を接続します。

2.なぜ Canvas が必要?

これまでは:

  • div を動かす
  • style.left を変更する

という DOM アニメーションでした。

でも、

  • 大量描画
  • パーティクル
  • 物理的な動き
  • UIシミュレーション

をやるなら、DOMよりCanvasのほうが圧倒的に制御しやすいです。

3.まずは最小構成

Canvasはこの3ステップだけ覚えればOKです。

<canvas id="canvas" width="600" height="400"></canvas>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.fillRect(100, 100, 50, 50);

これだけで四角が描けます。

4.重要な概念

Canvasは「毎フレーム描き直す世界」です。

DOMのように「要素が残る」わけではありません。

なのでループでは必ず:

ctx.clearRect(0, 0, canvas.width, canvas.height);

を入れます。

5.これまでの設計とつなぐ

ここが今回の本質です。

今まで作った構造:

update(dt)
render(alpha)

これをCanvasに流し込むだけです。

6.統合例(最小形)

class State {
  constructor() {
    this.x = 0;
    this.prevX = 0;
    this.speed = 100;
  }

  update(dt) {
    this.prevX = this.x;
    this.x += this.speed * dt;
  }

  render(ctx, alpha) {
    const interpolatedX =
      this.prevX + (this.x - this.prevX) * alpha;

    ctx.fillRect(interpolatedX, 150, 50, 50);
  }
}

7.ループ部分

const fixedDelta = 1 / 60;
let accumulator = 0;
let lastTime = 0;

function loop(time) {
  const delta = (time - lastTime) / 1000;
  lastTime = time;
  accumulator += delta;

  while (accumulator >= fixedDelta) {
    state.update(fixedDelta);
    accumulator -= fixedDelta;
  }

  const alpha = accumulator / fixedDelta;

  ctx.clearRect(0, 0, canvas.width, canvas.height);
  state.render(ctx, alpha);

  requestAnimationFrame(loop);
}

8.ここで何が起きている?

  • update → 論理更新(60回固定)
  • render → 描画(毎フレーム)
  • interpolation → 滑らか補間
  • Canvas → 実際に描く場所

つまり、

設計がそのまま描画エンジンに接続できた

ということです。

9.DOMとの違い

DOMCanvas
要素が残る毎回描き直す
CSS管理全て手動描画
レイアウト計算あり超軽量

Canvasは「自分で全部やる世界」です。

でもその分、設計が活きます。

10.実験:DOM vs Canvas 描画コスト比較

今回の実験では、

  • 左:DOM(left/top 更新 + shadow)
  • 右:Canvas(fillRect 描画)

を 同じ update ロジックで動かします。

違うのは「描画方法」だけです。

🔍 実験内容

  • 同じ数の粒子(N個)を動かす
  • DOMは left/top で位置更新
  • DOMには box-shadow を追加してペイント負荷を増やす
  • Canvasは fillRect で同数を描画

HUDには以下を表示します:

  • DOM 描画時間(ms)
  • Canvas 描画時間(ms)
  • Ratio(DOM ÷ Canvas)

👀 観察ポイント

① N を増やす(800 → 1200 → 1500)

→ DOMの ms が先に増えやすい
→ Ratio が 1.5x / 2x / 3x と上がることがある

(※端末性能によって差は変わります)

② Shadow を ON にする

→ DOMはペイントコストが増える
→ 差がさらに拡大する可能性あり

③ 16ms を意識する

60fps を維持するには:

1フレーム ≒ 16.7ms

DOM側が 16ms に近づくと
体感的なカクつきが出やすくなります。

🧠 この実験で分かること

Canvasが「速い」というよりも、

  • DOMは要素ごとの管理コストがある
  • Canvasは1枚の面に描く構造

という設計思想の違いが見えてきます。

つまり:

Canvas統合とは「描画の制御を自分で持つ」ということ

11.ここまでで出来たこと

あなたは今:

  • アニメーションループを設計できる
  • 時間制御を理解している
  • 状態と描画を分離できる
  • Canvasへ接続できた

つまり、

ゲームエンジンの最小構造を理解した

ということです。

12.次は?

次は入力です。

描くだけではなく、
「ユーザー操作を状態に渡す」

#13 Input設計へ進みます。

🔎 このラボの全体像はこちら
UI Architecture Roadmap

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA