見出し画像

【GASでサイエンス】2D物理シミュレーション用ライブラリ「Matter.js」をGASに組み込んでみる(最終)~準備が済んだらrun!|コードの実装~

この記事は、2次元の物理シミュレーション用ライブラリ「Matter.js」を組み込んだ、GASによる物理シミュレーションアプリのご紹介です。

このアプリは以下の様なデモを実行します。

2次元シミュレーションの様子

上記の物体の大きさなどの諸元は、以下の様に、Goolgeスプレッドシートにデータを書いて制御できます。

シミュレートする物体の諸元

この記事は、以下の記事の続きとなります。


先回の記事までで、「物理エンジン」「結果の描画」「登場する物体」「空間」の実体化が済み、事前準備が終わりました。

本記事では実装コードを最後にご紹介しています。様々な理由により、この説明通りにいかない場合がしばしばあります。申し訳ありませんが、自己責任・自己解決でお進めくださるよう、お願いいたします。

なお、Matte.jsのコードは以下のサイトを参考にさせて頂きました。この場を借りて御礼申し上げます。


準備が終わったらあとは実行するだけ~物理エンジンと結果描画をrunする~


事前準備が終わり、実行させるのは簡単です。物理エンジンを実行させ、その結果を描画するだけです。

これらのコードは以下の構文になります。

インスタンス.run(実行対象)

コードは以下の様になります。

          Engine.run(myEngine);
          Render.run(myRender);


上記のコードを実行させると、1、2秒の準備時間を経て、以下の画面が現れます。


初期画面


その後は、物理法則に従って、長方形とボールが動きます。

このシミュレーションは、単純そうで、意外と複雑な内容をシミュレートしています。

  • 重力による加速

  • 物体同士の衝突

  • 物体の跳ね返りや転がり

  • 摩擦による運動の停止

  • 一連の過程をアニメーション表示する

ユーザーは最初にどういう状態であったかだけ記述すれば良く、あとはライブラリが表示まで含めて処理してくれるのが、「Matte.js」の素晴らしいところです!

このライブラリの主な目的は、ゲームなどに応用して「それらしく」動くアニメーション表示を行う事だと理解していますので、私見ですが、厳密なシミュレーションからは外れている可能性はあると思います(調べられていません)

WEBアプリに使うGoolgeスプレッドシートとGASのコードのご紹介


本アプリのための、スプレッドシート、スクリプトとテンプレートをご紹介します。

スプレッドシート

Googleドライブ上にスプレッドシートを新規作成し、以下のエクセルワークブックを「ファイル」→「インポート」メニューによりアップロードしてインポートしてください。(シート名は変えないでください)

上記の「諸元」シートには、この記事で紹介している例をテスト用に記載しています。

デモだけのアプリですので、ユーザーが編集できるのは黄色いセル(ダウンロード頂くものには色をつけています)の数字だけで、長方形やボールの順序などは変えられません。

インポートしたらGoogleスプレッドシートを表示させた状態で、ブラウザのURLを確認し、スプレッドシートのIDを控えておきましょう。

HTTPS://docs.google.com/spreadsheets/d/★スプレッドシートの
ID★/edit・・・

スクリプトとテンプレート

Googleドライブ上で「新規」→「その他」→「Google Apps Script」を選択し新規のプロジェクトを追加します。作成したらプロジェクトのエディタを開きます。

コードを以下に記載しますが、手順そのものは以下の記事を参考にしてください。

スクリプトのコード

以下のコードをスクリプトに貼り付けてください。(★スプレッドシートID★の書き換えを忘れずに)

//-----------------------------------------
//----物理エンジン matter.jsの利用------------------
//---著作:Particlemethod-2022年02月01日-----
//---使用は自由ですが著作権は作成者に帰属します---
//-----------------------------------------

//=====doGet関数はURLから呼び出された時に実行する関数|1つだけ定義できます=====
function doGet(e) {

 //HTMLファイルのテンプレートをファイル名を指定して取得
 var myHTML = HtmlService.createTemplateFromFile('INDEX');


 //HTMLファイルをホスティング|メタタグを指定してスマホ表示に対応
 return myHTML.evaluate().addMetaTag("viewport", "width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=10.0");
}

//=====HTMLから呼び出されて実行する関数=====

//HTMLテーブルの値myCellsをシートに書き込む関数
function GetSheet(Row0, Col0, nRow, nCol){

 //アプリケーションを取得|★スプレッドシートID★は各自のものを記入
 var myApp = SpreadsheetApp.openById('★スプレッドシートID★');

 //対象シートをシートの名前を指定して取得
 var mySheet = myApp.getSheetByName('諸元');

 //セル範囲の値を返す 
 return mySheet.getRange(Row0, Col0, nRow, nCol).getValues();
}

テンプレートのコード

プロジェクトに、テンプレートを追加し、以下のコードを貼り付けます。名前は「INDEX.hrml」とします。


<!--
-----------------------------------------
----物理エンジン matter.jsの利用---------
---著作:Particlemethod-20220201日-----
---使用は自由ですが著作権は作成者に帰属します---
-------------------------------------------
--------------参考サイト--------------
https://yujin777.com/2020/08/21/matter-js-sample-12-%E8%90%BD%E4%B8%8B%E3%81%99%E3%82%8B%E9%95%B7%E6%96%B9%E5%BD%A2%E3%81%A8%E5%86%86/
-->

<html>
  <head>
    <meta charset="UTF-8" />

   <!--ライブラリ「Matte.js」の組み込み--->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.14.2/matter.min.js"></script>
  </head>
  <body>


    <script>
   //====Matter.jsの道具立て(インスタンス)を用意=====

      //物理エンジンのインスタンス
      var Engine = Matter.Engine;

      //レンダリング(描画機能)のインスタンス
      var Render = Matter.Render;

      //シミュレーションする舞台(ワールド)のインスタンス
      var World = Matter.World;

      //登場させる物体のインスタンス
      var Bodies = Matter.Bodies;

   //====インスタンスを実体化=====

      //使用する物理エンジンの宣言
      var myEngine = Engine.create();

      //使用する画面(レンダリング)の宣言
      var myRender = Render.create({

      //画面(CANVAS要素)をどこに置くか
        element: document.body,

      //使用する物理エンジン
        engine: myEngine,

      //画面サイズ、簡易表示(ワイヤフレーム)有無
        options: {
          width: 650,
          height: 350,
          wireframes: false,
        },
      });

      //==テーブルのセルの値をGASのSetSheet 関数に渡し、成功したらonSuccessを実行==
      //★★セルのデータを増やした場合は、GetSheet(データ開始行,データ開始列, データ行数, データ列数)を編集★★

      google.script.run.withSuccessHandler(onSuccess).GetSheet(3, 2, 5, 4);

      //script.run関数が成功したら、セルの内容を記憶したres配列を使って以下を実行
      function onSuccess(res){
        //長方形 rectangle(x座標,y座標,幅,高さ)
          var myBoxA = Bodies.rectangle(res[0][0], res[0][1], res[0][2], res[0][3]);

        //長方形 | isStatic: true ← 不動設定
          var myBoxB = Bodies.rectangle(res[1][0], res[1][1], res[1][2], res[1][3], { isStatic: true });
          
        //ボール circle(x座標,y座標,半径)
          var myBallA = Bodies.circle(res[2][0], res[2][1], res[2][2]);
          var myBallB = Bodies.circle(res[3][0], res[3][1], res[3][2]);

        //地面:長方形&不動設定
          var myGround = Bodies.rectangle(res[4][0], res[4][1], res[4][2], res[4][3], { isStatic: true });

        //空間の実体化|空間を支配する物理エンジン、物体を記載します
          World.add(myEngine.world, [myBoxA, myBoxB, myBallA, myBallB, myGround]);

        //シミュレーションの実行と結果の描画
          Engine.run(myEngine);
          Render.run(myRender);
      }

    </script>
  </body>
</html>

以上となります。

コードを保存してデプロイしたら、URLにアクセスしてみてください。扉のアニメーションが表示されるはずです。

 この説明通りにいかない場合は申し訳ありませんが、自己責任・自己解決でお進めくださるよう、お願いいたします。

GASでWEBアプリを作る記事を、解説書にしてみました。拙い解説ですが、宜しければどうぞ。

本書の内容は、以下の記事をご覧ください。


いいなと思ったら応援しよう!