Edited at
phina.jsDay 12

イベントドリブンな当たり判定処理を作ってみる


はじめに

phina.jsで当たり判定を行う時は、update関数の中で当たり判定用の関数を使うことがほとんどだと思います。当たり判定に関連して、去年のアドベントカレンダーの記事では、Accessoryを使ってUnityなどの当たり判定で使用されるColliderと同様なクラスを作る記事を書きました。

今回はそれを発展させて、イベントドリブンで当たり判定ができるようにしてみます。

GIF.gif

[runstantで確認]


目標

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


準備

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


<script src="http://cdn.rawgit.com/phi-jp/phina.js/v0.2.3/build/phina.js"></script>
<script src="https://rawgit.com/alkn203/phina-collider/master/collider.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からヒットしたオブジェクトの情報を得て、それをコンソールに表示しでいます。


まとめ

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