我是AS3的新手,并制作了一款简单的"asteroids"
游戏,屏幕上有游戏,resetButton
可让用户再次玩游戏。当用户点击重置按钮时,屏幕上的游戏和重置按钮将从舞台上移除,并且游戏本身将与eventListeners一起添加到舞台上。其中一个是添加到MouseEvent.CLICK
的{{1}}侦听器,它调用stage
函数。此功能绘制一个项目符号并将其添加到舞台上(代码的其他部分然后使子弹在屏幕上移动)。
我遇到的问题是,当用户点击重置按钮时,游戏切换屏幕会被正确删除,并且正确的游戏(玩家,小行星,eventListeners)会被正确地添加到舞台上,但同时也是如此即使用户在点击fireBullet
后未点击,也会触发bullet
次。
我的reset button
功能是这样的:
gameOver()
然后,stage.removeChild() all objects
stage.removeEventListener() all listeners
null out all objects
draw and add to the stage the game over text and resetButton
addEventListener(MouseEvent.CLICK, onReset) to the resetButton
函数如下所示:
onReset()
stage.removeChild() the gameover text and the resetButton
call gameStart();
函数如下所示:
gameStart()
我在每个函数中添加了跟踪以查看发生了什么,这就是流程:
initialize variables
draw and add player and asteroids on the screen
add eventListeners including MouseEvent.Click, fireBullet
我已经读过某个地方一直调度事件,无论是否有任何侦听器正在侦听它们,所以我怀疑我的MouseEvent.CLICK侦听器是从重置按钮的时间开始点击鼠标按钮单击,即使之后将此侦听器添加到舞台中。
我没有足够的AS3或编程经验来确定是否真的如此,我该怎么做才能确保added fireBullet listener //this is gameStart() function being called from Main() and adding everything to the stage the first time
fired bullet //shooting at the asteroids
fired bullet
fired bullet
fireBullet listener should have been removed //this is gameOver() being called that removes everything from the stage and adds the resetButton
clicked on reset
added fireBullet listener //gameStart() being called again from onReset() function
fired bullet //I did not click a second time after clicking on reset
监听器不响应之前发生的任何点击加入舞台,所以对此的任何帮助将不胜感激。
====
我假设我遇到了逻辑问题或者对AS3和flash一无所知,所以我只是使用上面的伪代码。下面是完整的.as文件的链接,包括生成的.swf 以下是完整的相关功能 https://www.dropbox.com/sh/a4rlasq8o0taw82/wP3rB6KPKS
MouseEvent.CLICK
这是从Main
private function startGame():void
{
//initialize variables
bulletArray = [];
cleanupBullets = [];
bulletSpeed = 10;
score = 0;
asteroid1Speed = 0;
asteroid2Speed = 0;
asteroid3Speed = 0;
asteroid4Speed = 0;
//draw player and asteroids
ship = drawPlayer();
asteroid1 = drawAsteroid();
asteroid2 = drawAsteroid();
asteroid3 = drawAsteroid();
asteroid4 = drawAsteroid();
//embarrasing and inefficient code to get random number between -5 and 5 without a 0
asteroid1Speed = Math.ceil(Math.random() * 10 -5);
if (asteroid1Speed == 0)
asteroid1Speed = returnNonZero(asteroid1Speed);
asteroid2Speed = Math.ceil(Math.random() * 10 -5);
if (asteroid2Speed == 0)
asteroid2Speed = returnNonZero(asteroid2Speed);
asteroid3Speed = Math.ceil(Math.random() * 10 -5);
if (asteroid3Speed == 0)
asteroid3Speed = returnNonZero(asteroid3Speed);
asteroid4Speed = Math.ceil(Math.random() * 10 -5);
if (asteroid4Speed == 0)
asteroid4Speed = returnNonZero(asteroid4Speed);
//trace(asteroid1Speed, asteroid2Speed, asteroid3Speed, asteroid4Speed);
//add asteroids to stage
stage.addChild(asteroid1);
stage.addChild(asteroid2);
stage.addChild(asteroid3);
stage.addChild(asteroid4);
//position player and add to stage
ship.x = 40;
ship.y = 40;
stage.addChild(ship);
//add event listeners
stage.addEventListener(Event.ENTER_FRAME, onFrame);
stage.addEventListener(MouseEvent.CLICK, fireBullet);
trace("added fireBullet listener");
}
这是从我不包括的private function gameOver():void
(称为每帧)函数中调用的(它太大而且不完全相关)。当所有小行星被移除时都会调用它。
onFrame
{
//remove any remaining bullets off the screen
for each (var item:Sprite in bulletArray)
{
stage.removeChild(item);
}
//null out objects and remove listeners
bulletArray = null;
stage.removeEventListener(Event.ENTER_FRAME, onFrame);
stage.removeEventListener(MouseEvent.CLICK, fireBullet);
//check if the listener has actually been removed
if (!(stage.hasEventListener(MouseEvent.CLICK))) {
trace("fireBullet listener should have been removed");
}
stage.removeChild(ship);
ship = null
//graphic for resetButton
resetButton = new Sprite();
resetButton.graphics.beginFill(0xFFFFFF);
resetButton.graphics.drawRect(0, 0, 100, 50);
resetButton.graphics.endFill();
//position for resetButton
resetButton.x = 250;
resetButton.y = 300;
//text for resetButton
resetTextField = new TextField();
var resetTextFormat:TextFormat = new TextFormat();
resetTextFormat.size = 30;
resetTextFormat.color = 0x000000;
resetTextField.defaultTextFormat = resetTextFormat;
resetTextField.selectable = false;
resetTextField.text = "RESET";
resetButton.addChild(resetTextField);
//add resetButton and listener
stage.addChild(resetButton);
resetButton.addEventListener(MouseEvent.CLICK, onReset);
//gameover text
gameOverTxtField = new TextField();
gameOverFormat = new TextFormat();
gameOverFormat.size = 50;
gameOverFormat.color = 0xFFFFFF;
gameOverFormat.align = "center";
gameOverTxtField.defaultTextFormat = gameOverFormat;
gameOverTxtField.selectable = false;
gameOverTxtField.text = "GAME OVER";
gameOverTxtField.width = 660;
gameOverTxtField.height = 200;
gameOverTxtField.x = -10;
gameOverTxtField.y = 20;
stage.addChild(gameOverTxtField);
}
private function onReset(e:MouseEvent):void
答案 0 :(得分:3)
正在发生的事情是MouseEvent.CLICK
是bubbling event。在Flash中,事件有三个阶段:“捕获阶段”,“目标”阶段和“冒泡阶段”。您可以在此Adobe article中阅读相关内容。
您的重置按钮的点击事件处理程序发生在“目标”阶段。如果您在重置按钮单击处理程序中跟踪事件的阶段,它将显示event.phase
为2.每docs,1 =“捕获阶段”,2 =“在目标”,3 = “冒泡阶段”。
在重置按钮单击处理程序完成其工作后,该事件随后通过显示列表进行回火。由于stage
位于显示列表的顶部,因此点击事件会“冒泡”到舞台上。到那时,你又开始了游戏并添加了舞台的点击事件处理程序。因此,舞台的点击处理程序也会被触发。
您可以通过在event.phase
方法中追踪bulletFired()
的值来确认这一点:
private function fireBullet(e:MouseEvent):void
{
// most of this time it will trace out 2 for the phase
// except when you click on an asteroid when firing or
// click the reset button
trace("fired bullet, event phase: " + e.eventPhase);
bullet = drawBullet();
bullet.y = ship.y;
bullet.x = ship.x + (ship.width / 2);
bulletArray.push(bullet);
stage.addChild(bullet);
}
要解决此问题,您可以使用onReset()
方法阻止事件冒泡:
private function onReset(e:MouseEvent):void
{
// prevent this event from bubbling
e.stopPropagation();
trace("clicked on reset");
//remove gameover objects and null them
resetButton.removeEventListener(MouseEvent.CLICK, onReset);
stage.removeChild(gameOverTxtField);
stage.removeChild(resetButton);
resetButton = null;
gameOverTxtField = null;
//restart the game
startGame();
}
答案 1 :(得分:0)
听起来像你之前的游戏迭代没有移除MOUSE.CLICK事件监听器。即使游戏被移除,MOUSE.CLICK事件也会继续触发您添加到其中的任何处理程序,例如; addEventListener(MOUSE.ClICK,)。删除游戏后,您还需要删除EventListener(MOUSE.CLICK,)。