addChild 在舞台上没有显示任何内容

Posted

技术标签:

【中文标题】addChild 在舞台上没有显示任何内容【英文标题】:addChild not displaying anything on stage 【发布时间】:2014-06-23 20:02:19 【问题描述】:

所以我试图让宇宙飞船在按下空格键时发射激光。我之前在一个纯 flex 项目中做过这个,但最近获得了创意云,并试图使用 flash 专业/flash builder 重新创建相同的效果。

不幸的是,当我创建“Laser”类的新实例并尝试使用 addChild() 将其放在舞台上时,似乎什么也没发生。

这里是主文件/文档类

    public class PlayerShip extends Sprite
    

        private var laserTimer:Timer;
        private var shipTime:Timer;
        private var upKey:Boolean;
        private var downKey:Boolean;
        private var leftKey:Boolean;
        private var rightKey:Boolean;
        private var spacebar:Boolean;
        private var utils:Utils = new Utils();

        //tuning variables
        private var MOVE_SPEED:int = 5;
        private var REVERSE_SPEED:int = 3;
        private var TURN_SPEED:int = 5;

        private var laserEmitter:shipLasers = new shipLasers(stage);

        public function PlayerShip():void
        
            super();

            addEventListener(Event.ENTER_FRAME, fly);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, movementKeysDown);
            stage.addEventListener(KeyboardEvent.KEY_UP, movementKeysUp);

            laserTimer = new Timer(1000/1000);
            laserTimer.addEventListener(TimerEvent.TIMER, fireLasers);
            laserTimer.start();
            addChild(laserEmitter);
        

        public function fly(e:Event):void 
            if(downKey) 
                SpaceShip.x -= Math.sin(utils.degreesToRadians(SpaceShip.rotation)) * REVERSE_SPEED;
                SpaceShip.y += Math.cos(utils.degreesToRadians(SpaceShip.rotation)) * REVERSE_SPEED;
            
            if(upKey) 
                SpaceShip.x += Math.sin(utils.degreesToRadians(SpaceShip.rotation)) * MOVE_SPEED;
                SpaceShip.y -= Math.cos(utils.degreesToRadians(SpaceShip.rotation)) * MOVE_SPEED;
            
            if(leftKey) 
                SpaceShip.rotation -= TURN_SPEED;
            
            if(rightKey) 
                SpaceShip.rotation += TURN_SPEED;
            
        

        public function movementKeysUp(e:KeyboardEvent):void  //rotators is key_up :P
            switch(e.keyCode) 
                case 83:
                    downKey = false;
                    break;
                case 65:
                    leftKey = false; // on "a" key_up sets left turn to false. Simple enough.
                    break;
                case 68:
                    rightKey = false; // K. "d" released makes me not turn right.
                    break;
                case 87:
                    upKey = false; // I guess case 87 is "w"
                    break;
                case 32:
                    spacebar = false;
                    break;
            
        

        public function movementKeysDown(e:KeyboardEvent):void  // key_down for movers
            switch(e.keyCode) 
                case 83:
                    downKey = true;
                    break;
                case 65:
                    leftKey = true; //so now on key_down for the "a" key it makes me go left! :D
                    break;
                case 68:
                    rightKey = true; //same as lft...
                    break;
                case 87:
                    upKey = true;
                    break;
                case 32:
                    spacebar = true;
                    break;
            
        

        public function fireLasers(e:TimerEvent) 
            if(spacebar) 
                laserEmitter.Emit(SpaceShip.x, SpaceShip.y, SpaceShip.rotation);
                addChild(laserEmitter);
            
        

        public function getShip():MovieClip 
            return SpaceShip;
        
    

这是一个单独的类,它应该创建 Laser 类的新实例并将它们放在舞台上。

    public class shipLasers extends Sprite implements Emittable
    
        var tempLaserRight:MovieClip;
        var tempLaserLeft:MovieClip;
        var laserArray:Array = [];

        public function shipLasers(stage:Stage):void
        
        


        public function Emit(x:int, y:int, rotation:Number):void 
                tempLaserRight = new Laser();
                tempLaserLeft = new Laser();

                tempLaserRight.rotation = tempLaserLeft.rotation = rotation;
                tempLaserRight.x = 200;
                tempLaserLeft.x = 210;
                tempLaserRight.y = 200;
                tempLaserLeft.y = 200;

                laserArray.push(tempLaserRight);
                laserArray.push(tempLaserLeft);
                stage.addChild(tempLaserRight);
                stage.addChild(tempLaserLeft);

                trace("Oh come on!");
        
    

谢谢!

【问题讨论】:

【参考方案1】:

您永远不会将传递的阶段引用存储在shipLasers 类中,因此您试图引用它自己的内置阶段引用,这可能是空的,因为您的shipLasers 实例不会自己添加到显示列表中。您需要存储在构造函数中传递的阶段 ref 并使用它来添加子项。

 public class shipLasers ... 
     var theStage:Stage;
     public function shipLasers(aStage:Stage)
         theStage = aStage;
     
     public function Emit(...)  
         ...
         theStage.addChild(tempLaserRight);
         thestage.addChild(tempLaserLeft);
     
 

更新:首先检查阶段可用性,然后使用阶段参考也是一个很好的做法。为此,您需要在 ship 类中收听 Event.ADDED_TO_STAGE 事件,因为它使用舞台左右和中心。实现这个的常用代码如下:

public function PlayerShip() 
    ....
    // leave here only code that does not require stage 
    if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE,init);

private function init(e:Event=null):void 
    removeEventListener(Event.ADDED_TO_STAGE,init);
    // here place all code that's left from your initialization process
    laserEmitter=new shipLasers(stage);
    stage.addEventListener(KeyboardEvent.KEY_DOWN, movementKeysDown);
    stage.addEventListener(KeyboardEvent.KEY_UP, movementKeysUp);
    // etc.

【讨论】:

我现在有一个阶段变量,它获取从构造函数传入的阶段对象,并且如您所展示的那样从该新阶段对象调用 addChild,但我仍然只得到一些跟踪语句原因。 您必须跟踪的不仅仅是“加油”,比如激光的 X 和 Y 位置、它们的旋转,添加后您还可以获得激光目标点的localToGlobal() 转换。您的激光可能已超出舞台的可见部分。 另外,请参阅更新的答案,了解另一个可能导致您的游戏无法正常运行的错误。 我在 PlayerShip 的构造函数中放入了 init 函数,并跟踪了激光的坐标和旋转,并使用了 localToGlobal,它们实际上显示在我期望的位置(我检查了另一个 SO 主题正确使用 localToGlobal 所以我认为我使用它正确)。我不知道这是否真的是个问题,但我已经尝试将背景移出舞台,以确保它们不会以某种方式落后于它,这也不是问题。 使用localToGlobal()应该像tempLaserRight.localToGlobal(new Point()),调用localToGlobal()的对象应该是你需要确定的位置。 请勿shipLasers 类中使用 this 或空限定符,如果这样做,您将收到虚假值,因为您的 laserEmitter 不是包含这些激光的显示列表的一部分.

以上是关于addChild 在舞台上没有显示任何内容的主要内容,如果未能解决你的问题,请参考以下文章

正确使用 addChild

Cocos2d 应用程序可在除 iPhone 4(任何操作系统)之外的所有设备上运行,CCBatchnode 在 addchild 后仅显示黑屏

动态附加组件

显示对象的 ActionScript 本地 X 和 Y 坐标?

变量 addChild 没有定义?

使用 addChild() 时,MovieClip 没有播放动画