0
votes

I have an issue here. Every five seconds the spawnEnemies is fired. It creates a movieclip, sets it position and adds it to the stage and an array. In the function checkBullet I check if the bullet hits one of the enemies. If it does, the bullet and the enemy are removed from the stage, and the enemy is spliced from the array. But an error is thrown once I hit an enemy:

TypeError: Error #1010: A term is undefined and has no properties.

If I comment out the arrayEnemies.splice(i,1) line, it works fine but then it isn't removed from the array. This is in itself not an issue, but naturally I don't like to keep unnecessary data in my array. Any help on this?

function checkBullet(event:Event) {
    if(stage.contains(mcBullet)) {
        for(var i:int = 0; i < arrayEnemies.length; i++) {
            if(arrayEnemies[i].hitTestPoint(mcBullet.x, mcBullet.y, true)) {
                stage.removeChild(mcBullet);
                this.removeChild(arrayEnemies[i]);
                arrayEnemies.splice(i,1);
                bulletOnStage = false;
            }
        }
        if(mcBullet.x > 800) {
            stage.removeChild(mcBullet);
            bulletOnStage = false;
        }
    }
}


function spawnEnemies(event:TimerEvent) {
    var enemie:MovieClip = new box_mc();
    enemie.name = "mcBox" + event.currentTarget.currentCount;
    enemie.x = 850;
    enemie.y = Math.floor(Math.random()*(1+155)+255);
    addChild(enemie);
    arrayEnemies.push(enemie);
}

function moveEnemies(event:Event) {
    for(var i:int = 0; i < arrayEnemies.length; i++) {
        arrayEnemies[i].x -= 5;
    }
}
3

3 Answers

0
votes

This will be caused by working on an array that you are interating through, you should hold a ref to the stuff you want to remove then do it after the loop.

0
votes

Your problem is that if the bullet hits two enemies, you try to remove it from the stage twice. This will throw an ArgumentError.

If you need to test against all enemies (assuming multiple enemies can be hit by the same bullet), you also need to decrement i when you remove an element from your enemy array.

function checkBullet(event:Event) {
    if(stage.contains(mcBullet)) {
        if(mcBullet.x > 800) {
            stage.removeChild(mcBullet);
            bulletOnStage = false;
        }
        for(var i:int = 0; i < arrayEnemies.length; i++) {
            if(arrayEnemies[i].hitTestPoint(mcBullet.x, mcBullet.y, true)) {
                if(stage.contains(mcBullet)){
                    stage.removeChild(mcBullet);
                }
                this.removeChild(arrayEnemies[i]);
                arrayEnemies.splice(i,1);
                bulletOnStage = false;
                i--;
            }
        }
    }
}
0
votes

Bit of an older question but thought I'd throw in my answer too for anyone that might end up here.
Like Neil said, editing an array that you're itterating through (in this case arrayEnemies) can cause concurrent update problems.

My prefered solution is to use a seperate toRemove array and remove them after the update, for example:

var enemies:Array();
//Lets assume at some point this is populated with Enemy objects

function update():void
{
    var toRemove:Array = new Array();
    //May want to keep and clear an array instead to avoid creating a new one each update

    foreach(var enemy:Enemy in enemies)
    {
        enemy.update();
        if(enemy.markedForRemoval())
            toRemove.push(enemy);
    }

    foreach(var enemy:Enemy in toRemove)
        enemies.splice(enemies.indexOf(enemy), 1);
}