Copy link to clipboard
Copied
Hello, I'm making a game using Flash Pro cc. But I wonder what happens to aTile, which is dynamically declared MovieClip variable through a loop. And each aTile gets the 2 EventListener's.
for(var i:Number=0; i<pVector.length;i++){
var aTile:ATile=new ATile();
aTile.x=pVector.x;
aTile.y=pVector.y;
aTile.gotoAndStop(Math.ceil(Math.random()*Color));
nVector.push(aTile);
Spr.addChild(aTile);
aTile.addEventListener(MouseEvent.CLICK,Clicked,false,0,true);
aTile.addEventListener(Event.COMPLETE, stop,false,0,true);
// the current function ends here. what happens to aTile now ?? Is it going to be garbage collected? By the way, this piece of code runs whenever a player starts a new level of my game. And I don't make use of the aTile variable in other functions. I use only the nVector variable. And does declaring a dynamic variable in a loop mean a multiple of them are created? For example, if I loop the piece of code above 5 times, does it mean 5 aTile variables are created? Or each time you declare
var aTile:ATile=new ATile(); again, does it replace the 'old' aTile with the 'new' aTile and therefore only 1 aTile exists after the loop????
}
it should not be gc'd because it looks like it's added to the display (but that depends on whether Spr is added to the display).
Copy link to clipboard
Copied
it should not be gc'd because it looks like it's added to the display (but that depends on whether Spr is added to the display).
Copy link to clipboard
Copied
yep Spr is added to the display. So how can I make sure that aTile is gc'd?
Copy link to clipboard
Copied
it must be removed from the display list. to do that you will need a reference to it. you may be able to do that using its depth, but its easier and more reliable to assign it a name and use its name property (Spr.getChildByName() ) or add it to an array.
and the new constructor creates a new ATile. it does not replace anything previously replace.
that line reuses the aTile reference so you have no easy way to reference previous aTile's but they all still exist, are in the display list and are not eligible for gc. you've made it difficult to reference them, but they can still be referenced so they won't be gc'd.
Copy link to clipboard
Copied
Thank you for your help! I think I'm going to push the aTile in another array and then nullify them all in a loop just like I nullifed nVector at the end.
Copy link to clipboard
Copied
you'll need to remove them from the display and remove them from the array to make them available for gc. eg, if atileA is your array,
function removeF():void{
for(var i:int=atileA.length-1;i>=0;i--){
atileA.parent.removeChild(atileA);
atileA.splice(i,1);
}
}
Copy link to clipboard
Copied
so if I splice each element of the vector array atileA, there is no need to do atileA(theWholeVectorArray) = null?
Copy link to clipboard
Copied
correct: you don't need to null each array element because each reference is removed from the array
but if you were going to null them you would not use what you showed in message 10. you would use:
function removeF():void{
for(var i:int=atileA.length-1;i>=0;i--){
atileA.parent.removeChild(atileA);
atileA=null;
}
}
Copy link to clipboard
Copied
Both worked out great! Thank you kglad I appreciate your help.
Copy link to clipboard
Copied
you're welcome.
Copy link to clipboard
Copied
kglad wrote:
correct: you don't need to null each array element because each reference is removed from the array
but if you were going to null them you would not use what you showed in message 10. you would use:
function removeF():void{
for(var i:int=atileA.length-1;i>=0;i--){
atileA.parent.removeChild(atileA);
atileA=null;
}
}
It's better to actually remove the index, that way your vector has the same amount as indexes as real objects it is controlling. Note that the above code will error if you run it twice when you try to remove the null children. Try something more like:
while (nVector.length>0) {
var aTile:ATile = nVector.shift();
if (aTile.parent && aTile.parent.contains(aTile)) {
aTile.parent.removeChild(aTile);
}
}
Note that if you do push the tile into another Vector like you were talking about, it will not be eligible for garbage collection, so only do this if you're trying to implement object pooling.
Copy link to clipboard
Copied
read message 9.
(and message 1 is correct.)
Copy link to clipboard
Copied
In AS3 all variables declared in function body are hoisted by compiler to the top of the function. This means that loops do not create new declarations but reuse variables declared in the function "header".
In your case although you write it this way:
function myFunction():void
{
for (var i:int = 0; i < pVector.length; i++)
{
var aTile:ATile = new ATile();
// the rest
}
}
After compilation actual function takes this shape - note position of aTile var declaration:
function myFunction():void
{
var aTile:ATile;
for (var i:int = 0; i < pVector.length; i++)
{
aTile = new ATile();
// the rest
}
}
Copy link to clipboard
Copied
Thank you for clarification. So on this line, aTile = new ATile(), what exactly does 'new' do? Does it replace the 'old' aTile with 'new' (or fresh?) aTile which doesn't have any value yet?
Copy link to clipboard
Copied
I feel there is a gap in understanding of using variables by reference vs. by value. You should look it up.
1. new instructs Flash to create a distinct instance that per se has absolutely nothing to do with aTile variable.
2. REFERENCE to this new instance is assigned to variable aTile. aTile var is a temporary pointer to instance.
3. It does not replace old tile - it replaces reference.
4. If reference to the instance is not stored elsewhere - upon exiting of function this instance will be gced.
5. By creating another reference to the instance you prevent it from GC. One of the ways you preserve instance is by adding it to display list when using addChild.
You can look at this this way (it is a lame example but still it illustrates parts of the concept)
Say you have
1. basket;
2. basket is small and can hold only one apple;
3. table;
4. an apple;
5. apple can be placed into the basket or table;
6. dog who love apples.
7. Dog is trained not to take apples from baskets but table but is free to eat apples that are on the ground.
So, once apple is in the basket or on the table - it is safe.
If you move these entities into the realm of AS3, basket and table become declared variables, apple an instance and dog garbage collector.
What this example demonstrates is that apple exists independently of basket or table. You can put apple to the basket OR on the table OR you can put apple into basket and place basket onto the table.
1. Find apple instance (if you know whether apple is in the basket, on the table or in the basket on the table)
2. Prevent dog from eating apple.
3. Allow dog to eat it (destroy it when garbage collector kicks in) by assuring that apple is in neither basket or on the table.
Copy link to clipboard
Copied
Thank you so much for your explanation! I understand it so much better now.
Copy link to clipboard
Copied
The original poster has made a mistak in marking kglad's answer as correct, whereas Andre's answer is the one that is correct.