AS3 - removeEventListener(ADDED_TO_STAGE)

时间:2012-11-20 16:13:57

标签: actionscript-3 events actionscript event-handling

我在尝试删除Event.ADD_TO_STAGE时遇到了一些问题,基本上在游戏中我已经开发了一旦生命小于或等于零游戏将结束并切换到屏幕上的游戏但是当我这样做时它会因为这个错误而退缩。

ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.   
at flash.display::DisplayObjectContainer/removeChild()
at States/changeState()
at AvoiderGame/onTick()
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()

然后变成..

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Enemy/StayOnScreen()
at AvoiderGame/onTick()
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()

我不完全确定为什么 - 任何人都可以澄清它为什么以及如何解决它?

package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.Event;
import flash.events.TimerEvent;
import com.freeactionscript.CollisionTest;
import flash.display.Stage;

public class AvoiderGame extends MovieClip
{
    var theCallBackFunction:Function;

    public static var enemyArray:Array;
    public var enemy:Enemy
    public var Background:gameBackground;
    public var Lives:Number = 3;

    public var avatar:Avatar;
    public var gameTimer:Timer;

    private var _collisionTest:CollisionTest;
    private var numStars:int = 80;

    private var fireTimer:Timer; //causes delay between fires
    private var canFire:Boolean = true; //can you fire a laser

    public function AvoiderGame(callBack)
    {
        this.addEventListener(Event.ADDED_TO_STAGE, init);
        theCallBackFunction = callBack;
    }

    private function init(e:Event):void
    {
        Background = new gameBackground();
        addChild(Background);

        enemyArray = new Array();

        avatar = new Avatar(stage);
        addChild(avatar);

        avatar.x = stage.stageWidth / 2;
        avatar.y = stage.stageHeight / 2;

        _collisionTest = new CollisionTest();

        gameTimer = new Timer(25);
        gameTimer.addEventListener(TimerEvent.TIMER, onTick);
        gameTimer.start();

        for (var i:int = 0; i < numStars; i++)
        {
            stage.addChildAt(new Star(stage), 1);
        }

        fireTimer = new Timer(1000, 1);
        fireTimer.addEventListener(TimerEvent.TIMER, fireTimerHandler, false, 0, true);
        fireTimer.start();
    }

    public function onTick(timerEvent:TimerEvent):void 
    {

        if (Math.random() < 0.1)
        {
            trace('array length: ', AvoiderGame.enemyArray.length);
            enemy = new Enemy(Math.round(1 + (500 - 1) * Math.random()), - 28, stage);
            enemyArray.push(enemy);
            addChild(enemy);
            enemy.gotoAndStop("Enemy" + Math.round(1 + (5 - 1) * Math.random()))
        }

        canFire = avatar.UpdateAvatar(canFire);
        if (canFire == false)
        {
            fireTimer.start();
        }
        avatar.StayOnScreen();

        for each (var enemy:Enemy in enemyArray)
        {
            enemy.moveDown();
            enemy.StayOnScreen();
            if (_collisionTest.complex(enemy, avatar)) 
            {
                gameTimer.stop();
                for each (var enemy:Enemy in enemyArray)
                {
                    for(var i:int = 0; i < enemyArray.length; i++)
                    {
                        removeChild(enemyArray[i]);
                        enemyArray.splice(i, 1); //remove the i'th element as i'th element is the enemy containing the ID of hit enemy
                    }
                }
                Lives--;
                trace('lives: ', Lives);
                gameTimer.start();
            }
        }

        if (Lives == 0)
        {
            removeEventListener(Event.ADDED_TO_STAGE, init)
            theCallBackFunction(this, "over");
        }
    }
    private function fireTimerHandler(e:TimerEvent) : void
    {
        //timer ran, we can fire again.
        canFire = true;
    }
}
}

1 个答案:

答案 0 :(得分:1)

//使用弱引用,以便在必要时处理侦听器

this.addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);

private function init(e:Event):void {

//remove this now as we have added the object to the stage
this.removeEventListener(Event.ADDED_TO_STAGE, init);

//add a new listener that will fire when the object is removed from stage
this.addEventListener(Event.REMOVED_FROM_STAGE, reset, false, 0, true);

...

private function reset(e:Event):void {

//this function is called when the object has been removed from the stage
this.removeEventListener(Event.REMOVED_FROM_STAGE, reset);

//now make sure all timers and stopped and nulled if required
//as well as all objects removed from stage and nulled if required. e.g.

fireTimer.stop();
fireTimer = null;

enemyArray = [];
enemyArray = null;

enemy

removeChild(Background);
Background = null;

removeChild(avatar);
avatar = null;

gameTimer.stop();
gameTimer = null;

_collisionTest = null;

}

// NB。您正在为舞台添加星星,并且无法引用它们以将其删除。

for (var i:int = 0; i < numStars; i++)
{
   stage.addChildAt(new Star(stage), 1);
}

//您可能希望将它们添加到数组中,以便删除它们。

var starArray = [];

for (var i:int = 0; i < numStars; i++)
{
   var newStar:Star = new Star(stage);
   stage.addChildAt(newStar, 1);
   starArray.push(newStar);
}

然后删除它们:

for (var i:int = starArray.length; i > 0; i--)
{

   stage.removeChild(starArray[starArray.length-1]);

}
starArray = [];
starArray = null;