-
[RESOLVED] Remove children error
Hey Everyone,
I'm trying to remove a child of a Sprite in actionscript, where each of the children are stored in arrays as well as holder sprite, as that seemed to easiest way to go about things. The arrays are then looped through for each of the children.
However, often while testing my game, I get an error:
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
at flash.display::DisplayObjectContainer/removeChild()
at TowerDefence_fla::MainTimeline/moveBullets()
at TowerDefence_fla::MainTimeline/everyFrame()
my moveBullets function is:
Actionscript Code:
function moveBullets():void { for each (var bullet in bulletArray) { //if (bullet.bulletType = ...) bullet.y += bullet.ySpeed; bullet.x += bullet.xSpeed; bullet.stageTime += 1; for each (var enemy in enemyArray) { if (bullet.hitTestObject(enemy)) { enemy.health -= bullet.damage; if (enemy.health <= 0) { enemyHolder.removeChild(enemy); //error here :C enemyArray.splice(enemyArray.indexOf(enemy), 1); } bulletHolder.removeChild(bullet); bulletArray.splice(bulletArray.indexOf(bullet), 1); } } if (bullet.stageTime > bullet.range / bullet.speed) { bulletHolder.removeChild(bullet); bulletArray.splice(bulletArray.indexOf(bullet), 1); } } }
I can't figure out why this happens. When it does happen, the Array is spliced fine because the enemy stops moving.
Another problem I have had is that when I remove the child like that, the loop runs for 1 less time then it should, so sometime the enemies or bullets pause for a frame. What's the best way to get around this. It's possible the problems are related.
Any help would be appreciated. Thank you!
-
I think you should work with an e.target instead of having it removeChild(enemy) since you have more then just 1 I guess?
I'm not really pro at this stuff and I suggest you to wait for some usefull post XD, but if you can make such a thing I guess you understand what I mean with the target.
-
you've got a few problems there. to start, you're removing the bullet a bunch of times - once for each enemy in the inner loop, then once more in the outer loop. and, after it's removed the first time, you're going to get that error since it doesn't exist in the caller's display list after that, despite multiple calls to removeChild. the easy fix is just to test to make sure it's in the display list before attempting to remove it:
PHP Code:
if(parentElement.contains(childElement)) parentElement.removeChild(childElement);
that said, i'd make some other changes as well. not sure why you have need the arrays at all - but assuming there is a valid reason, instead of trying to manipulate them in the loop (which is going to cause problems - the array you're iterating through is potentially being changed during each iteration - it's quite likely you're going to 'miss' some elements). i'd reconstruct the array based on the child population, outside the loop.
PHP Code:
function moveBullets():void {
for each (var bullet in bulletArray) { bullet.y += bullet.ySpeed; bullet.x += bullet.xSpeed; bullet.stageTime += 1; for each (var enemy in enemyArray) { if (bullet.hitTestObject(enemy)) { enemy.health -= bullet.damage; if (enemy.health <= 0) { if(enemyHolder.contains(enemy)) enemyHolder.removeChild(enemy); } if(bulletHolder.contains(bullet)) bulletHolder.removeChild(bullet); } } if (bullet.stageTime > bullet.range / bullet.speed) { if(bulletHolder.contains(bullet)) bulletHolder.removeChild(bullet); } }
// iterator... var i:int;
// rebuild the enemyArray based on whatever hasn't been removed enemyArray = []; for(i=0;i<enemyHolder.numChildren;i++){ enemyArray[i] = enemyHolder.getChildAt(i); }
// rebuild the bulletArray based on whatever hasn't been removed bulletArray = []; for(i=0;i<bulletHolder.numChildren;i++){ bulletArray[i] = bulletHolder.getChildAt(i); }
}
that's assuming you need the arrays at all - from what's posted, there's no need - you can just run through the children of bulletHolder and enemyHolder.
hth
Last edited by moagrius; 12-09-2010 at 11:11 AM.
-
Ok, I can see why the error is occuring. I guess could also just try breaking the from the loop after it's removed the first time.
Also, when I was posting I felt kinda silly explaining how I was using Arrays, and when I thought about it, I didn't really need them. I'll probably get rid of them.
So, when I'm looping through the Sprites, I guess I should use something like:
Actionscript Code:
var i:int = 0; for(i=0;i<enemyHolder.numChildren;i++){
seeing as I'll be removing those children inside the loop?
I think I tried something like that once while trying to fix the problem, but I was unsure if it was really a good way to go about things.
Anyway, thanks! I kinda felt like there were some major problems with what I was doing. It's good to finally have an idea of how to fix it. C:
-
actually, you may want to keep the arrays and just rebuild as i demo'ed...
the problem with this:
PHP Code:
for(var i:int=0;i<container.numChildren;i++){ if(someCondition) container.removeChild(container.getChildAt(i)); }
is that the removed children will affect where the next child is, as well as numChildren. say that there were 5 children total, and the loop qualified to remove the child at 2... so the child at position 3 would then move down to position 2, but the next loop iteration would still be i=3, so it'd actually 'skip' that child. there are ways to get around it (pass the children qualified to be removed to an local ('temporary') array by reference (rather than index), then loop through that local array and remove all those that qualified. or, you could just keep your arrays and make sure not to modify them until you're done processing them, as shown above.
hth
-
Ok yeah.
Just one last question:
With the above situation, would something like:
Actionscript Code:
for(var i:int=container.numChildren ;i>0;i-=1){ if(someCondition) container.removeChild(container.getChildAt(i)); }
work, or would the positions of the children mean it would still skip some of them?
-
...or what about
Actionscript Code:
for(var i:int=0;i<container.numChildren;i++){ if(someCondition) { container.removeChild(container.getChildAt(i)); i -= 1; } }
-
the first one wouldn't, but the second one might - give it a try on something simple first and see what happens
-
Ok, I'll stop asking you questions now.
Thanks for all your help. C:
-
sorry - didn't mean to be short - i'm just slammed this week with pre-holiday deadlines... i'll check back on those when i get a minute, maybe this weekend
-
don't worry, I was just kinda thinking that I'm making you do all the testing for stuff that I could do myself.
I was just interested in asking you in case you already knew.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|