🐦

[phina.js]イベントドリブンな当たり判定を作ってみた

2022/07/07に公開

はじめに

phina.jsで当たり判定を行う時は、update関数の中で当たり判定用の関数を使うことがほとんどだと思います。当たり判定に関連して、[phina.js]Colliderクラスを作ってみたでは、Accessoryを使ってUnityなどの当たり判定で使用されるColliderと同様な自作クラスについて書きました。
今回はそれを発展させて、イベントドリブンな当たり判定ができるようにしてみます。

collisionlayer

[runstantで確認]

目標

オブジェクトを追加しただけで、バックグラウンドで当たり判定が行われるようにします。

準備

scriptタグでphina.jsのほかにColliderクラスを読み込んでおきます。

<script src="https://cdn.jsdelivr.net/gh/phi-jp/phina.js@v0.2.3/build/phina.js"></script>
<script src="https://cdn.jsdelivr.net/gh/alkn203/phina-extensions@master/build/phina-extensions.min.js"></script>

CollisionLayerクラス

今回作成したクラスで、このクラスの子要素として追加されたオブジェクトを当たり判定の対象にします。

phina.define("CollisionLayer", {
  // 継承
  superClass: 'DisplayElement',
  // 初期化
  init: function() {
    // 親クラス初期化
    this.superInit();
  },
  // 毎フレーム更新処理
  update: function() {
    var self = this;
    
    this.children.each(function(c1, i) {
      self.children.each(function(c2, j) {
        // 子要素にColliderがあれば
        if (i !== j && c1.collider && c2.collider) {
          // 当たり判定
          if (c1.collider.hitTest(c2.collider)) {
            // ヒットイベント発火
            c1.flare('hit', {obj: c2});
            c2.flare('hit', {obj: c1});
          }
        }
      });
    });
  },
});

当たり判定

update関数内で行います。

 update: function() {
    var self = this;
    
    this.children.each(function(c1, i) {
      self.children.each(function(c2, j) {
        // 子要素にColliderがあれば
        if (i !== j && c1.collider && c2.collider) {
          // 当たり判定
          if (c1.collider.hitTest(c2.collider)) {
            // ヒットイベント発火
            c1.flare('hit', {obj: c2});
            c2.flare('hit', {obj: c1});
          }
        }
      });
    });
  },
  • 追加された子オブジェクトはchildren配列に格納されてますので、ループ処理でお互いの判定を行います。
  • まず、そのオブジェクトにcolliderがあるか調べてから、hitTest関数で判定を行います。
  • 単純にループで比べると同じオブジェクト同士を判定して常に当たっている状態になります。これを避けるために、配列中のインデックス値が同じ場合は判定をパスしています。
  • ヒットした場合は、flare関数で自身のイベントを発火させます。第一引数はイベント名で、第二引数にイベントに引き渡したいパラメータで、ヒットしたオブジェクトを渡しています。

使い方

当たり判定を行いたいオブジェクトにcolliderを設定します。

// コライダー設定
    player.collider.setSize(42, 64).show();
// コライダー設定
    wall.collider.show();

オブジェクトのイベント実行関数に処理を書きます。

// イベント関数定義
    player.onhit = function(e) {
      // ヒットしたオブジェクト名
      console.log(e.obj.name);  
    };
  • 関数は、on + イベント名とする必要があります。今回の場合は、onhitとなります。
  • 関数の引数eからヒットしたオブジェクトの情報が得られます。

まとめ

このようにイベントを上手く活用すれば、イベントドリブンな当たり判定処理を実現することができます。大量のオブジェクトの場合、処理が重たくなることも予想されますが、一つの拡張手段と捉えて頂ければと思います。

Discussion