AS3 - removeChild thinks it's working, but isn't removing anything (no error)

62 views Asked by At

This is similar to a question I asked a couple of weeks ago, but different code and previous solution is not working.

In a nutshell, I'm creating an array of tiles, the size of which can be selected via a dropdown menu. I want the previous grid to be removed when a new size is selected. As you can see in the code, I've put failsafes in place to ensure that the child exists and has a parent, and it passes both of these tests, but does not removeChild.

public class gridtest extends MovieClip {
    public var gridSize:Number = 225;
    public var gridBreak:Number = 15;
    public var tilesArray = new Array();
    public var tiles:MovieClip = new MovieClip();
    public var MAX_ROWS:Number = 15;
    public var MAX_COLS:Number = 15;
    public var dropDwn:MovieClip;
    //info array for the dropdown menu
    public var dropDArray:Array = new Array({label:"Select Shop Size", data:0},{label:"Size 0 - 15x15", data:225},{label:"Size 1 - 18x15", data:270},{label:"Size 2 - 18x18", data:324},
                                            {label:"Size 3 - 21x18", data:378},{label:"Size 4 - 21x21", data:441},{label:"Size 5 - 24x21", data:504},
                                            {label:"Size 6 - 24x24", data:576},{label:"Size 7 - 27x24", data:648},{label:"Size 8 - 27x27", data:729},
                                            {label:"Size 9 - 30x27", data:810},{label:"Size 10 - 30x30", data:900},{label:"Size 11 - 33x30", data:990},
                                            {label:"Size 12 - 33x33", data:1089},{label:"Size 13 - 36x33", data:1188},{label:"Size 14 - 36x36", data:1296},
                                            {label:"Size 15 - 39x36", data:1404},{label:"Size 16 - 39x39", data:1521},{label:"Size 17 - 42x39", data:1638},
                                            {label:"Size 18 - 42x42", data:1764});

    public function gridtest():void {
        //create dropdown menu based off http://www.codingcolor.com/as3/as3-drop-down-menu/
        dropDwn = new DropDown();
        dropDwn.x = 50;
        dropDwn.y = 770;
        dropDwn.init(dropDArray,150, 20,"up");
        addChild(dropDwn);
        dropDwn.addEventListener(Event.CHANGE,onDropDown);  
        }

        public function onDropDown(event:Event){
        gridSize = event.target.selectedObject.data;
        switch (gridSize){

    case 225:
    MAX_ROWS = 14;
    MAX_COLS = 14;
    break;

    case 270:
    MAX_ROWS = 17;
    MAX_COLS = 14;
    break;

    case 324:
    MAX_ROWS = 17;
    MAX_COLS = 17;
    break;

    case 378:
    MAX_ROWS = 20;
    MAX_COLS = 17;
    break;

    case 441:
    MAX_ROWS = 20;
    MAX_COLS = 20;
    break;

    case 504:
    MAX_ROWS = 23;
    MAX_COLS = 20;
    break;

    case 576:
    MAX_ROWS = 23;
    MAX_COLS = 23;
    break;

    case 648:
    MAX_ROWS = 26;
    MAX_COLS = 23;
    break;

    case 729:
    MAX_ROWS = 26;
    MAX_COLS = 26;
    break;

    case 810:
    MAX_ROWS = 29;
    MAX_COLS = 26;
    break;

    case 900:
    MAX_ROWS = 29;
    MAX_COLS = 29;
    break;

    case 990:
    MAX_ROWS = 32;
    MAX_COLS = 29;
    break;

    case 1089:
    MAX_ROWS = 32;
    MAX_COLS = 32;
    break;

    case 1188:
    MAX_ROWS = 35;
    MAX_COLS = 32;
    break;

    case 1296:
    MAX_ROWS = 35;
    MAX_COLS = 35;
    break;

    case 1404:
    MAX_ROWS = 38;
    MAX_COLS = 35;
    break;

    case 1521:
    MAX_ROWS = 38;
    MAX_COLS = 38;
    break;

    case 1638:
    MAX_ROWS = 41;
    MAX_COLS = 38;
    break;

    case 1764:
    MAX_ROWS = 41;
    MAX_COLS = 41;
    break;
    }

    var tilesArray:Array = new Array();


        //initalize the arrays
        for (var row = 0; row <= MAX_ROWS; row++)
        {
            var boolArray:Array = new Array();

            for (var col = 0; col <= MAX_COLS; col++){
                boolArray.push(false);
            }

            tilesArray.push(boolArray);
        }

        for (var row = 0; row <= MAX_ROWS; row++)
        {
            for (var col = 0; col <= MAX_COLS; col++){

                tilesArray.push(1); ;
            }
        }

        buildLevel(tilesArray);

    }

        public function buildLevel(s:Array){

            //This reports back "tiles removed", but the tiles are still on the screen...

            if(tiles != null && this.contains(tiles)){ 
                removeChild(tiles);
                trace("tiles removed");
            }

            for(var i=0; i  < MAX_ROWS + 1; i++){
                for(var o=0; o < MAX_COLS + 1; o++){
                    var currentTile:Tiles = new Tiles();
                    currentTile.x = i*15;
                    currentTile.y = o*15;
                    currentTile.name = "t"+i+"by"+o;
                    tiles.addChild(currentTile);
                    currentTile.gotoAndStop(int(s[o][i]));

                }
            }

                tiles.x = 400 - tiles.width/2;
                tiles.y = 360 - tiles.height/2;
                addChild(tiles);

        }
1

There are 1 answers

1
null On BEST ANSWER

I want the previous grid to be removed when a new size is selected.

You do this indeed. But you add it back to the display list later. See the comments I added to your code below:

public function buildLevel(s:Array){
    //This reports back "tiles removed", but the tiles are still on the screen...

    if(tiles != null && this.contains(tiles)){ 
        removeChild(tiles);     // <--------------------you remove tiles here                   
        trace("tiles removed");
    }

    for(var i=0; i  < MAX_ROWS + 1; i++){
        for(var o=0; o < MAX_COLS + 1; o++){
            var currentTile:Tiles = new Tiles();
            currentTile.x = i*15;
            currentTile.y = o*15;
            currentTile.name = "t"+i+"by"+o;
            tiles.addChild(currentTile);
            currentTile.gotoAndStop(int(s[o][i]));
        }
    }

    tiles.x = 400 - tiles.width/2;
    tiles.y = 360 - tiles.height/2;
    addChild(tiles);        // <--------------------but you add it again here       
}

If you remove the container, you do just that: you remove the container. The children of that container remain children of that container. When you add the container again, you add it with all its previous children, which makes them visible again as well.

There's no point in removing tiles while adding children to it if you add it back later anyway.

Instead of removing tiles, you want to remove all of is children. To do this, you can use the removeChildren() method that allows you to remove all children. However, you could simply replace tiles with a new empty container just the same. After all, if you throw away all the children, the benefit of reusing the single parent container is negligible.


failsafes in place to ensure that the child exists and has a parent, Actually, you didn't. The fact that this condition is true:

tiles != null && this.contains(tiles)

does not guarantee that this line:

removeChild(tiles); 

will execute without problems. I leave it up to you to read the documentation on contains() to see why this is not a failsafe. In your case it probably worked, but still, this won't work all the time. Generally speaking, those "failsafes" are usually used as "hotfixes", to patch some unexpected behaviour. This unexpected behaviour is pretty much always cause by a lack of understanding what's going on and lack of interest for the source of the underlying problem.

You clearly showed interest by asking. I hope that you agree that this "failsafe" didn't save anything. Instead of wrapping an erroneous line of code into a failsafe (which might not be as safe as you think it is), try to tackle the underlying problem and get some insight on what causes the trouble.

I hope I could provide some of that insight.