ちょっと前にlark-matterっていう物理エンジンMatter.jsのレンダラをドット絵っぽくするプラグインを作ったんだけど、その時に覚えたはずのMatter.jsのプラグインによる拡張方法を忘れないうちにメモっておく。
基本的には以下のドキュメントを読めば良い。
プラグインの基本情報を書く所と登録する所はだいたいサンプルの通り書けばいいとして、肝心なのはエンジンへのパッチの当て方だ。
基本的にはMatter.before
とMatter.after
という関数を使えばMatter.js内のあらゆる関数の実行前と実行後にプラグインとして実行したい処理を挟み込むことができるので、そこでゴニョゴニョすれば良い。
lark-matterの例で言えば、まずRenderを差し替えたいのでRender.create
の後で独自レンダラの初期化などを行って、Render.run
の後で既存レンダラを止めて新しいレンダラに差し替えている。
matter.after('Render.create', initRender); matter.after('Render.run', runRender);
function runRender(render: Matter.Render) { matter.Render.stop(render); renderLm(render); }
Render.runの引数とかはそのままフックする関数の引数にくるので、それを使ってrunしたレンダラを止めるとかいう処理もできる。
後はEngine.create
の後でMatter.js内のイベントのリスナーを登録しておけば、特定のイベントが発生した時の処理を差し込むこともできる。例えば衝突発生時(collisionStart
)にパーティクルを飛ばすとか。
matter.after('Engine.create', initEngine);
function initEngine() { const engine: Matter.Engine = this; matter.Events.on(engine, 'collisionStart', e => { e.pairs.forEach(p => { p.activeContacts.forEach(ac => { const b = ac.vertex.body; const v = b.velocity; let ratio = (<any>p).collision.depth * matter.Vector.magnitude(v) * 0.1; if (ratio > 2) { ratio = 2; } if (ratio > 0.3) { ppe.emit(b.ppeTypeId, ac.vertex.x / LarkMatter.options.dotSize, ac.vertex.y / LarkMatter.options.dotSize, Math.atan2(-v.y, -v.x), { countScale: ratio, speed: 0.7 * ratio }); if (LarkMatter.options.enableSes) { sss.play(b.sssTypeId, 2, null, ratio > 1 ? 1 : ratio); } } }); }); }); }
どのようなイベントが存在するかはMatter.jsのリファレンスを見れば分かる。例えばEngineで発生するイベントの一覧とか。