我正在制作一个游戏作为学校的项目,最近在as3中遇到了一些问题。我正在制作一个你正在机动船避开小行星的游戏,并且只是添加了这个功能,这样当你击中一颗小行星时,你的船就会通过stage.removeChild从舞台上移走。一切都很好,直到你真的碰到了什么,然后出现了这个错误(我的意思是很多,就像游戏开启时它一直在重复):
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
at flash.display::DisplayObjectContainer/removeChild()
at Function/com.asgamer.basics1:Engine/private:loop/com.asgamer.basics1:krash()[C:\Users\nti\Desktop\Ship game\com\asgamer\basics1\Engine.as:54]
这是代码(我标记了第54行):
package com.asgamer.basics1
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
public class Engine extends MovieClip
{
private var numStars:int = 80;
private var enemyList:Array = new Array();
private var ourShip:Ship;
public function Engine() : void
{
ourShip = new Ship(stage);
stage.addChild(ourShip);
ourShip.x = stage.stageWidth / 2;
ourShip.y = stage.stageHeight / 2;
for (var i:int = 0; i < numStars; i++)
{
stage.addChildAt(new Star(stage), stage.getChildIndex(ourShip));
}
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function loop(e:Event) : void
{
if (Math.floor(Math.random() * 14) == 5)
{
var enemy:Asteroid = new Asteroid(stage);
enemy.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy, false, 0, true);
enemyList.push(enemy);
stage.addChild(enemy);
stage.addEventListener(Event.ENTER_FRAME, krash);
function krash(e:Event):void{
if (enemy.hitTestObject(ourShip)==true){
stage.removeChild(ourShip); <-------------------------- LINE 54
}
}
}
}
private function removeEnemy(e:Event)
{
enemyList.splice(enemyList.indexOf(e.currentTarget), 1);
}
}
}
请记住,我是编码的初学者,这可以解释代码中其他可能的“错误”。 :)
答案 0 :(得分:1)
正如前面提到的那样,问题是你在实际将其从舞台上移除后不会清理你的ourShip
。请注意,一旦您致电stage.removeChild()
,船舶不再在舞台上,但碰撞检查仍然存在,因为您没有删除输入框架侦听器。您应该将删除侦听器语句添加到删除该船的代码分支。
stage.addEventListener(Event.ENTER_FRAME, krash);
... // other code
function krash(e:Event):void{
for each (var enemy in enemyList)
if (enemy.hitTestObject(ourShip)==true){
stage.removeChild(ourShip);
stage.removeEventListener(Event.ENTER_FRAME, krash); // THIS line
}
}
编辑:首先,将addEventListener(Event.ENTER_FRAME, krash)
行移动到您添加loop
侦听器的位置,因为您不希望拥有多个这样的一个,其次,创建一个hitTestObject
与enemyList
的完整循环。上面的代码已更新。
注意:可能需要在侦听器代码中出现一些有效性检查,例如,如果已经删除了ourShip
,您可能只是return
来自事件侦听器函数,或者跳过命中测试检查。一旦你开始进入单个主进入帧监听器,这也会对你有所帮助 - 一般来说,将一个函数作为事件监听器比同一事件的许多函数更快,并且还可以帮助你整合想要执行的每一段代码。在一个地方响应某个特定事件,而不是搜索你将该声明放在哪里。这也有助于不定期添加/删除监听器,尽管有时与听众一起玩可以让你做得更好。
答案 1 :(得分:0)
问题是由于您尝试多次从ourShip
删除stage
而引起的。更确切地说,每个Event.ENTER_FRAME
事件。