JavaScriptでつくる物理演算ゲームの基本と最適化(Matter.js入門)

🎮 この記事のポイント:物理演算を使うことで、ゲームに一気にリアルさと不確実性の面白さが生まれます。「合体!おっさん進化論」でも使用しているMatter.jsの導入方法から、描画負荷を低減するモバイル向け最適化テクニックを網羅解説します。

Matter.jsとは?ブラウザで動く2D物理エンジン

HTML5ブラウザゲームで物理的な挙動(重力、衝突、反発、摩擦)を再現するためには、物理演算ライブラリを使用するのが効率的です。JavaScriptで動作する2D物理エンジンの中で、最も扱いやすくパフォーマンスが高いのが「Matter.js」です。

Matter.jsは、剛体(Rigid Body)の衝突応答、複雑な形状のポリゴンサポート、ばね結合(Constraint)、摩擦や空気抵抗などの計算をミリ秒単位で高速に行います。Canvas APIと組み合わせて使うことで、スイカゲームのようなマージ系ゲームや、ピンボール、パズルアクションを簡単に作成することができます。

Matter.jsの基本モジュール

Matter.jsを扱う上で理解しておくべきコアオブジェクトが以下の5つです。

  • Engine(物理シミュレータ): 世界全体の時間の進みや物理のアップデート(重力の適用など)を管理します。
  • World(物理空間): 物理シミュレーションが行われる空間自体です。この中に物体(Body)を追加します。
  • Body / Bodies(剛体・物体): 円形、矩形、多角形などの物理特性(質量、反発力、摩擦)を持ったオブジェクトを作成します。
  • Composite(複合体): 複数の物体や制約を1つにグループ化して操作しやすくするための仕組みです。
  • Render(デバッグ描画用レンダラー): 物体のワイヤーフレームなどをCanvasに簡易的に表示するデバッグ用の簡易描画機能です(本番は自前でテクスチャを描画することが推奨されます)。

基本的な世界と剛体の作成

Matter.jsのセットアップは驚くほどシンプルです。以下は画面内に「床」と「落下するボール」を作る基本コードの例です。

const { Engine, World, Bodies, Composite } = Matter;
const engine = Engine.create();

// ボールの作成 (x=400, y=100, 半径=40)
const ball = Bodies.circle(400, 100, 40, {
    restitution: 0.8, // 跳ね返り係数 (0.8はよく弾む)
    friction: 0.1     // 摩擦係数
});

// 静的オブジェクト(床・壁)の作成 (isStatic: trueを指定)
const ground = Bodies.rectangle(400, 580, 800, 60, { isStatic: true });

// ワールドにオブジェクトを追加
Composite.add(engine.world, [ball, ground]);

// 毎フレームEngineを更新するループ
function update() {
    Engine.update(engine, 1000 / 60);
    requestAnimationFrame(update);
}

モバイル・ブラウザ向け物理演算の最適化(重要)

多くの物理演算ゲームが、PCでは滑らかに動くのに、スマートフォン(特に少し古い世代)では極端に動作が遅くなる(カクつく)問題に悩まされます。これは、毎フレーム行われる「衝突検出(Narrowphase)」と「制約の解決(Constraint Solver)」の計算負荷が、モバイルのCPUに対して重すぎるためです。

ブラウザゲームで60FPSを維持するための具体的な最適化テクニックを3つ紹介します。

1. イテレーション回数(繰り返し計算)の削減

物理エンジンは、衝突した物体のめり込みを解決するために1フレームの間に何回も補正計算を繰り返します。Matter.jsでは、Engineのオプションを調整してこの計算精度(反復回数)を下げることで、計算量を激減させることができます。

// デフォルト値 (位置12, 速度8) を下げる
engine.positionIterations = 6;
engine.velocityIterations = 4;

※この値を下げすぎると、物体が超高速で移動したときに壁を突き抜けてしまう(トンネル効果)可能性があるので、ゲームバランスを見ながら調整します。

2. 物理演算と描画(Canvasレンダリング)の完全分離

Matter.js付属の`Render`モジュールは開発用の簡易デバッグツールです。ゲーム本番では自前の描画エンジン(Pixi.jsや純粋なCanvas API、WebGLなど)を使用し、物理物体の座標(`body.position.x`, `body.position.y`)と回転角(`body.angle`)の値だけを読み取って、それに合わせてキャラクターやネオン画像を回転・描画させます。これにより、無駄なGPU転送を省くことができます。

3. 画面外の物体のシミュレーション除外(スリープ機能)

画面外に落下した不要な物体や、床の上に完全に静止して動いていない物体は、物理演算の対象外(スリープ)にします。Matter.jsには`enableSleeping: true`オプションが用意されており、これを有効にするだけで、床に積み重なった静止オブジェクトの余計な計算がスキップされ、全体の動作が驚くほど軽くなります。

まとめ:物理演算が生み出すゲームの魅力

物理演算を導入することで、「毎回必ず違った軌道で落ちていくボール」や「ぶつかり合って予期せぬ連鎖を起こすおっさん」のように、ユーザーが何度遊んでも飽きないゲームを作ることができます。Matter.jsを使えば、Webのスキルセット(HTML/CSS/JS)だけで世界中に届く超軽量なゲームを作ることが可能です。ぜひ Matter.js を使ったゲーム開発に挑戦してみてください!