Is it possible to destroy a dispatched event - actionscript-3

I'm making a game in AS3.
I've got a class named "UseBox" that dispatch an event.
If thisThing.buyable not event is dispatch and the child "Building" is visible whith 2 buildings visible and 2 not visible.
If thisThing.destructible then the event "upgradable" is dispatch and the child "Building" is visible whith 4 buildings visible.
The problem is that the dispatch "upgradable" is always on now.
Is it possible to destroy the event each time the child "Building" become visible ?
Thanx for your answers,
Here's my code :
UseBox
public function UseBox(stageRef:Stage, thisThing:Object){
if (thisThing.buyable){
useButton.gotoAndStop("buy");
useButton.addEventListener(MouseEvent.CLICK, buyIt, false, 0, true);
}
if (thisThing.destructible){
this.gotoAndStop("upgrade");
upgradeButton.buttonMode = true;
upgradeButton.addEventListener(MouseEvent.CLICK, upgradeIt, false, 0, true);
}
public function buyIt(e:MouseEvent):void{
boxClicked();
showBatiments();
lookButton.removeEventListener(MouseEvent.CLICK, buyIt);
}
public function upgradeIt(e:MouseEvent):void{
boxClicked();
showBatiments();
stageRef.dispatchEvent(new Event("upgradable"));
lookButton.removeEventListener(MouseEvent.CLICK, buyIt);
}
private function showBatiments():void{
Engine.batiments.visible = true;
}
Oh, and my buidling.as code :
poulaillerPlusBtn.visible = false;
poulaillerImpossible.visible = true;
poulaillerBtn.addEventListener(MouseEvent.CLICK, poulaillerConstruction, false, 0, true);
stageRef.addEventListener("upgradable", checkConstruction, false, 0, true);
private function checkConstruction(Event):void{
trace("I've heard upgradable");
poulaillerPlusBtn.visible = true;
poulaillerImpossible.visible = false;
poulaillerPlusBtn.addEventListener(MouseEvent.CLICK, poulaillerAmelioration, false, 0, true);
trace("on a vérifé, tu peux améliorer le batiment");
}
So, if the event "upgradable" is heard, the function "checkConstruction" is called, else not.
But, once the event "upgradable" has been dispatched, it seems that it stay always dispatch so the function "checkConstruction" is always called when "Building" is visible...

I'm not 100% sure this is what you're looking for, but if your only looking to handle an event once, then once you've recieved it by checkConstruction being called, you can remove it from listening for the event again:
private function checkConstruction(Event):void{
//Here, you would remove the function from listening to any more "upgradable" events being dispatched.
stageRef.removeEventListener("upgradable", checkConstruction);
trace("I've heard upgradable");
poulaillerPlusBtn.visible = true;
poulaillerImpossible.visible = false;
poulaillerPlusBtn.addEventListener(MouseEvent.CLICK, poulaillerAmelioration, false, 0, true);
trace("on a vérifé, tu peux améliorer le batiment");
}

Related

as3 How to dispatch a specific keyboard event

I was looking for this answer and had no luck. One place I looked actually had a very discouraging answer: "You cannot force mouse or keyboard events - they HAVE TO come from mouse or keyboard."
Huh?
I tried 'brute force' and came up with this solution. Maybe I'm going about it wrongly or stupidly; is there a better way?
I had a keyboard event that launched a class and wanted to put a sprite on the stage that would initiate this same action -- clicking on the sprite would launch the keyboard event (Escape key).
In the eventListener function, I traced the event e itself:
private function keys(e:KeyboardEvent):void {
trace("EscapeKey: ",e);
if (e.keyCode == 27) {
...
}
}
The output was
EscapeKey: [KeyboardEvent type="keyDown" bubbles=true cancelable=false eventPhase=2 charCode=27 keyCode=27 keyLocation=0 ctrlKey=false altKey=false shiftKey=false]
I then had the mouseClick listener create and dispatch a new keyboardEvent using the values I got from the above trace:
private function pauseClick(e:MouseEvent):void {
var a:KeyboardEvent = new KeyboardEvent("keyDown", true, false, 27, 27, 0, false, false, false);
stage.dispatchEvent(a);
}
Presto!
Hopefully, this post will come in handy to others looking for these types of mouse/keyboard event redundancies.
EDIT --- A complete class example requested in comments:
package{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
public class KeyboardMouse extends Sprite {
private var pauseInfo:PauseInfo;
private var escapeKey:EscapeKey;
public function KeyboardMouse() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keys);
escapeKey = new EscapeKey();
stage.addChild(escapeKey);
pauseInfo = new PauseInfo();
pauseInfo.x = stage.stageWidth;
pauseInfo.y = stage.stageHeight;
pauseInfo.addEventListener(MouseEvent.CLICK,pauseClick);
addChild(pauseInfo);
}
private function keys(e:KeyboardEvent):void {
trace("KeyboardEvent ",e);
if (e.keyCode == 27) { // esc key
if (stage.contains(escapeKey)){
trace("remove escape");
escapeKey.visible = false;
}
else {
trace("show escape");
escapeKey.visible = true;
}
}
}
private function pauseClick(e:MouseEvent):void {
// The trace in 'keys' gives this:
//[KeyboardEvent type="keyDown" bubbles=true cancelable=false eventPhase=2 charCode=27 keyCode=27 keyLocation=0 ctrlKey=false altKey=false shiftKey=false]
var a:KeyboardEvent = new KeyboardEvent("keyDown", true, false, 27, 27, 0, false, false, false);
stage.dispatchEvent(a);
}
}
}
Alright, now I get this. I just don’t get it’s purpose. Also there is, I think, an annoying error in the code.
First: you’ve shown that you can essentially ‘cast’ one type of event (e.g. MouseEvent) as another (KeyboardEvent). But you still have a listener function registered for each Event type (which, at some point, you’ll have to remove for memory management purposes) and a newly dispatched Event, so you’re not exactly minimizing code. What, exactly, is the value of this trick? Why not just register a single listener function with multiple event types? Within that function you can discriminate between the Event types and do stuff accordingly, for instance with a line like this:
if(e.type == 'keyDown' || e.type == 'click')
Second: you say: if (stage.contains(escapeKey)) and then you try to make the ‘visible’ property of escapeKey dependent on that. But by making the escapeKey.visible = false you’re not changing the fact that the stage still contains escapeKey. So the escapeKey will never become visible again because the 'else' condition doesn't exist. I believe that you want to say “removeChild(escapeKey)” and then “addChild(escapeKey)” instead of setting “escapeKey.visible = false” and then “escapeKey.visible = true”. Then you’re little program does what I think you want it to.
+1 and big props to #Neal Davis for his comments!
As he suggests, having one listener for both events with an argument of (e:Event) is a cleaner, less convoluted way of achieving the same result:
pauseInfo.addEventListener(MouseEvent.CLICK,keys);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keys);
private function keys(e:Event):void {
trace("EscapeKey: ",e);
if (e.keyCode == 27) {
...
}
}
Both listeners must still be removed at some point, though, even though only one Listener Function is handling both, of course!

remove or destroy child completely

I've got a child named "viseur" that appears on a particular scene and replace my actual cursor.
When the event "removeViseur" is called, I would like to completely remove the child "viseur" (and I'll use my previous cursor).
I did that :
stage.addEventListener("functionCalled", removeViseur, false, 0, true);
public function removeViseur(e:Event):void{
trace("removeViseur");
viseur.visible = false;
viseur.parent.removeChild(viseur);
viseur = null;
}
The child "viseur" is no longer here, but if do Alt+tab or changing window and came back, the child "viseur" come back...
Do you know how I can destroy it completely ? (I don't need it after this function is called)
Thx,
EDIT
Here is more of my code.
public static var viseur:Viseur;
var lookCocoDessous:Boolean = thisBack == "cocotierDessous";
if (lookCocoDessous) {
viseur = new Viseur(stage);
stage.addChild(viseur);
viseur.visible = true;
stage.addEventListener("functionCalled", removeViseur, false, 0, true);
public function removeViseur(e:Event):void{
trace("removeViseur");
viseur.visible = false;
viseur.parent.removeChild(viseur);
viseur = null;
}
And "viseur" has is own class like that
viseur.as :
public class Viseur extends MovieClip
{
private var engine:Engine;
private var stageRef:Stage;
private var p:Point = new Point();
public function Viseur(stageRef:Stage)
{
Mouse.hide(); //make the mouse disappear
mouseEnabled = false; //don't let our cursor block anything
mouseChildren = false;
this.stageRef = stageRef;
x = stageRef.mouseX;
y = stageRef.mouseY;
stageRef.addEventListener(MouseEvent.MOUSE_MOVE, updateMouse, false, 0, true);
stageRef.addEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler, false, 0, true);
stageRef.addEventListener(Event.ADDED, updateStack, false, 0, true);
}
private function updateStack(e:Event) : void
{
stageRef.addChild(this);
}
private function mouseLeaveHandler(e:Event) : void
{
visible = false;
Mouse.show(); //in case of right click
stageRef.addEventListener(MouseEvent.MOUSE_MOVE, mouseReturnHandler, false, 0, true);
}
private function mouseReturnHandler(e:Event) : void
{
visible = true;
Mouse.hide(); //in case of right click
removeEventListener(MouseEvent.MOUSE_MOVE, mouseReturnHandler);
}
private function updateMouse(e:MouseEvent) : void
{
x = stageRef.mouseX;
y = stageRef.mouseY;
e.updateAfterEvent();
}
}
}
}
Viseur is adding itself to the stage whenever Event.ADDED fires. This fires whenever anything is added to the stage (not just Viseur). You've also made Viseur a static property, thus ensuring it doesn't disappear from memory.
To be succinct: add Viseur only once, and from outside of itself (thereby removing the need to pass a stage reference). Be aware that once a DisplayObject is parented, it automatically gains stage & root properties which you can reference for mouseX and mouseY.
That said, if you're trying to replace the mouse cursor, I highly recommend taking a different tact: Native cursors.
See http://inflagrantedelicto.memoryspiral.com/2012/07/as3-quickie-native-mouse-cursors/

An approach to remove a listener when it is dispatched

I find addEventListener method a bit limited. I would like to use another version of it, made by me. I would like to insert a parameter that will tell if a dispatched event can be auto removed, so it will avoid me have to write this in everywhere:
obj.addEventListener(Click, function onClick(e:Event):void {
obj.removeEventListener(Click, onClick); // <--- I want to avoid this
});
Then:
obj.addEventListener(Click, function onClick(e:Event):void {
// no need anymore.
}, true); // <--- see
What approach can I take in order to reach that?
You can always intercept your addEventListener method call using override with closures:
override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
{
var self = this;
var weakListener:Function = function(e) {
self.removeEventListener(type, weakListener);
listener(e);
}
super.addEventListener(type, weakListener, useCapture, priority, useWeakReference);
}
A quick and fairly simple solution to allow for anonymous functions is the arguments.callee property
obj.addEventListener(Event.WHATEVER, function(e:Event)
{
e.currentTarget.removeEventListener(Event.WHATEVER, arguments.callee);
//Do your stuff
}
This creates the event listener and listen function at the same time, in the remove listener, it uses arguments.callee the reference the called function, allowing it to remove itself.

Child mouseEnabled

There is a main CONTAINER which contains a lot of other movieclips, in these CHILD1 movieclips, there are a CUBE and an IMAGE movieclip too. I want to disable the mouse events for only the IMAGE movieclip, is it possible?
CONTAINER
-CHILD1
-CUBE //this has mouse events!
-IMAGE //want to disable the mouse events for this!
-CHILD2
-CUBE //this has mouse events!
-IMAGE //want to disable the mouse events for this!
-CHILD3
-CUBE //this has mouse events!
-IMAGE //want to disable the mouse events for this!
Any idea? Thanks!
CHILD's code chunk:
private function added(e:Event) {
removeEventListener(Event.ADDED_TO_STAGE, added);
addEventListener(MouseEvent.MOUSE_UP, NEXT);
}
public function NEXT(e:MouseEvent) {
//OB is the instance name of the IMAGE
if(e.target.name == "OB"){
e.stopImmediatePropagation();
return;
}
OB.gotoAndStop(Main.ID);
}
[SOLVED]
To disable a specific child's event listeneing:
private function added(e:Event) {
mouseEnabled = false; //This is the clue.
OB.mouseEnabled = false;
OB.mouseChildren = false;
removeEventListener(Event.ADDED_TO_STAGE, added);
cube.addEventListener(MouseEvent.MOUSE_UP, NEXT);
}
If your mouse listener is attached to the image, set the IMAGE's mouseEnabled & mouseChildren properties to false in the constructor (OR If using the timeline in Flash CSX) then on the IMAGE objects timeline (on the first frame) set mouseEnabled & mouseChildren to false.
HERE would be the changes to your posted code (not sure what you called your instance of CUBE):
private function added(e:Event) {
removeEventListener(Event.ADDED_TO_STAGE, added);
CUBE.addEventListener(MouseEvent.MOUSE_UP, NEXT);
OB.mouseEnabled = false;
OB.mouseChildren = false;
}
public function NEXT(e:MouseEvent) {
OB.gotoAndStop(Main.ID);
}
Give a instance name to your image(assuming it is "OB") and:
private function added(e:Event)
{
this.getChildByName("OB").mouseEnabled = false
this.getChildByName("OB").mouseChildren = false;
removeEventListener(Event.ADDED_TO_STAGE, added);
addEventListener(MouseEvent.MOUSE_UP, NEXT);
}
If this doesn't work, probably you have other issues in your code and you should explain and show your code.

how to stop triggering two event at a time in spark textarea (as3+flex4)

textChanged and valueCommit both event listener are attached with a spark textarea as follows:
addEventListener("textChanged",
function(event:Event):void {
colorize();
},false,0,true);
addEventListener("valueCommit",
function(event:Event):void {
colorize();
},false,0,true);
if I type any thing in textarea, then this colorize() function is called twice. How can I stop this one that both event should not be triggered together. Pls help
If you want to listen for typing, why do you have two listeners? If you really need two listeners, you need to queue colorize with a setTimeout instead of calling it directly:
import flash.utils.setTimeout;
private var colorizeQueued:Boolean = false;
private function queueColorize():void
{
if (colorizeQueued)
return;
colorizeQueued = true;
setTimeout(function():void
{
// Process for real and note update
colorize();
colorizeQueued = false;
}, 100);
}
addEventListener("textChanged",
function(event:Event):void {
queueColorize();
},false,0,true);
addEventListener("valueCommit",
function(event:Event):void {
queueColorize();
},false,0,true);