TIGSource Forums

Developer => Technical => Topic started by: Craig Stern on July 12, 2010, 11:30:36 AM



Title: Using removeChild properly
Post by: Craig Stern on July 12, 2010, 11:30:36 AM
Remember that adventure game engine I posted about? Remember how it attaches instances of Monster (http://forums.tigsource.com/index.php?topic=13257.msg405224#msg405224) to the stage using, then pushes them to the char array for later reference? I've added new code for when the player attacks. It draws a rectangle named hitBox, positions it according to where the player is and which direction he's facing, then runs a hitTest to see if any Monster instances overlap hitBox. If they do, the game removes them using removeChild(). Here's the new function:

Code:
private function attack (attackType) {

if (attackType == "sword") {

var leftEdge:Number = char[0].x - (heroWidth * 0.25) - swordLength;
var rightEdge:Number = char[0].x + (heroWidth * 0.25);
var topEdge:Number = char[0].y - (heroHeight * 0.25) - swordLength;
var bottomEdge:Number = char[0].y + (heroHeight * 0.25);

var vertAlign:Number = char[0].y - (heroHeight * 0.75);
var horizAlign:Number = char[0].x - (heroWidth * 0.5);

//check for monsters and objects
for ( i = 0 ; i < char.length ; i++ ) {
if (i > 0) {

var hitBox:Sprite = new Sprite();
hitBox.graphics.beginFill(0xFF0000);
hitBox.name = "hitBox";

//add hitBox to the left
if (char[0].currentFrameLabel == "swordLeft") {
hitBox.graphics.drawRect(0, 0, swordLength, heroHeight);
addChild(hitBox);
hitBox.x = leftEdge;
hitBox.y = vertAlign;
}
//add hitBox to the right
else if (char[0].currentFrameLabel == "swordRight") {
hitBox.graphics.drawRect(0, 0, swordLength, heroHeight);
addChild(hitBox);
hitBox.x = rightEdge;
hitBox.y = vertAlign;
}
//add hitBox above
else if (char[0].currentFrameLabel == "swordUp") {
hitBox.graphics.drawRect(0, 0, heroWidth , swordLength);
addChild(hitBox);
hitBox.x = horizAlign;
hitBox.y = topEdge;
}
//add hitBox below
else if (char[0].currentFrameLabel == "swordDown") {
hitBox.graphics.drawRect(0, 0, heroWidth , swordLength);
addChild(hitBox);
hitBox.x = horizAlign;
hitBox.y = bottomEdge;
}

if (hitBox.hitTestObject(char[i])) {
removeChild(char[i]);
}

removeChild(hitBox);
}
}
} //end sword

}

Everything works fine, but there's a weird bug: after the monster instance is removed, the area where the monster once was remains unwalkable (the engine ordinarily doesn't allow the player to walk through monsters). I'm guessing that this is because I'm not using removeChild correctly here, but I'm not sure how. Would anyone be kind enough to tell me what I'm doing wrong here?


Title: Re: Using removeChild properly
Post by: ishlilith on July 12, 2010, 12:39:37 PM
Remove child only removes the objects from the display list, but they still exist. If you want to destroy the object when the hit test is true you need to splice the array. char.splice(i,1)

Keep that in mind because it will haunt you when you start seeing memory leaks.


Title: Re: Using removeChild properly
Post by: Craig Stern on July 12, 2010, 12:50:13 PM
Oh, interesting. Okay. What method would I use to remove hitBox, then? Do I need to add that to an array first as well?


Title: Re: Using removeChild properly
Post by: Draknek on July 12, 2010, 01:02:26 PM
That's kinda misleading: removing the monster objects from the array won't destroy the object. Removing them from the array means that Flash's automatic garbage collector can detect that they're not being used and can destroy them automatically (assuming of course that they really aren't being used any more).

The problem you have is that you're removing the monster from the display list (so it won't be rendered) but not from the array of monsters. So when you loop over that array to see where you can go, it's still there.

And the fact that the monster is still in that array will also prevent Flash from reclaiming any memory for that object until the array itself gets discarded, but that's a separate issue.


Title: Re: Using removeChild properly
Post by: Craig Stern on July 12, 2010, 01:09:04 PM
So if I create a rectangle and add it using addChild, then remove the thing using removeChild without ever adding it  to an array, will Flash's garbage collection sweep it up?


Title: Re: Using removeChild properly
Post by: agj on July 12, 2010, 06:50:10 PM
Yep.


Title: Re: Using removeChild properly
Post by: Craig Stern on July 12, 2010, 06:57:02 PM
Awesome. Thanks a bunch, guys! :)