gpt4 book ai didi

actionscript-3 - AS3 - MouseEvent.CLICK 触发在添加监听器之前发生的鼠标单击

转载 作者:行者123 更新时间:2023-12-04 04:54:31 25 4
gpt4 key购买 nike

我是 AS3 的新手,并制作了一个简单的 "asteroids" 游戏,其中包含一个游戏屏幕和一个 resetButton,可以让用户再次玩游戏。当用户点击重置按钮时,游戏结束屏幕和重置按钮会从舞台上移除,游戏本身与事件监听器一起添加到舞台上。其中之一是添加到 MouseEvent.CLICKstage 监听器,它调用 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

我在每个函数中添加了跟踪以查看发生了什么,这是流程:
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

我在某处读到事件总是被调度,无论是否有任何监听器实际上在监听它们,所以我怀疑我的 MouseEvent.CLICK 监听器从单击重置按钮时开始拾取鼠标按钮单击,即使虽然这个听众后来被添加到舞台上。

我没有足够的 AS3 或编程经验来确定这是否真的如此,我该怎么做才能确保 MouseEvent.CLICK 监听器不会响应在添加到舞台之前发生的任何点击,所以任何对此的帮助将不胜感激。

====

编辑

我假设我有逻辑问题或者对 AS3 和 Flash 一无所知,所以我只是使用了上面的伪代码。以下是包含生成的 .swf 的完整 .as 文件的链接
下面是完整的相关功能
https://www.dropbox.com/sh/a4rlasq8o0taw82/wP3rB6KPKS
private function startGame():void 这是从 Main 调用的
{
//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
{
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();
}

最佳答案

发生的事情是MouseEvent.CLICKbubbling 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();
}

关于actionscript-3 - AS3 - MouseEvent.CLICK 触发在添加监听器之前发生的鼠标单击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16942883/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com