0
votes

I'm trying to remove this item from the stage and keep getting this error. The code seems to work and the object is removed but the game seems kinda buggy.

Here's the full error:

ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller. at flash.display::DisplayObjectContainer/removeChild() at JumpingGame/onTick2()[E:\Folder\Folder\Folder\Folder\JumpingGame.as:95] at flash.utils::Timer/_timerDispatch() at flash.utils::Timer/tick()

The error is pointing to:

  • removeChild(enemy)
  • removeChild(leg);
  • removeChild(life);

I'm also getting:

TypeError: Error #1009: Cannot access a property or method of a null object reference

on this line theLives.text = liveLives.toString();

Here's my code:

    package 
{
    import flash.display.MovieClip;
    import flash.utils.Timer;
    import flash.events.TimerEvent;

    public class JumpingGame extends MovieClip 
    {
        public var army:Array;
        public var powerups:Array;
        public var pluslives:Array;

        public var newDoodle:doodle;

        public var enemyTimer:Timer;
        public var legTimer:Timer;
        public var lifeTimer:Timer; 

        public function JumpingGame() 
        {

            enemyTimer = new Timer( 40 );
            enemyTimer.addEventListener( TimerEvent.TIMER, onTick );
            enemyTimer.start();

            legTimer = new Timer( 20 );
            legTimer.addEventListener( TimerEvent.TIMER, onTick2 );
            legTimer.start();

            lifeTimer = new Timer( 30 );
            lifeTimer.addEventListener( TimerEvent.TIMER, onTick3 );
            lifeTimer.start();

            army = new Array();
            var newEnemy = new Enemy( 100, -15 );
            army.push( newEnemy );
            addChild( newEnemy );

            powerups = new Array();
            var newLeg = new Leg( 300, -15 );
            powerups.push( newLeg );
            addChild( newLeg );

            pluslives = new Array();
            var newLife = new Plus1( 300, -15 );
            pluslives.push( newLife );
            addChild( newLife );

            newDoodle = new doodle();
            addChild( newDoodle );
            newDoodle.y = stage.stageHeight - 50;
            newDoodle.x = stage.stageWidth / 2;
        }

        public function onTick( timerEvent:TimerEvent ):void
        {
            if (Math.random() <0.005 )
            {
                var randomX:Number = Math.random() * 320;
                var newEnemy:Enemy = new Enemy( randomX, -15 );
                army.push( newEnemy );
                addChild( newEnemy );
            }

            for each ( var enemy:Enemy in army )
            {
                enemy.moveDownABit();
                if (newDoodle.hitTestObject( enemy ) )
                {
                    //gotoAndPlay ("Game Over");
                    removeChild(enemy);
                    liveLives -= 1;
                    theLives.text = liveLives.toString();

                }
            }
        }

        public function onTick2( timerEvent:TimerEvent ):void
        {
            if (Math.random() <0.008 )
            {
                var randomX2:Number = Math.random() * 320;
                var newLeg:Leg = new Leg( randomX2, -15 );
                powerups.push( newLeg );
                addChild( newLeg );
            }

            for each ( var leg:Leg in powerups )
            {
                leg.moveDownABit2();
                if (newDoodle.hitTestObject( leg ) )
                {
                    //gotoAndPlay ("Game Over");
                    removeChild(leg);
                    liveScore += 2000;
                    theScore.text = liveScore.toString();
                }
            }

        }

        public function onTick3( timerEvent:TimerEvent ):void
        {
            if (Math.random() <0.001 )
            {
                var randomX3:Number = Math.random() * 320;
                var newLife:Plus1 = new Plus1( randomX3, -15 );
                pluslives.push( newLife );
                addChild( newLife );
            }

            for each ( var life:Plus1 in pluslives )
            {
                life.moveDownABit3();
                if (newDoodle.hitTestObject( life ) )
                {
                    //gotoAndPlay ("Game Over");
                    removeChild(life);
                    liveLives += 1;
                    theLives.text = liveLives.toString();

                }
            }

        }
    }
}
3
Where have you initialized "liveLives" variable? - Mana
I had my liveLives variable in my timeline code, I've now moved it into the class as a public variable and it seems to have done the job - Ceejay1705
When I was having similar error, I initialized the variables, in your case, enemy of Enemy type, life of Plus1 type in the class itself and the error seemed to go away. Try adding public var enemy:Enemy; , public var leg:Leg; and for all other types you have initizalized in the loop argument along with other member declarations of class and tell me if it works. - Mana
I added a public var for enemy, leg, and life, and I am still getting TypeError: Error #1009: on "enemy.parent.removeChild(enemy);". Also getting the error for "theLives.text = liveLives.toString();" still. - Ceejay1705
Just remove parent ; use the original code you had and then try to see if it works. Also for the liveLives, try tracing out the text of theLives.text and check if it is really accessible or not. - Mana

3 Answers

0
votes

Try using:

enemy.parent.removeChild(enemy)
leg.parent.removeChild(leg);
life.parent.removeChild(life);

And there is no liveLives var, or theLives textfield on stage is misspelled.

0
votes

The problem you have is caused by removing the objects from the display list without removing them from the data structure that you store them in.

Take a look at this excerpt from your code: Let's say that powerups has only one element and hitTestObject returns true. The object is removed from display.

for each ( var leg:Leg in powerups )
{
    if (newDoodle.hitTestObject( leg ) )
    {
         removeChild(leg);

the code is executed the second time. The object is still in the array. hitTestObject still returns true. The object cannot be removed from display, because it was removed already when the function was executed for the first time.

You have two data structures: the display list and your array and they are out of sync.

To solve this, remove the object from the array, not just the display list:

  1. find the index of the object that you want to remove with indexOf()
  2. remove the element at that index with splice()
0
votes

In this case, you should not use 3 array to store child objects. Simple that, you create 3 empty movie clips and add child to them. After that, you remove them when hit test.

Something like that:

    public function onTick( timerEvent:TimerEvent ):void
    {
        if (Math.random() <0.005 )
        {
            var randomX:Number = Math.random() * 320;
            var newEnemy:Enemy = new Enemy( randomX, -15 );
            armyContainer.addChild( newEnemy );
        }

        var childs:Array = [];
        for (var i:int = 0; i<armyContainer.numChildren; i++) {
            var enemy:Enemy = armyContainer.getChildAt(i) as Enemy;
            enemy.moveDownABit();
            if (newDoodle.hitTestObject( enemy ) )
            {
                //gotoAndPlay ("Game Over");
                //removeChild(enemy);
                childs.push(enemy);
                liveLives -= 1;
                theLives.text = liveLives.toString();

            }
        }

        for each ( var child:Enemy in childs )
        {
            armyContainer.removeChild(child);
        }
    }