AS3 - Button inside MovieClip triggers MC's event - actionscript-3

On stage, I have a MovieClip named "mc" with a simple rectangle drawn inside. mc also has a Button child named "btn" which is another simple rectangle ( smaller than mc's rectangle obviously). Then I have this code on stage.
function mcDown( _e:MouseEvent):void{
trace( "mc" );
}
function btnClick( _e:MouseEvent):void{
trace( "btn" );
}
mc.addEventListener( MouseEvent.MOUSE_DOWN, mcDown );
mc.btn.addEventListener( MouseEvent.CLICK, btnClick );
The problem I am having is when click the button, mcDown event is also triggered and traces both "mc" and "btn".
How can I make it so that when I click the button, it triggers only btnClick and not mcDown along? I tried MOUSE_UP instead of CLICK, same problem. And mcDown event has to remain MOUSE_DOWN.

There is no way to prevent bubbling except setting the bubbles parameter as false in the dispatchEvent.
dispatchEvent(EVENT_TYPE, BUBBLES,....);
However, you can avoid the bubbling by doing a check. Just have the below line as first line of your listener function it avoids the events dispatched from all objects other then targets.
if(e.eventPhase != EventPhase.AT_TARGET) return;
So, for your sample code, when you click on the button both the events dispatches but in the mcDown function it won't execute after the above said line.

If you add button in a MC, and you click on the button, you also click on the MC, because the part of the MC that is under the button is still there and it runes the function for the whole of the MC, you can't remove it.
So it's good idea to make a function that will check if the button is pressed, otherwise it will run the function for the whole of the MC.
This one should do it.
//add this in you constructor
mc.addEventListener(MouseEvent.MOUSE_DOWN, myReleaseFunc);
function myReleaseFunc(e:MouseEvent):void {
if(e.currentTarget.name == Btn1) //Btn1 is instance name for a button
{
Btn_func1();
}
else if(e.currentTarget.name == Btn2) //Btn2 is another button.
{
Btn_func2();
//For every button you'll need to add another function and if statement to check if that button was clicked.
}
else
{
Mc_func();
}
}
// this outside the main class
function Mc_func():void{
//you code here
}
function Btn_func1():void{
//you code here
}
function Btn_func2():void{
//you code here
}
I think that this way is much more effiecient and it will works better and faster and you'll have a lot smaller chance of overloading the system.

Related

keycode for MouseEvent?

So to my understanding, there are keycodes to represent the keystrokes, for example:
public function left(e:KeyboardEvent):void
{
if (e.keycode == 65)
{
leftKey = true;
}
}
I want to do something similar with this logic and apply it for Mouse Events. I've searched on Google but haven't found much results for Flashdevelop AS3. Would there be a keycode to represent Mouse Events?
For example:
stage.addEventListener(MouseEvent.MOUSE_DOWN, down);
stage.addEventListener(MouseEvent.MOUSE_MOVE, move);
stage.addEventListener(MouseEvent.CLICK, click);
public function down(e:MouseEvent):void
{
if (e.keycode == ?)
}
public function move(e:MouseEvent):void
{
if (e.keycode == ?)
}
public function click(e:MouseEvent):void
{
if (e.keycode == ?)
}
Thanks in advance!
When you fire a mouse event that has a listener attached to it, then the function associated with that listener will get called. Period. You don't need to then, again, check to see if the mouse event happened. That's the whole beauty of event listeners. Just to make sure you get it, I'll post an example.
stage.addEventListener(MouseEvent.CLICK,mClick);
Great. We added a listener to the stage. Now, any time you click anywhere on the stage, this listener will cause that mClick function to get called. Now we write the mClick function.
private function mClick(me:MouseEvent):void{
trace("me.target.x",me.target.x);
trace("me.target.y",me.target.y);
}
me is just a variable we chose to represent the event that triggered this function. Event is a class. A MouseEvent is a subclass of Event. So we are saying that me is an Event of sublcass MouseEvent and that this is the expected input for this function. If you were to try to call this function elsewhere in your code it would throw an error saying that this function expected some sort of input.
me.target is the thing that caused the event to get triggered. In this case it is the mouse, so me.target.x will be the x position of the mouse at the time that the mouse was clicked.
That is all there is to it. You have just confused yourself a little bit by trying to apply a specific solution to a different problem, namely, how to register key presses on a keyboard. They are handled slightly fundamentally differently. With a keyboard, we check listen for if the keyboard had a key pressed and then in the event handler, we determine which key was pressed. With mouse events we would have a different listener for mouse move, mouse click, left mouse click and middle mouse click. Since each of those specific events has their own listener, we don't have to evaluate which button was pressed in the handler:
public function left(e:KeyboardEvent):void
{
if (e.keycode == 65)
{
leftKey = true;
}
}
The e is the thing that caused the event. In this case, the Keyboard key. Each key has a keycode. But instead of writing a different listener for every single key on the keyboard, we can just write one listener and one function and then evaluate which key was pressed inside the function. As stated before, with the mouse, the left mouse button gets its own event listener, so no need (or ability) to check that in the event listener. There are properties like ROLL_OVER and MOUSE_UP and MOUSE_DOWN. Look at the documentation for a full list.

Problems disabling movieclip button flash/as3

I've got a screen which involves a movie-clip where the object has a outline to symbolize that it can be clicked. Upon clicking the object, I'm requesting it to do numerous functions, disable itself and then go to another frame which removes the outline symbolizing it cannot be clicked anymore. But once you disable an object it goes to the original frame.
The object itself consists of these 3 frames.
Frame 1: Original State (Glow)
Frame 2: Hover over giving stats
Frame 3: No glow
To summerise i'd like to click the object and for it to go to the no glow frame and disable the movieclip.
The movieclip enabled = 1 is for when the user returns to the this frame, so the scene is aware of the button press.
Movieclip.addEventListener(MouseEvent.CLICK, Fun_Movieclip);
Movieclip.addEventListener(MouseEvent.MOUSE_OVER, Fun_MovieclipMouseOver);
Movieclip.addEventListener(MouseEvent.MOUSE_OUT, Fun_MovieclipMouseOut);
function Movieclip(event:MouseEvent):void
{
MovieclipEnabled = 1;
Movieclip.gotoAndStop(1);
Movieclip.mouseEnabled = false;
}
function Fun_MovieclipMouseOver(event:MouseEvent):void
{
Movieclip.gotoAndStop(2);
}
function Fun_MovieclipMouseOut(event:MouseEvent):void
{
Movieclip.gotoAndStop(3);
}
For some reason when ever the movieclip is disabled, it always reverts back to the glow state. Does anyone have a solution for this? Cheers
Edit: Inside the movieclip, the first frame has Stop();. Don't know if this would interfere with it.
mc.addEventListener(MouseEvent.CLICK, clickHandler);
mc.addEventListener(MouseEvent.MOUSE_OVER, mouseoverHandler);
mc.addEventListener(MouseEvent.MOUSE_OUT, mouseoutHandler);
function clickHandler(event:MouseEvent):void
{
mc.gotoAndStop(3);
mc.removeEventListener(MouseEvent.CLICK, clickHandler);
mc.removeEventListener(MouseEvent.MOUSE_OVER, mouseoverHandler);
mc.removeEventListener(MouseEvent.MOUSE_OUT, mouseoutHandler);
}
function mouseoverHandler(event:MouseEvent):void
{
mc.gotoAndStop(2);
}
function mouseoutHandler(event:MouseEvent):void
{
mc.gotoAndStop(1);
}
Not entirely sure what you meant by:
The movieclip enabled = 1 is for when the user returns to the this frame, so the scene is aware of the button press.
My suggestion for getting the scene to recognize the button click is to have the scene also listen to the mouse click handler

How to do "if Single Click" instead of "if MouseDown" in AS3?

I want to do a single click and have it not repeat the function if my mouse is still down if that makes any sense.
Currently I have it:
if (mouseDown)
{
avatar.moveABit( 0, -2);
sfxSoundChannel = moveSound.play();
}
and if I keep my Mouse Down it keeps repeating that. I want it to only work with a single click, and have to keep tapping to do it instead of leaving the mouse down.
You probably want
MouseEvent.MOUSE_CLICK
I would add an event listener on the object that is being clicked to listen for the click, and on the click run the handler function which would contain your move and soundplay code.
See this documentation.
You need MouseEvent.CLICK like so:
//Create a function (which moves avatar) to be called on mouse click
function moveAvatar(e:MouseEvent):void
{
avatar.moveABit( 0, -2);
sfxSoundChannel = moveSound.play();
}
stage.addEventListener(MouseEvent.CLICK, moveAvatar); //add mouse click event listener
EDIT: moveABit should not be using ENTER_FRAME event.
I don't know if I understood it correctly, maybe we'll need more of your code to understand what you really want.
I'm assuming that you're using some kind of loop (setInterval, Event.ENTER_FRAME) to check if the mouse button is down or not. If you are, I think you should change that to only fire inside a function like this:
function OnMouseDownHandler(event:MouseEvent):void
{
avatar.moveABit( 0, -2);
sfxSoundChannel = moveSound.play();
}
stage.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDownHandler, false, 0, true);
If you use MouseEvent.CLICK event the OnMouseDownHandler Method will be fired only when you release the mouse button, using MouseEvent.MOUSE_DOWN will behave more like a "Tap".

My mouse clicks created and triggered my eventListener at the same time

I tried to achieve the following but failed with the code below:
Click mouse once to appear the box.
Click it again to disappear the box.
What happened is that when I fire the mouse.click event (by clicking), that triggered the "stage.addEventListener(MouseEvent.CLICK, boxGone)" event listener as well. At the screen there is nothing happened because I technically addChild and removeChild the box at the same frame.
I am guessing my initial click created and triggered the event listener at the same time.Is there anyway to avoid this from happening without changing my triggering event(mouse click)? below is the code:
public function ClassConstructor(){
addEventListener(MouseEvent.CLICK, onMouseClickHandler);
}
private function onMouseClickHandler(e:MouseEvent):void{
box.x = stage.mouseX;
box.y = stage.mouseY;
box.gotoAndPlay(1);
stage.addChild(box);
stage.addEventListener(MouseEvent.CLICK, boxGone);
}
private function boxGone(e:MouseEvent):void{
stage.removeChild(box);
stage.removeEventListener(MouseEvent.CLICK, boxGone);
}
Thanks in advance,
Sunny
Modify your first listener with:
stage.addEventListener(MouseEvent.CLICK, onMouseClickHandler);
The event goes from your main class to the stage, and you add the second listener in between, so it is called just after the function's closure. Another solution, to be sure, would be to call
e.stopImmediatePropagation();
This prevents any listener to catch the same event.

Disabling button rollover for certain number of frames Flash actionscript 3.0

I'm constructing an area with selectable buttons that transition and appear every 10 frames. During these 10 frame transition periods I don't want the buttons to be selectable and if possible to disable the rollover.
I've tried creating an If statement on the addEventListener so that it only works when currentFrame is 11,21,31 etc but this didn't work. I then also tried the same principal on the function to which the Event Listener relates but still no success.
Does anyone have any ideas?
Add a listener for the ENTER_FRAME event, and put the if in the callback function.
For example
this.addEventListener (Event.ENTER_FRAME, onEnterFrame);
function onEnterFrame (evt:Event):void {
if (currentFrame == 21) {
yourButton.enabled = false;
} else {
yourButton.enabled = true;
}
}
You could do 2 things:
1:
You manually add and remove the listener.
So when you start the transition, the listener is removed,
then when the transition ends, the listener is added.
2:
You make a custom listener which checks for the state of the frame to see whether it should execute its body.
EXAMPLE:
public void listener(event:Event) {
if (event.getSource().stage.getCurrentFrame() == 10) {//This is an example, I don't know whether this specific way will work.
//Run your code here
}
}