Is it possible to remove an eventListener temporarily (i.e. until a function has been executed) - actionscript-3

I am doing actionscript 3 at the moment and was wondering if it was possible to remove and eventListner temporarily. I know of removeEventListener, however, that removes the eventListener completely and i cannot click the button again.
If you want some more details, here the exact problem. I have function that when a button is pressed, an object appears. In the function which makes this object there is an eventListener which leads to a function which allows the user to press that object. When you press that object it disappear and the button will animate. However, since the original eventListener still exists, you can press the object while in motion and create a new object. So to the point: What i want to do is disable the eventListener while the button is moving, and reactivate it when it stops.

The best way is to simply use a flag which tells the function if the animation is complete or not. Here's an example of what I'm talking about using TweenLite as tween library:
public class CreateButton extends Sprite{
private var animating:Boolean = false;
public function CreateButton(){
this.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
}
private function onClick(event:MouseEvent):void{
if(this.animating == false){
// Trigger creation functionality
TweenLite.to(this, 0.5, {/* Parameters for the actual animation */ onComplete:animationComplete});
this.animating = true;
}
}
private function animationComplete():void{
this.animating = false;
}
}

It is best practice to remove the listener if it's functionality is to be disabled. You could however set the .mouseEnabled to false if you want to disable it's click functionality without removing the listener.

Related

Why doesn't stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown, true) work?

I want to listen to stage for keyboard event, and I want to catch an event directly when it appears (not in bubbling or target). Why can't I do this?
Actually it seems that I can't use useCapture for keyboard events at all.
I want to open my inner console window by pressing tilda button, and change focus to input field. So, I wrote something like this
public function init(stage:Stage):void
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, onStageKeyDown);
}
private function onStageKeyDown(event:KeyboardEvent):void
{
event.stopImmediatePropagation();
switch(event.keyCode)
{
case Keyboard.BACKQUOTE:
visible = !visible;
stage.focus = visible ? inputField : stage;
break;
}
}
The problem is, it writes "`" character in my input, which I don't want it to do. So, I decided to try to listen to keyboard event in capture phase to stop its propagation. But it seems that stage can't have capture phase, because there is no nodes before it. How can I handle that situation properly?
To simply answer your question, you can listen for keyboard events on the capture phase.
Most likely, the reason you can't, is because nothing has focus. If nothing has focus in your application then the stage will not get a keyboard event. By default, when a swf runs nothing has focus.
Give an item focus when your application starts (anything besides the stage itself), and the event will come.
public function init(stage:Stage):void
{
stage.focus = this; //assuming this is the document class
stage.addEventListener(KeyboardEvent.KEY_DOWN, onStageKeyDown, true);
}
Now, to follow up with what you are actually trying to accomplish (aside from your actual question) all you need to do is listen for the right event (TEXT_INPUT). Your answer is close, but it can be much simpler without the need for flags or a key down listener:
stage.focus = this; //give something focus, probably not needed if you have to click the text input in order to input text
//listen on the capture phase for text input
stage.addEventListener(TextEvent.TEXT_INPUT, onStageTextInput, true);
function onStageTextInput(event:TextEvent):void
{
switch(event.text)
{
//if the new text was a backquote or # sign, don't let the event trigger it's normal action
case "`":
case "#":
event.preventDefault(); //prevent default is needed
break;
}
}
I finally found a workaround for this problem.
First of all: handling and stopping KeyboardEvent.KEY_DOWN is NOT preventing TextField from getting input. That's sad because in this case it would be useful, but it seems there is some other reasons for not doing this.
So, what I should do is listen for TextEvent.TEXT_INPUT by inputField
inputField.addEventListener(TextEvent.TEXT_INPUT, onTextInput);
and listen to KeyboardEvent.KEY_DOWN by stage
stage.addEventListener(KeyboardEvent.KEY_DOWN, onStageKeyDown);
in case I may still want to put tilda of backquote signs in my TextField (for example by coping and pasting them) I decided to use a flag
private function onStageKeyDown(event:KeyboardEvent):void
{
switch(event.keyCode)
{
case Keyboard.BACKQUOTE:
...
inAction = true;
break;
}
}
so when TextEvent.TEXT_INPUTevent fires I can see if that was opening window action or not. And if it is, then preventDefault() behaviour, which means NOT inputting received sign in TextField
private function onTextInput(event:TextEvent):void
{
if(inAction)
{
event.preventDefault();
inAction = false;
}
}

click events don't reach root flash object

I started using as3 a while ago, and mostly used starling instead of native flash objects. Today I decided to give a try to raw flash, and created a simple button:
private var _button: SimpleButton;
public function Main()
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
_button = new SimpleButton(new BUTTON); //BUTTON is an embedded bitmap
addChild(_button);
_button.useHandCursor = true;
_button.addEventListener(MouseEvent.CLICK, OnClick);
}
private function OnClick(e:MouseEvent):void
{
trace("clicked");
}
This would definely work in starling, but I found that the click event won't dispatch to the button for some reason. Neither is hand cursor shown on mouse over. I tried mouse over, mouse up and other mouse events, but none of them work. I checked that the button is correctly added to stage. Also, when I add a mouse click event listener to the stage itself, clicks register normally. When I add a listener to Main, no events are registered again.
I'm probably misunderstanding something obvious. Maybe I need to dispatch events manually down to the children? But that would be strage, though. Or can it be a bug in FlashDevelop? Please, help.
The constructor of SimpleButton takes 4 optional parameters:
public function SimpleButton(upState:DisplayObject = null,
overState:DisplayObject = null,
downState:DisplayObject = null,
hitTestState:DisplayObject = null)`
of which you supply the first one (upState):
_button = new SimpleButton(new BUTTON); //BUTTON is an embedded bitmap
The others default to null. That includes hitTestState which is the same as property of the class hitTestState:
Specifies a display object that is used as the hit testing object for the button. [...] If you do not set the hitTestState property, the SimpleButton is inactive — it does not respond to user input events.
It also includes a solution to your problem:
For a basic button, set the hitTestState property to the same display object as the overState property.
However, if all you want is to add click functionality to that Bitmap, which it doesn't have on its own, because it's not an InteractiveObject, simply use a Sprite:
// entry point
_button = new Sprite();
_button.addChild(new BUTTON); //BUTTON is an embedded bitmap
addChild(_button);
_button.useHandCursor = true;
_button.addEventListener(MouseEvent.CLICK, OnClick);
Use SimpleButton only if you want the functionality of its 4 states.
Please be careful with the overloaded term "stage":
I checked that the button is correctly added to stage.
If you mean the "drawing area" that you can see in the Adobe Flash IDE or the main time line with "stage", then yes, you'd be correct that your button is added to that.
The stage property of DisplayObject however is something different. It's the top most element of the display list and the container that the instance of your Main class is added to, which happens at the start of the execution of your .swf in the FlashPlayer.
As your Main class adds the _button to itself by calling its ownaddChild(), the button is added to the instance of Main and not stage, which are two different objects.

Is there any way to remove and addListener based on a timer?

How would i go about disabling the controls for a character for 5 seconds after they've hit an object and then immediatly afterwards allowing the character to move freely? So far, i've been able to get the code for the hitTest done and the removing keyboard controls (the easy part) but now i'm stumped as to how i would set the keyboard controls on a timer. Any help? My code for the hitTest and removing of controls is as follows.
if (player.hitTestObject(folder))
{
trace("success!");
addChild(myInfo);
//stops player movement
stage.removeEventListener(KeyboardEvent.KEY_DOWN,kD);
}
else
{
addChild(myInfo);
removeChild(myInfo);
}
The other problems in the code are of no concern right now (such as the add/remove child in the else function.
private var m_tmr:Timer = new Timer(5000, 1);
private function someFunc():void
{
if (player.hitTestObject(folder))
{
trace("success!");
addChild(myInfo);
//stops player movement
stage.removeEventListener(KeyboardEvent.KEY_DOWN,kD);
m_tmr.addEventListener(TimerEvent.TIMER, onTimer);
m_tmr.start();
}
else
{
addChild(myInfo);
removeChild(myInfo);
}
}
private function onTimer(pEvent:TimerEvent):void
{
m_tmr.removeEventListener(TimerEvent.TIMER, onTimer);
stage.addEventListener(KeyboardEvent.KEY_DOWN, kD);
}
Adding/removing the timer's event listener each time is for purposes of efficiency; it's not critical that you keep adding/removing it like that.

Flash AS3 making it so whenever a button is clicked on screen is like pressing a specific keyboard key

Hello I am working on a game in flash, in the mobile version of this app I am trying to make it so in a mousedown event on a button it will be equal to the Left, Right keycodes etc. being active?
Is there a way in AS3 for a keyboard key to be activated by other means such as mouse clicks?
leftButton.addEventListener(MouseEvent.MOUSE_DOWN, leftKeyPress)
function leftKeyPress(e:MouseEvent){
// Left Key is pressed
Keyboard.LEFT;
trace("trace statement");
}
This code doesent seem to work
EDIT: also this is important this class and the class that uses the keyboard(The player) are in two seperate classes, so Im trying to make it so that when this is click it is recognized as a key press on a keyboard
Sorry but It is all wrong. You can't trigger keyboard events like that. That is the way of capturing events. And your function is also a MouseEvent. Should be keyboard event. I Opened Flash after one year. Anyway. AFAI understand you are trying to disable keyboard until mouse click somewhere.
leftButton.addEventListener(MouseEvent.MOUSE_DOWN, leftKeyPress);
var keyEnabled:Boolean = false;
function leftKeyPress(e:MouseEvent){
keyEnabled = true;
}
key.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
function keyPressed(e:KeyboardEvent):void{
if(keyPressed){
//do whatever here
}
}
You can manually dispatch a keyboard event; however, is not the best design pattern:
dispatchEvent(new KeyboardEvent(KeyboardEvent.KEY_DOWN,
true,
false,
Keyboard.LEFT,
Keyboard.LEFT));
It would be better to establish two handlers:
addEventListener(KeyboardEvent.KEY_DOWN, moveKeyHandler);
addEventListener(MouseEvent.CLICK, moveMouseHandler);
From each handler, call a function that abstracts movement function from the handlers:
protected function moveKeyHandler(event:KeyboardEvent):void
{
/* switch statement for key */
moveLeft();
}
protected function moveMouseHandler(event:MouseEvent):void
{
/* switch statement for button target */
moveLeft();
}
protected function moveLeft():void
{
}

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
}
}