Sniffle6
Sniffle6

Reputation: 149

supplied DisplayObject must be a child of the caller fix

Im confused as to why my codes saying this,

My game creates a procedural generated map and the map is split into chuncks. The map works fine, i can switch areas and stuff no problem but when i delete a tree tile and re-add a grass tile then try to switch areas it tells me "The supplied DisplayObject must be a child of the caller." Iv gottn and fixed and slighty understand this problem, but i feel as if it IS a child of the calleer. idk :c

How my code is set up it creates a world class on my level class, then in that world a worldTiles sprite is created to place the tiles of the world into. This is where the tiles are originally added and deleted

This is where im pretty sure my problem is, the fucntion that deletes a tree tile and adds a grass tile

protected function mouseOnTile()
    {
        for (var i:int; i < world.tilesInWorld.length; i++)
        {
            if (mouse.hitTestObject(world.tilesInWorld[i]))
            {

                trace(world.tilesInWorld[i].Name);
                if (world.tilesInWorld[i].Name == "tree")
                {
                    var tx:int = world.tilesInWorld[i].x;
                    var ty:int = world.tilesInWorld[i].y;
                    world.worldTiles.removeChild(world.tilesInWorld[i]);
                    world.treePool.returnSprite(world.tilesInWorld[i]);
                    world.tilesInWorld.pop();

                    world.tile = world.tilePool.getSprite();
                    world.tile.width = world.TILE_SIZE;
                    world.tile.height = world.TILE_SIZE;
                    world.tile.x = tx;
                    world.tile.y = ty;
                    world.tilesInWorld.push(world.tile);
                    world.worldTiles.addChild(world.tile);
                }
            }
        }
    }

Im sure it has something to do with how im re-adding the grass tile into the worldTiles, but im confused on how else i could do it?

This is the function that deletes the tiles when you walk to a different screen section

public function deleteTiles()
    {
        if (tilesInWorld.length > 0)
        {
            for (var i:int = tilesInWorld.length - 1; i >= 0; i--)
            {
                worldTiles.removeChild(tilesInWorld[i]);
                switch (tilesInWorld[i].Name)
                {
                    case "water" :
                        waterPool.returnSprite(tilesInWorld[i]);
                        break;
                    case "shallow" :
                        shallowPool.returnSprite(tilesInWorld[i]);
                        break;
                    case "shell" :
                        shellPool.returnSprite(tilesInWorld[i]);
                        break;
                    case "sand" :
                        sandPool.returnSprite(tilesInWorld[i]);
                        break;
                    case "tree" :
                        treePool.returnSprite(tilesInWorld[i]);
                        break;
                    case "grass" :
                        tilePool.returnSprite(tilesInWorld[i]);
                        break;
                    case "rock" :
                        rockPool.returnSprite(tilesInWorld[i]);
                        break;
                    case "stone" :
                        stonePool.returnSprite(tilesInWorld[i]);
                        break;
                }
            }
            tilesInWorld.length = 0;//empty array
            generateTile();
        }
    }

This is where the tiles are generated onto the screen after being deleted

    public function generateTile()
    {
        var Xcalc:int = (X + (800 / TILE_SIZE) / GlobalCode.MAP_SCALE);
        var Ycalc:int = (Y + (600 / TILE_SIZE) / GlobalCode.MAP_SCALE);

        for (var i:int = X; i < Xcalc; i++)
        {
            for (var j:int = Y; j < Ycalc; j++)
            {
                hm = heightmap[i][j];
                if ((hm >= 0.84))
                {
                    tile = waterPool.getSprite();
                }
                else if (((hm >= 0.8) && hm < 0.84))
                {
                    tile = shallowPool.getSprite();
                }
                else if (((hm >= 0.79) && hm < 0.799))
                {
                    tile = shellPool.getSprite();
                }
                else if (((hm >= 0.7) && hm < 0.8))
                {
                    tile = sandPool.getSprite();
                }
                else if (((hm >= 0.35) && hm < 0.4))
                {
                    tile = treePool.getSprite();
                }
                else if (((hm >= 0.2) && hm < 0.7))
                {
                    tile = tilePool.getSprite();
                }
                else if (((hm >= 0.09) && hm < 0.2))
                {
                    tile = stonePool.getSprite();
                }
                else
                {
                    tile = rockPool.getSprite();
                }
                tile.width = TILE_SIZE;
                tile.height = TILE_SIZE;
                worldTiles.x = 0;
                worldTiles.y = 0;
                tile.x = TILE_SIZE * (i % 800);
                tile.y = TILE_SIZE * (j % 600);
                tilesInWorld.push(tile);
                worldTiles.addChild(tile);
            }
        }
    }

Upvotes: 1

Views: 61

Answers (2)

Josh
Josh

Reputation: 8159

I believe your problem is here:

for (var i:int; i < world.tilesInWorld.length; i++)
{
    ...
    world.worldTiles.removeChild(world.tilesInWorld[i]);
    world.treePool.returnSprite(world.tilesInWorld[i]);
    world.tilesInWorld.pop();
    ...
}

You are lopping forward through the array, using removeChild on an element in the array, and using "pop" which removes the last item of the array, not the item that was actually removed. You eventually will hit an item that was already removed. Additionally, your i pointer changes each time you pop, which means the loop will never hit every item and is fundamentally flawed.

The DisplayObject used as the argument in dO.removeChild() must be defined, non-null, and a child of dO (i.e. added with dO.addChild(). If it does not meet all of those requirements, it will error out.

To fix this, use splice() instead of pop() (which will allow you to remove a specific element in an array) and go backwards through the array (which will handle the i pointer issues)

for (var i:int = world.tilesInWorld.length - 1; i >= 0; --i)
{
    ...
    world.worldTiles.removeChild(world.tilesInWorld[i]);
    world.treePool.returnSprite(world.tilesInWorld[i]);
    world.tilesInWorld.splice(i, 1);
    ...
}

You can also loop forward through the array, but you need to modify the pointer. This is slower and more error prone than going backwards, but can work just as well (when I say slower, we're talking microseconds difference unless you are doing massive computations).

for (var i:int; i < world.tilesInWorld.length; i++)
{
    ...
    world.worldTiles.removeChild(world.tilesInWorld[i]);
    world.treePool.returnSprite(world.tilesInWorld[i]);
    world.tilesInWorld.splice(i, 1);
    --i;
    ...
}

Additionally, and this is just a syntax/readability thing, you should never rely on a datatype's default value. int will default to 0, but you should still declare it as var i:int = 0 to make it easy to change in the future, standardized and easy to read, and so that you could easily change it to a Number, which has a much, much higher max value than int but defaults to NaN.

Upvotes: 5

BotMaster
BotMaster

Reputation: 2223

This does not make any sense. Since you are removing all element from the array you can jusr forget about pop or slice and do

world.tilesInWorld.length = 0;

after the loop.

Since you are removing all object from world.worldTiles don't bother removing them one by one and do:

world.worldTiles.removeChildren()

after the loop.

Finally you are left with a simple loop where you only do:

world.treePool.returnSprite(world.tilesInWorld[i]);

It's a case (in your case and in the answer given) where you both try very hard to make a simple code as complicated as possible.

Upvotes: 0

Related Questions