SVGのPathの当たり判定を取る方法

Pathで囲まれたSVGの当たり判定を取ることができれば、ベクター形状の間で正確に当たり判定が取れる。現代版1ドットのエクスタシーを魅せることが可能だ。以下の様なコードを書いた。

stars stars

SVG自体にはバウンディングボックスを使ったおおまかな当たり判定の仕組みしかないので、厳密な当たり判定は自前でなんとかするしかない。

この記事にあるようにまずバウンディングボックスでの衝突を判定し、衝突している場合のみパスを使った厳密な当たり判定を取るのがパフォーマンスの面から見て望ましい。

バウンディングボックスはこのスレにあるように、getBBox()で取ったバウンディングボックスを自力でtransformすることで得た。

パスを使った当たり判定は、まじめにパスとパスの交差を計算するととても大変なので、いくつかの線分で近似するのが現実的だろう。SVGPathElementにはgetPointAtLength()というパスの始点から特定の長さの位置にある点を取る関数があるのでこれを利用する。getTotalLength()で取ったパス全体の長さを適当な数で割ってその長さごとの点で囲まれた多角形を当たり判定とする。

実際に当たり判定を行うのはsat-jsに丸投げ。ただsat-jsのPolygonの当たり判定は凸面のポリゴンにしか対応してないので、凹面の多角形は適当な凸面ポリゴンに分割する必要がある。今回は安直に多角形の中心点と各辺から成る三角形に分割した。

こうすればそこそこ正確に当たり判定を取れるはずだが、処理としては結構重たいかも。ゲームで使っていいスピードが出るかどうかは微妙かもしれず。