错误#2025:提供的DisplayObject必须是调用方的子级 - 不确定如何修复

时间:2013-05-15 14:24:30

标签: actionscript-3 flash-cs6

所以我得到一个错误,说明提供的DisplayObject必须是调用者的子代。发生的事情是我的游戏第一次工作,点击'Play'按钮调用startGame功能并删除菜单以便显示游戏,但随后在游戏结束时playAgainBtn单击1}},而不是简单地再次玩游戏/重新启动游戏,我收到此错误:

ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller. at flash.display::DisplayObjectContainer/removeChild()

具体指向这一行:

menuLayer.removeChild(mainMenu);

以下是代码:

package  {
    import flash.display.MovieClip;
    import flash.display.LoaderInfo;
    import flash.display.Sprite;
    import flash.display.DisplayObject;
    import flash.display.Stage;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.utils.Timer;
    import flash.ui.Mouse;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.text.TextFormat;
    import flash.text.TextField;
    import flash.text.AntiAliasType;
    import flash.display.Loader;
    import flash.net.URLRequest;
    import flash.net.URLLoader;
    import flash.system.LoaderContext;
    import flash.display.Sprite;
    import flash.net.Socket;
    import caurina.transitions.Tweener;
    import flash.text.Font;

    public class Main extends MovieClip {

    public static var backgroundLayer:Sprite = new Sprite;
    public static var gameLayer:Sprite = new Sprite;
    public static var interfaceLayer:Sprite = new Sprite;
    public static var endGameLayer:Sprite = new Sprite;
    public static var menuLayer:Sprite = new Sprite;
    public static var gameOverLayer:Sprite = new Sprite;
    public static var howToLayer:Sprite = new Sprite;
    public static var scoresLayer:Sprite = new Sprite;
    public static var aboutLayer:Sprite = new Sprite;

    public var mainMenu:menuMain = new menuMain;
    public var gameEnd:endGame = new endGame;
    public var howtoPlay:howToPlay = new howToPlay;
    public var gameAbout:aboutGame = new aboutGame;
    public var intro:IntroSound = new IntroSound();
    public var soundControl:SoundChannel = new SoundChannel();

    public var gameTime:int;
    public var levelDuration:int;

    public var crosshair:crosshair_mc;
    static var score:Number;

    var enemyShipTimer:Timer;
    var enemyShipTimerMed:Timer;
    var enemyShipTimerSmall:Timer;

    static var scoreHeader:TextField = new TextField();
    static var scoreText:TextField = new TextField();
    static var timeHeader:TextField = new TextField();
    static var timeText:TextField = new TextField();

    static var scoreFormat = new TextFormat("Arial Rounded MT Bold", 20, 0xFFFFFF);
    public var gameOverscoreFormat = new TextFormat("Arial Rounded MT Bold", 32, 0xFFFFFF);

   public function Main()
   {
        addChild(gameLayer);
        addChild(backgroundLayer);
        addChild(interfaceLayer);
        addChild(menuLayer);

        menuLayer.addChild(mainMenu);
        interfaceLayer.addChild(howtoPlay);
        interfaceLayer.addChild(gameEnd);
        interfaceLayer.addChild(gameAbout);
        soundControl = intro.play(0, 100);
        addMenuListeners();
   }

   public function menuReturn(e:Event)
   {

        addChild(gameLayer);
        addChild(backgroundLayer);
        addChild(interfaceLayer);
        addChild(menuLayer);

        menuLayer.addChild(mainMenu);
        interfaceLayer.addChild(howtoPlay);
        interfaceLayer.addChild(gameEnd);
        interfaceLayer.addChild(gameAbout);
   }

   public function showAbout(e:Event)
   {
      menuLayer.removeChild(mainMenu);
      interfaceLayer.addChild(gameAbout);
   }

   public function startGame(e:Event)
   {
        removeMenuListeners();
        soundControl.stop();
        interfaceLayer.removeChild(howtoPlay);
        interfaceLayer.removeChild(gameAbout);
        interfaceLayer.removeChild(gameEnd);
        menuLayer.removeChild(mainMenu);

        levelDuration = 30;
        gameTime = levelDuration;
        var gameTimer:Timer = new Timer(1000,levelDuration);
        gameTimer.addEventListener(TimerEvent.TIMER, updateTime);
        gameTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timeExpired)
        gameTimer.start();

        scoreHeader = new TextField();
        scoreHeader.text = String("Score: ");
        interfaceLayer.addChild(scoreHeader);
        scoreHeader.x = 5;
        scoreHeader.selectable = false;
        scoreHeader.embedFonts = true;
        scoreHeader.antiAliasType = AntiAliasType.ADVANCED;

        scoreText = new TextField();
        scoreText.text = String("0");
        interfaceLayer.addChild(scoreText);
        scoreText.x = 75;
        scoreText.y = 0;
        scoreText.selectable = false;
        scoreText.embedFonts = true;
        scoreText.antiAliasType = AntiAliasType.ADVANCED;

        timeHeader = new TextField();
        timeHeader.text = String("Time: ");
        interfaceLayer.addChild(timeHeader);
        timeHeader.x = 500;
        timeHeader.y = 0;
        timeHeader.selectable = false;
        timeHeader.embedFonts = true;
        timeHeader.antiAliasType = AntiAliasType.ADVANCED;

        timeText = new TextField();
        timeText.text = gameTime.toString();
        interfaceLayer.addChild(timeText);
        timeText.x = 558;
        timeText.y = 0;
        timeText.selectable = false;
        timeText.embedFonts = true;
        timeText.antiAliasType = AntiAliasType.ADVANCED;

        scoreHeader.setTextFormat(scoreFormat);
        scoreText.setTextFormat(scoreFormat);
        timeHeader.setTextFormat(scoreFormat);
        timeText.setTextFormat(scoreFormat);

        var timeScorebg:Sprite = new Sprite();
        backgroundLayer.addChild(timeScorebg);
        timeScorebg.graphics.beginFill(0x333333);
        timeScorebg.graphics.drawRect(0,0,600,30);
        timeScorebg.graphics.endFill();
        timeScorebg.y = 0;

        enemyShipTimer = new Timer(2000);
        enemyShipTimer.addEventListener("timer", sendEnemy);
        enemyShipTimer.start();

        enemyShipTimerMed = new Timer(2500);
        enemyShipTimerMed.addEventListener("timer", sendEnemyMed);
        enemyShipTimerMed.start();

        enemyShipTimerSmall = new Timer(2750);
        enemyShipTimerSmall.addEventListener("timer", sendEnemySmall);
        enemyShipTimerSmall.start();

        crosshair = new crosshair_mc();
        gameLayer.addChild(crosshair);

        crosshair.mouseEnabled = crosshair.mouseChildren = false;

        Mouse.hide();

        gameLayer.addEventListener(Event.ENTER_FRAME, moveCursor);
        resetScore();
    }

    function addMenuListeners():void
    {
        mainMenu.playBtn.addEventListener(MouseEvent.CLICK, startGame);
        mainMenu.howToPlayBtn.addEventListener(MouseEvent.CLICK, showInstructions);
        mainMenu.aboutBtn.addEventListener(MouseEvent.CLICK, showAbout);
        howtoPlay.backBtn.addEventListener(MouseEvent.CLICK, menuReturn);
        gameEnd.playagainBtn.addEventListener(MouseEvent.CLICK, startGame);
        gameAbout.backBtn.addEventListener(MouseEvent.CLICK, menuReturn);
    }

    function removeMenuListeners():void
    {
        mainMenu.playBtn.removeEventListener(MouseEvent.CLICK, startGame);
        mainMenu.howToPlayBtn.removeEventListener(MouseEvent.CLICK, showInstructions);
        mainMenu.aboutBtn.removeEventListener(MouseEvent.CLICK, showAbout);
        howtoPlay.backBtn.removeEventListener(MouseEvent.CLICK, menuReturn);
        gameEnd.playagainBtn.removeEventListener(MouseEvent.CLICK, startGame);
        gameAbout.backBtn.removeEventListener(MouseEvent.CLICK, menuReturn);
    }

    public function showInstructions(e:Event)
    {
        menuLayer.removeChild(mainMenu);
        interfaceLayer.addChild(howtoPlay);
    }

    function sendEnemy(e:Event)
    {
        var enemy = new EnemyShip();
        gameLayer.addChild(enemy);
        gameLayer.addChild(crosshair);
    }

    function sendEnemyMed(e:Event)
    {
        var enemymed = new EnemyShipMed();
        gameLayer.addChild(enemymed);
        gameLayer.addChild(crosshair);
    }

    function sendEnemySmall(e:Event)
    {
        var enemysmall = new EnemyShipSmall();
        gameLayer.addChild(enemysmall);
        gameLayer.addChild(crosshair);
    }

    static function updateScore(points)
    {
        score += points;
        scoreText.text = String(score);
        scoreHeader.setTextFormat(scoreFormat);
        scoreText.setTextFormat(scoreFormat);
    }

    static function resetScore()
    {
        score = 0;
        scoreText.text = String(score);
        scoreText.setTextFormat(scoreFormat);
    }

    function updateTime(e:TimerEvent):void
    {
        gameTime--;
        timeText.defaultTextFormat = scoreFormat;
        timeText.text = String(gameTime);
    }

    function timeExpired(e:TimerEvent):void
    {
        var gameTimer:Timer = e.target as Timer;
        gameTimer.removeEventListener(TimerEvent.TIMER, updateTime)
        gameTimer.removeEventListener(TimerEvent.TIMER, timeExpired)

        interfaceLayer.addChild(gameEnd);

        var thisFont:Font = new myFont();
        var myFormat:TextFormat = new TextFormat();
        myFormat.font = thisFont.fontName;

        scoreText = new TextField();
        scoreText.defaultTextFormat = myFormat;
        scoreText.text = String(score);
        interfaceLayer.addChild(scoreText);
        scoreText.x = 278;
        scoreText.y = 180;
        scoreText.selectable = false;
        scoreText.embedFonts = true;
        scoreText.antiAliasType = AntiAliasType.ADVANCED;
        scoreText.setTextFormat(gameOverscoreFormat);

        Mouse.show();
        removeChild(gameLayer);
        addMenuListeners();
    }

    function moveCursor(event:Event) 
    {
      crosshair.x=mouseX;
      crosshair.y=mouseY;
    }
    }
  }

我不太确定如何解决这个问题,因此欢迎任何建议或解决方案。我不能让它以我想要的方式工作而不会出错。

感谢。

6 个答案:

答案 0 :(得分:1)

我认为问题是在第二次播放时调用menuLayer.removeChild(mainMenu);会导致错误,因为您已经将其删除了一次。最快的解决方案是在您尝试删除之前检查menuLayer是否包含mainMenu:

if(menuLayer contains mainMenu)
    menuLayer.removeChild(mainMenu);

(请注意,我现在无法访问IDE,但我认为这应该有效)

更强大的解决方案是在从主菜单中单击播放按钮时调用不同的方法,从mainMenu中删除menuLayer,然后调用startGame(其中为{{ 1}}直接调用playAgain

修改 好的,我明白你的意思了。也许是这样的事情:

startGame

答案 1 :(得分:0)

我不知道为什么你的代码不能正常工作,但是没有必要担心,请尝试:

 MovieClip(menuLayer.parent).removeChild(menuLayer);

答案 2 :(得分:0)

您在两个不同的位置删除mainMenu。我的猜测是它被删除一次,然后再被删除。

if ( mainMenu.parent == menuLayer ) {
    menuLayer.removeChild( mainMenu );
}

这将验证mainMenu在删除之前实际上是menuLayer的子节点。您无法从父实际上不是父项的父项中删除子项。想象一下,州政府带走了一个孩子并从绑架者手中接过他们的监护权。这不是最漂亮的比较,但它给出了正确的想法。

答案 3 :(得分:0)

如果没有看到如何处理游戏,我无法验证这一点,但我认为可能的问题是,每次玩游戏时你都不会删除你的事件监听器。因此,当您返回主菜单并再次添加它们时,您现在可以使用playAgainBtn的两个侦听器。

所以当你结束游戏并点击playAgainBtn时,startGame会被称为TWICE。所以第一次将它移除就好了,第二次 - 没有什么可以删除的。根据您当前的设计,所有事件监听器都可能存在此问题。

如果是这种情况,您只需在删除菜单时删除事件侦听器。

我建议无论何时激活菜单,都要添加监听器,然后在隐藏它时将其删除。也许有两个方法,addMenuListeners和removeMenuListeners

您可以创建这两个函数并在适当的地方使用它们:

   function addMenuListeners():void
   {
        mainMenu.playBtn.addEventListener(MouseEvent.CLICK, startGame);
        mainMenu.howToPlayBtn.addEventListener(MouseEvent.CLICK, showInstructions);
        mainMenu.aboutBtn.addEventListener(MouseEvent.CLICK, showAbout);
        howtoPlay.backBtn.addEventListener(MouseEvent.CLICK, menuReturn);
        gameEnd.playagainBtn.addEventListener(MouseEvent.CLICK, startGame);
        gameAbout.backBtn.addEventListener(MouseEvent.CLICK, menuReturn);
   }

function removeMenuListeners():void
{
        mainMenu.playBtn.removeEventListener(MouseEvent.CLICK, startGame);
        mainMenu.howToPlayBtn.removeEventListener(MouseEvent.CLICK, showInstructions);
        mainMenu.aboutBtn.removeEventListener(MouseEvent.CLICK, showAbout);
        howtoPlay.backBtn.removeEventListener(MouseEvent.CLICK, menuReturn);
        gameEnd.playagainBtn.removeEventListener(MouseEvent.CLICK, startGame);
        gameAbout.backBtn.removeEventListener(MouseEvent.CLICK, menuReturn);
}

如果遵循在不使用时始终删除事件侦听器的规则,则可以避免此问题。

答案 4 :(得分:0)

if(mainMenu.parent){mainmenu.parent.removeChild(mainMenu);}或者它已经被删除/根本没有添加?

答案 5 :(得分:0)

更改此行

menuLayer.removeChild(mainMenu);

到这个..

if (mainMenu.parent != null && mainMenu.parent == menuLayer)
{
  menuLayer.removeChild(mainMenu);
}

希望它会解决。