株式会社グローバルゲート公式ブログ

ブラウザで動く物理エンジン【Matter.js】を試してみる

こんにちは、株式会社グローバルゲートのモーリーです。 

米不足が解消され、我が家で常食しているゆめぴりかもスーパーに新米が並ぶようになって一安心です。
…が、大幅に値上がりしてしまって5kgで3500円…主食を米ではなく麺にしようかと真剣に考えました…。

さて、今回はJavascriptの物理エンジン「Matter.js」を使って、重力や衝突といった物理現象をWebサイト上で表現してみたいと思います。 

物理エンジンとは?

物理エンジンとは、コンピュータ内で重力や衝突などの物理法則をシミュレーションし、物体の動きを現実世界に基づいて再現するためのプログラムです。主にゲーム開発、シミュレーション、アニメーション制作などの分野で利用され、重力、摩擦、衝突、反射などの物理現象を再現します。物理エンジンを使うことで、キャラクターが坂を下りるときの加速や、物体が壁に衝突したときの反発などをリアルにシミュレーションすることができます。 
 
主に以下のような機能を持ちます。

剛体シミュレーション: 剛体(硬い物体)の運動や衝突を計算し、どのような動きをするかをシミュレーションします。 
流体シミュレーション: 液体や気体の流れをシミュレーションします。 
衝突検出: ボールが壁にぶつかったあとの動きなど、物体同士がぶつかった時にどのように反応するかをシミュレーションします。 
柔軟体シミュレーション: 布やゴムのような柔らかい物体の変形をシミュレーションします。

Matter.jsとは?

今回使ってみるMatter.jsはJavaScriptで記述されたオープンソースの2D物理エンジンで、ウェブブラウザ上で動作するため、HTML5を用いたゲームやインタラクティブなWebアプリケーションで広く利用されています。 
物理エンジンは複雑な計算が必要なため扱いが難しいのですが、Matter.jsは比較的シンプルなコードで扱うことができます。 
Matter.jsを使うことで簡単に物理法則をWebアプリケーションに簡単に組み込むことができ、2DゲームやWebサイトのアニメーション表現を向上させることができます。

Matter.jsを使ってみる

それでは実際にMatter.jsを使ってみましょう。 
チュートリアルを参考に簡単な処理を書いてみました。

物を落とす

まずは簡単に箱が上から降ってくるだけのアニメーションを実装してみます。 
箱と地面を定義することでそれぞれが描画され、描画が完了すると箱は地面まで落下します。 
 
重力をシミュレートしているため、落下速度が徐々に早くなっている点がポイントです。 

地球上の重力加速度は9.8m/s^2ですが(習うのは中学だったか高校だったか思い出せませんが…)、試しに重力を半分にしてみましょう。 
Matter.jsでは以下の記述で重力を調整することができます。

engine.world.gravity.y = 0.5;

 そうすると落下速度も遅くなりました。

弾性の表現

次に物体に反発力を持たせ、落とした物体がバウンドするようにしてみましょう。 
物体定義の際にrestitutionというオプションを追加することでその物体は弾性を持ちます。 
 
合わせてdensity(密度)も定義してみます。これは物体の重さを定義するもので、小さい数値にすると密度の高い(つまり重い)物体となります。 

var boxA = Bodies.rectangle(300, 0, 80, 80, { 
    render: { 
        fillStyle: '#343b81' 
    }, 
    restitution: 1.5, //弾性を持たせる 
    density: 0.001,//密度(小さいほど重い) 
});

箱に弾性を設定し、上に来る箱の密度を高くしたことで抑え込まれるような動きとなりました。 

マウス操作

Matter.jsではクリックやドラッグなどでオブジェクトを操作することができます。 
この機能も試してみます。 
 
クリックするとその位置からランダムな色とサイズの球体が生成される処理を作ってみました。

クリックイベントはHTMLのクリックと同じくaddEventListenerで定義します。

        document.addEventListener('click', function (event) { 
            // クリック位置を取得(キャンバス内の座標) 
            const rect = render.canvas.getBoundingClientRect(); 
            const mouseX = event.clientX - rect.left; 
            const mouseY = event.clientY - rect.top; 
 
 
 
            // クリック位置に円のオブジェクトを生成 
 
            //生成される円のサイズ範囲を指定 
            const circleSizeMax = 100; 
            const circleSizeMin = 10; 
            const circleSize = Math.floor(Math.random() * (circleSizeMax - circleSizeMin + 1)) + circleSizeMin; 
 
            //生成される円の色を指定 
            const color = '#' + Math.floor(Math.random() * 16777215).toString(16) 
 
            const circle = Bodies.circle(mouseX, mouseY, circleSize, { 
                restitution: 0.5, 
                render: { 
                    fillStyle: color, 
                } 
            }); 
 
            // 生成したオブジェクトをワールドに追加 
            World.add(world, circle); 
        });

ブロック崩し

最後に簡単なブロック崩しゲームを作ってみました。 
ゲームオーバーやクリアの処理は作ってませんので失敗した場合はリロードして遊んでみてください。 

これだけでもかなり大変だった…。
実際にゲームとして成立させるためには、ボールが落下したときにゲームオーバーとして判定する、破壊したブロックの個数を得点として計算する、スコアを保存する、など、まだまだ多くの機能を実装する必要があります。
ゲーム制作は難しいですね。 

まとめ

ということで、今回はJavascript製2D物理エンジンのMatter.jsを使って簡単な処理を書いてみました。 
 以前当ブログでCSSによるイージングについてご紹介しましたが、イージングも簡易的に物理現象をシミュレートしたものと言えます。
Matter.jsを使うことでより複雑でリアリティのある表現ができるかもしれません。どのような表現ができるか、引き続き模索していきたいと思います。

【関連記事】

ご相談・お問い合わせ

当社サービスについてのお問い合わせは下記までご連絡下さい。

お電話でのお問い合わせ

06-6121-7581 / 03-6415-8161