1

我正在尝试制作宇宙飞船游戏,当我使用该removeChild()方法将弹丸或敌舰移出舞台时遇到问题。

这是代码的相关部分:

var bulletsArr:Array = new Array();
var eShipsArr:Array = new Array();


for (var c = 0; c < eShipsArr.length; c++){
stage.addChild(eShipsArr[c]);
}
....

stage.addEventListener(KeyboardEvent.KEY_DOWN,shoot);

function shoot (e:KeyboardEvent):void{
if(e.keyCode==17){
    var pj:projectile = new projectile();
    pj.x = SShip.x;
    pj.y = SShip.y;
    stage.addChild(pj);
    bulletsArr.push(pj);
    if(bulletsArr.length >= 10){
       bulletsArr = bulletsArr.slice(1,10);
    }
}
}
stage.addEventListener(Event.ENTER_FRAME,checkHit);

function checkHit (e:Event):void{
for (var d = 0; d < bulletsArr.length; d++){
    for(var f = 0; f < eShipsArr.length; f++){
        if(bulletsArr[d].hitTestObject(eShipsArr[f])){
            trace(bulletsArr[d].parent);
            stage.removeChild(bulletsArr[d]); //ArgumentError: Error #2025!!!!
        }
    }
}
}

当我使用removeChild()withstage时,跟踪返回null。没有它,跟踪将返回Stage object。在这两种情况下,相同的错误都会跳转。

4

1 回答 1

0

可能是您试图删除一个已经被删除的孩子吗?

您不会将其从数组中删除,因此下一个循环或下一次checkHit调用将包括对可能已经从阶段中删除的对象的检查。即使对象不在舞台上,检查hitTestObject也会返回。true

未经测试(请注意,子弹数组正在向后迭代,以避免在删除数组元素时出现长度问题):

for (var d = bulletsArr.length - 1; d >= 0; d--){
    for(var f = 0; f < eShipsArr.length; f++){
        if(bulletsArr[d].hitTestObject(eShipsArr[f])){
            trace(bulletsArr[d].parent);
            stage.removeChild(bulletsArr[d]); 
            bulletsArr.splice(d, 1); // remove bullet from array
        }
    }
}

编辑:这是一些未经测试(正确键入)的代码,以防单个子弹可能与两艘或更多艘船相撞,您需要做的就是移除子弹:

for(var f:Number = 0; f < eShipsArr.length; f ++)
{
    for(var d:Number = bulletsArr.length - 1; d >= 0; d --)
    {
        if(bulletsArr[d].hitTestObject(eShipsArr[f]))
        {
            stage.removeChild(bulletsArr[d]);
            bulletsArr.splice(d, 1);
        }
    }
}

互换的循环,这样删除的项目符号不会再次检查。

如果一颗子弹有可能与两艘或更多艘船相撞,并且您计划对与子弹相撞的船做一些事情,那么试试这个:

    for(var d:Number = bulletsArr.length - 1; d >= 0; d --)
    {
        var bullet:DisplayObject = bulletsArr[d];
        var bulletHitSomething:Boolean = false;

        for(var f:Number = 0; f < eShipsArr.length; f ++)
        {
            if(bullet.hitTestObject(eShipsArr[f]))
            {
                if(!bulletHitSomething)
                {
                    bulletHitSomething = true;
                    stage.removeChild(bullet);
                    bulletsArr.splice(d, 1);
                }
                // do other, ship specific stuff here
            }
        }
    }

当前的子弹对象引用存储在一个变量中,并且所有检查都是针对该变量而不是使用数组访问的数组中的元素完成的。与可能访问不存在的索引的数组访问方法不同,这种方式可能对同一个项目符号进行连续检查应该没问题。还有一个变量存储子弹是否已经击中某物,这样它就不会再次尝试移除该子弹。

于 2012-10-20T13:20:20.130 回答