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 在舞台上没有显示任何内容的主要内容,如果未能解决你的问题,请参考以下文章
Cocos2d 应用程序可在除 iPhone 4(任何操作系统)之外的所有设备上运行,CCBatchnode 在 addchild 后仅显示黑屏