AS3 で書かれた衝突検出アルゴリズムを最適化しようとしています。
使用するとパフォーマンスが向上するかどうか疑問に思っています
Point.distance(pointObject1, pointObject2);
を使用する代わりに、2 つのオブジェクト間で
object1.hitTestObject(object2);
私のオブジェクトは多かれ少なかれ凸状なので、境界線はあまり重要ではありません。
AS3 で書かれた衝突検出アルゴリズムを最適化しようとしています。
使用するとパフォーマンスが向上するかどうか疑問に思っています
Point.distance(pointObject1, pointObject2);
を使用する代わりに、2 つのオブジェクト間で
object1.hitTestObject(object2);
私のオブジェクトは多かれ少なかれ凸状なので、境界線はあまり重要ではありません。
実際、この 2 つを比較することはできません。すべてのオブジェクトが単一ピクセルのビットマップである場合、距離テストは正常に機能します。しかし、そうではないと思います。
hitTestObject
基本的にオブジェクトの境界矩形をチェックするので、かなり高速です。ピクセルレベルのチェックを行う前に、距離をチェックして十分に近いかどうかを確認することができます。これは、コストが高く、あまりやりたくないためです。
距離チェックは、オブジェクトの周りに円形の境界を設定し、そのような 2 つの円が交差しないと判断する場合に最適です。交差する場合は、2 つのオブジェクトの形状が実際に重なり合っていることを確認するために、hitTestObject で別のチェックを行う必要があります。したがって、基本的には、距離チェックを最初のパス チェックとして使用し、hitTestObject を精度のフォローアップとして使用します。
Point.distance
テストオブジェクトが複数の子を持つ複雑なコンテナである場合、はるかに高速です (4 倍以上!)。単純なスプライトを使用すると、関数の実行時間の差は 25% 近くしかありません。
それは、Point.distance がピタゴラスの定理から斜辺を数えているだけだからです。したがって、カウントする必要があるのは、減算 2 回、加算 1 回、退化 3 回だけです。最近のプロセッサの多くはインボリューション命令を備えているため、高速です。hitTest を使用すると、さらに多くのアクションを実行できます。そして、これらのアクションの数は、hitTest'ing Sprite の複雑さとともに増加します (境界を数えるのは難しいため)。
いくつかのテストを行ったところです。その結果、私が正しかったことが確認されました。
var ar:Vector.<Sprite> = Vector.<Sprite>([]); //Sprites for hitTest
for(var i:int = 0; i < 100000; i++) {
var sp:Sprite = new Sprite(); //!The results will be other, is case of use a huge container with come objects here!
sp.graphics.drawCircle(0, 0, randomIntBetween(1, 200)); //add some shapes
sp.graphics.drawRect(0, 0, randomIntBetween(1, 200), randomIntBetween(1, 200));
sp.x = randomIntBetween(-800, 800);
sp.y = randomIntBetween(-800, 600);
sp.rotation = randomIntBetween(-360, 360); //rotate and scale in random way
sp.scaleX = sp.scaleY = Math.random();
ar.push(sp);
}
var tim:Number = new Date().time;
for each(var spr:Sprite in ar) {
ar[0].hitTestObject(spr);
}
tim = new Date().time - tim;
trace(tim);
var pn:Vector.<Point> = Vector.<Point>([]); //Points for Point.distance
for(i = 0; i < 100000; i++) {
var point:Point = new Point(randomIntBetween(-800, 800), randomIntBetween(-800, 800));
pn.push(point);
}
tim = new Date().time;
for each(var pnt:Point in pn) {
Point.distance(pn[0], pnt);
}
tim = new Date().time - tim;
trace(tim);