关于AS3中的碰撞检测算法

时间:2011-08-16 18:22:40

标签: actionscript-3 algorithm performance collision-detection

确定。因此,有几种方法可以实现碰撞检测,如R树,四叉树,BSP树递归维度聚类(RDC)。或者更多。

我的问题是我在舞台上有大约6-8个敌人,其中一些人将其中的一些移动到静止状态,而且我还有同时用三种类型的导弹射击的英雄。所以我一次在舞台上获得大约70-100个物体。

我的问题是,哪种算法用于此类问题,哪种常见做法?哪个也最有效?

我正在考虑实施Quad树,但我读到你可能很慢,或者我错了?

ps:我可以使用八叉树还是严格用于3D?

3 个答案:

答案 0 :(得分:2)

如果你只说,十个敌人和一百个子弹,我怀疑任何复杂的空间结构都将使你受益匪浅。检查每个敌人的每一颗子弹都要进行一千次检查,与维持更复杂的结构相比,性能的提升在我看来太小了。

根据游戏的速度,你可以在每隔一帧(甚至更少)检查碰撞,而不是每一帧。这将为您的碰撞检测提供100%的良好性能提升。

我建议只是这样做:

for each(var enemy:Enemy in _enemies){
    for each(var bullet:Bullet in _bullets){
         if(bullet.x > enemy.x - enemy.width / 2 && 
            bullet.x < enemy.x + enemy.width / 2 &&
            bullet.y > enemy.y - enemy.height / 2 && 
            bullet.y < enemy.y + enemy.height / 2){
                trace("collision!");
         }
     }
}

答案 1 :(得分:1)

我想我可能没有受过良好教育,无法理解空间索引数据结构如何解决两个多边形交叉的问题。也许你要检查一些其他多边形周围区域中的每个多边形是否交叉?

但我建议的一个解决方案是使用Minkowski Summing。特别是如果你的所有hitbox都是凸面的。你可以将Minkowski将导弹的命中箱与敌人的命中箱相加并将问题减少到导弹对每个敌人的点成员测试,但是如果你的导弹/敌人旋转,这将成为一个更难的问题。

希望这是足够有用的信息。

答案 2 :(得分:1)

一,你正在制作Flash游戏。二,你的弹药爆炸了。您不需要精确碰撞检测。如果您的方法简洁,100多个对象不会妨碍您。

循环你的敌人并检查距离。如果距离小于X,则爆炸,再次使用距离进行相对伤害。

// class variables
var baseDamage:Number = 50;
var splashMinDistance:Number = 72;
var splashMaxDistance:Number = 144;

var enemies:Array = // array of enemies
var ammunition:Array = // array of live ammo

function checkForContact() {
    var enemy:Enemy;
    var ammo:Ammo;

    var i:int, ic:int = enemies.length;
    var j:int, jc:int = ammo.length;

    for (i=0; i<ic; i++) {
        enemy = enemies[i];
            if (enemy == NULL) continue;
        for (j=0; j<jc; j++) {
            ammo = ammunition[j];
                    if (ammo == NULL) continue;
            if (contact(ammo, enemy)) {
                explode(ammo);
                ammo = NULL;
            }
        }
    }

    // sort ammo to remove nulls now that we're past
    // the time-sensitive part
}

function contact(ammo:Ammo, enemy:Enemy):Boolean {
    return (distance(ammo, enemy) < splashMinDistance);
}

function explode(ammo:Ammo) {
    var enemy:Enemy;
    var distance:Number;

    var i:int, ic:int = enemies.length;

    for (i=0; i<ic; i++) {
        enemy = enemies[i];
        distance = clamp(distance(ammo, enemy), splashMinDistance, Math.INT_MAX);
        if (distance > splashMaxDistance) continue;
        damageRatio = ((distance-splashMinDistance) / (splashMaxDistance-splashMinDistance));
        enemy.health -= baseDamage * damageRatio;
        if (enemy.health < 0) kill(enemy);
    }
}


function distance (o:Object, o2:Object) {
    var dx=o.x-o2.x;
    var dy=o.y-o2.y;
    return Math.sqrt(dx*dx+dy*dy);
}

最后,您不必每帧都检查碰撞。再一次,你正在进行一场flash游戏。管理您的期望。