mouseclick sometimes fails to work - actionscript-3

I used an eventlistener for MouseEvent.CLICK. If I click once, it sometimes wont shoot, but when I click again it shoots. Is this a problem within flash or my mouse? It's strange. Here is the code for my fire event.
function fire(m: Event)
{
//reset the cooldown
//spawn a bullet
//set the position and the rotation of the bullet
b.rotation = turret.rotation;
b.x = turret.x;
b.y = turret.y;
//add the bullet to the parent object
parent.addChild(b);
}

Related

Getting Mouse Position on Event

I have two events; mouse up and down. I get the initial position of the mouse when left button down. Then I plan to get the last position of the mouse when button released. So if there is a horizontal movement I can easily recognise. However it is problematic. Since I add listener to a movie clip, it obtain mouse x in bounds of that movie clip. What I mean is if you release button outside of the movie clip it does not work because event attached to it. Are there any turnarounds here?
m_c.addEventListener(MouseEvent.MOUSE_DOWN, StartPoint);
m_c.addEventListener(MouseEvent.MOUSE_UP, EndPoint);
function StartPoint(event:MouseEvent):void
{
initX = stage.mouseX;
}
function EndPoint(event:MouseEvent):void
{
lastX = stage.mouseX;
trace("drop ", lastX);
if(lastX < initX)
{
trace("goes left");
.
.
.
}
}
you need to addListener to stage, preferable in listener of MOUSE_DOWN
function StartPoint(event: MouseEvent) : void {
stage.addEventListener(MouseEvent.MOUSE_UP, EndPoint);
// another code
}

Flash AS3 rollover and button with ClickTag

I have a banner with a ClickTag and a hover function.
My problem is that that the user can't click on the button because of the hover function.
My code is for the ClickTag:
knap1.addEventListener(MouseEvent.CLICK, ADFclicked);
function ADFclicked(event:MouseEvent) { AdfURLNavigator.navigateToUrl( AdfFlashVarsUtil.getParameter("clickTAG"), AdfFlashVarsUtil.getParameter("landingPageTarget")); }
And for the hover function:
var holder:MovieClip = new MovieClip();
btn.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
btn.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
btn.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
function mouseOverHandler(e:MouseEvent):void{
//creating a new tooltip instance
var tooltip:Tooltip = new Tooltip();
//we tell the holder to hold our tooltip
holder = tooltip;
//positioning the tooltip on the stage
holder.x = 190;
holder.y = 280;
//adding the tooltip to the stage
addChild(tooltip);
}
function mouseOutHandler(e:MouseEvent):void{
//we remove the holder when the cursor is outside our button
removeChild(holder);
}
function mouseMoveHandler(e:MouseEvent):void{
holder.x = 190;
holder.y = 280;
}
Can anybody help?
I would assume, not seeing the entire code, that btn object is covering knap1 object so you cannot click on anything that is beneath btn.
If you want to have hover function over whole banner try using MOUSE_LEAVE event to detect mouse leaving and them MOUSE_MOVE to track if mouse is back on flash object after leaving it. As for MOUSE_MOVE event you can add listener to stage to detect mouse movement without any additional containers.
Hey you are using mousevent for hover & click at one time. So better remove addeventlistener & write the mouseover in button as inline.

AS3 - MouseEvent.CLICK fires off for mouse click that happened before the listener was added

I'm new to AS3 and have made a simple "asteroids" game with a game over screen and a resetButton that lets the user play again. When the user clicks on the reset button, the game over screen and the reset button are removed from the stage, and the game proper is added to the stage, along with eventListeners. One of these is a MouseEvent.CLICK listener added to the stage, which calls a fireBullet function. This function draws a bullet and adds it to the stage (other parts of the code then make the bullet move on the screen).
The issue that I am having is that when the user clicks on the reset button, the gameover screen is removed correctly, and the game proper (player, asteroids, eventListeners) are added to the stage correctly, but also at the same time a bullet fires even though the user has not clicked after clicking on the reset button.
My gameOver() function is like this:
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
Then, the onReset() function looks like this:
stage.removeChild() the gameover text and the resetButton
call gameStart();
The gameStart() function looks like this:
initialize variables
draw and add player and asteroids on the screen
add eventListeners including MouseEvent.Click, fireBullet
I've added traces at each function to see what's going on, and this is the flow:
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
I've read somewhere that events are dispatched all the time regardless if any listeners are actually listening for them, so my suspicion is that my MouseEvent.CLICK listener is picking up the mouse button click from the time when the reset button is clicked, even though this listener is added to the stage afterwards.
I don't have enough experience with AS3 or programming to figure out if this is really the case and what can I do to make sure that the MouseEvent.CLICK listener does not respond to any clicks that happened before it was added to the stage, so any help with this would be greatly appreciated.
====
EDIT
I was assuming I had a logic problem or didn't know something about AS3 and flash, so I just used pseudo code above. Below is a link to the full .as file including the generated .swf
And below that are the relevant functions in full
https://www.dropbox.com/sh/a4rlasq8o0taw82/wP3rB6KPKS
private function startGame():void this is called from 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 this is called from an onFrame(called every frame) function that I am not including (it's too big and not exactly relevant). it's called when all asteroids are removed.
{
//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();
}
What's happening is that MouseEvent.CLICK is a bubbling event. In Flash, events have three phases: the "capture phase", the "at target" phase, and "bubbling phase". You can read about it in this Adobe article.
Your reset button's click event handler happens in the "at target" phase. If you trace out the event's phase in the reset button click handler, it will show that event.phase is 2. Per the docs, 1 = "capture phase", 2 = "at target", 3 = "bubbling phase".
After the reset button click handler does its work, the event then bubbles back up through the display list. Since the stage is at the top of the display list, the click event "bubbles up" to the stage. And by that time, you've started the game again and added the stage's click event handler. So the stage's click handler is also triggered.
You can confirm this by tracing out the value of event.phase in your bulletFired() method:
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);
}
To fix the problem, you can stop the event from bubbling in your onReset() method:
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();
}
It sounds to me like the previous iteration of your game has not had the MOUSE.CLICK event listener removed. Even if the game is removed, the MOUSE.CLICK event will continue triggering whatever handler you added to it, eg; addEventListener(MOUSE.ClICK, ). When the game is removed you also need to removeEventListener(MOUSE.CLICK, ).

How do I stop a function of a parent movieclip when in a child of that parents?

Help!!
I have a piece of code on a mc that when the mouse is dragged it plays through that movie clip, giving a 360 spin of a product.
Inside this movieclip on different increments of the 360 spin i have child movieclips with various other animations to relate to each angle of the product.
exp..
Scene 1 > spinY_mc > AWComplete_mc
My code for the spin is written within the actions in scene1 and controls spinY_mc but once im in AWComplete_mc i do not want you to be able to drag the mouse and spin?
Im sure this is simple but im a noob at all this and am taking on a mammoth project!
Here is the code used on the movieclip (spinY_mc) I dont want this code to work when inside of its child mc (AWComplete_mc).
// Rotation of Control Body Y
spin_Y.stop();
spin_Y.buttonMode = true;
var spin_Y:MovieClip;
var offsetFrame:int = spin_Y.currentFrame;
var offsetY:Number = 0;
var percent:Number = 0;
spin_Y.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
spin_Y.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
function startDragging(e:MouseEvent):void
{
// start listening for mouse movement
spin_Y.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetY = stage.mouseY;
}
function stopDragging(e:MouseEvent):void
{
// STOP listening for mouse movement
spin_Y.removeEventListener(MouseEvent.MOUSE_MOVE,drag);
// save the current frame number;
offsetFrame = spin_Y.currentFrame;
}
// this function is called continuously while the mouse is being dragged
function drag(e:MouseEvent):void
{
// work out how far the mouse has been dragged, relative to the width of the spin_Y
// value between -1 and +1
percent = (mouseY - offsetY) / spin_Y.height;
// trace(percent);
// work out which frame to go to. offsetFrame is the frame we started from
var frame:int = Math.round(percent * spin_Y.totalFrames) + offsetFrame;
// reset when hitting the END of the spin_Y timeline
while (frame > spin_Y.totalFrames)
{
frame -= spin_Y.totalFrames;
}
// reset when hitting the START of the spin_Y timeline
while (frame <= 0)
{
frame += spin_Y.totalFrames;
}
// go to the correct frame
spin_Y.gotoAndStop(frame);
}
I'm pretty sure you just want to stop the propagation of an event from the child so it doesn't make it out to the parent. If you add a listener for the event you want to block (lets say it's mouseDown you want to block).
child_mc.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownBlocker);
private function mouseDownBlocker(event:MouseEvent):void
{
event.stopImmediatePropagation();
}
The way events work is they start at the "deepeest" child which the mouse has a hit event with, then they "bubble" up through all the parents. By stopping the propagation you block the bubbling from occurring, so the parents never get the event.

AS3 laser weapon

I am pretty new to action script 3 (I did a little bit in as2) and i am trying to create a laser gun that rotates towards the mouse and shoots when the mouse is fired.
kind of like this but in as3
http://www.freeactionscript.com/2009/04/laser-hitting-solid-objects-walls/
Thanks,
Thor
You can start to play with something like this:
//adding listener to run all the time
m.addEventListener("enterFrame", runGame);
//listener for mouse is down
stage.addEventListener("mouseDown", md);
//listener for mouse is up
stage.addEventListener("mouseUp", mu);
//to know if mouse is down
var _fire:Boolean = false;
//function for all the time
function runGame(evt:*):void
{
//to know the angle where the mouse is from the "canon" in radians
var angle:Number = Math.atan2(stage.mouseY - m.y, stage.mouseX - m.x);
//set the canon's rotation
m.rotation = 180 * angle / Math.PI;
//if mouse us down -> fire
if(_fire)
{
//create a point far away, so it will always work if the screen is normal
var point:Point = Point.polar(10000, angle);
//shoot the laser
graphics.lineTo(point.x, point.y);
}
}
//when mouse is down
function md(evt:*):void
{
//prepare graphics
graphics.clear();
graphics.lineStyle(2, 0xff0000);
graphics.moveTo(m.x, m.y);
//set fire to true
_fire = true;
}
//when mouse is up
function mu(evt:*):void
{
//set fire to false
_fire = false;
//clear the laser
graphics.clear();
}
Create a new project, place a movieclip on the stage, name it "m" (without the quotes ;)). Paste the script where the actionscript goes on frame 1.
If you want the laser to follow the mouse when it's down, change
runGame function to this:
function runGame(evt:*):void
{
//to know the angle where the mouse is from the "canon" in radians
var angle:Number = Math.atan2(stage.mouseY - m.y, stage.mouseX - m.x);
//set the canon's rotation
m.rotation = 180 * angle / Math.PI;
//if mouse us down -> fire
if(_fire)
{
//create a point far away, so it will always work if the screen is normal
var point:Point = Point.polar(10000, angle);
//shoot the laser
graphics.clear();
graphics.lineStyle(2, 0xff0000);
graphics.moveTo(m.x, m.y);
graphics.lineTo(point.x, point.y);
}
}
and md function to this:
//when mouse is down
function md(evt:*):void
{
//set fire to true
_fire = true;
}
"Epic" laser, with source. Also great site btw.
Probably best to learn the basic concepts of programming before trying to tackle things like this. Cutting/Pasting code is not programming, and can have frankenstein-ish results.
There is no magical shortcut to programming, you need to learn the basic concepts and build on them. Wonderfl.net is a cool place to check out, but I'd suggest starting out far more basic concepts to start. Until you do that, it's all going to appear as voodoo to you.