I have number of movieClips on stage, with each having it's own Event Listener. Once Click/Touch the event is called each movie clip does something. For example one movieClip makes about 6 other movie clips visible.
What I want to do is, when the user Touch/Click somewhere else on stage, where there is no movieClip I want to know, so I can perform some actions such as make some movieClips invisible.
P.S the reason why I say Touch/Click is I'm developing this app for Android, however to make testing easier I'm currently testing everything in PC with MouseEvent, rather than TouchEvent. Once I get all the features working, I will switch over to TouchEvent and test it in mobile.
Many Thanks,
Mike
Add event listener to the stage. And in the event handlers of your inner movieclips use event.stopPropagation function to prevent bubble event to the container.
I would just do a check, it's simple and quick and doesn't require adding code to alter propagation.
import flash.events.MouseEvent;
stage.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
function onClick(e:MouseEvent):void
{
if(e.target == stage)
{
trace("click click");
}
}
Related
In my Starling game, the player sprite is controlled by clicking the screen where you want to go. Since (AFAIK) you can't have touch events that happen outside a sprite activate handlers in the sprite, I put the handlers in the game object. Here's a basic idea of how it goes:
To create my listener, I do this within my game object:
this.addEventListener(TouchEvent.TOUCH, onTouch);
But onTouch is never called (I even tried putting a trace() in there).
Am I missing something here?
Well, you can make events that happen outside of a sprite to trigger the sprite's handlers, for this, you attach listeners not to the sprite, but to some other object, usually stage. Check if the stage is available, though. The best way to handle stage present is a listener to ADDED_TO_STAGE event. You put that into your handler object's constructor, and put all stage-aware code into that listener.
public function Handler() {
if (stage) init(null);
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point. This is where should stage-aware code start
stage.addEventListener(TouchEvent.TOUCH, onTouch);
// at this point stage is populated and valid, thus we can use stage reference
// without fear of null pointer.
}
im working on a fps game. The game contains multiple enemy. But im calling the same movieclip as enemy. That movieclip dispatches fire event and reduce player life. But i need to know which movieclip is dispatching event. I've added enemy randomly, i need to know the enemy location of the enemy who just have fired. Heres some code which may help...
dispatchEvent(new Event('Enemy_Fired')); // this event is dispatching from enemy movieclip
this.addEventListener('Enemy_Fired',ReduceLife);
public function ReduceLife(e:Event){
life--;
var currentLife:int = life * lifeRatio;
if(life<1){
Game_Over();
//game_completed();
} else {
sview.playerhit.gotoAndPlay(2);
sview.lifebar.gotoAndStop(100 - currentLife);
sview.health.text = String(currentLife);
}
//Here i need to know this event dispatched from which enemy
}
Thanks in advance
You can get a reference to the object that dispatched the event by using:
e.target
It seems like the parent is dispatching the Event though as seen in this line of code.
dispatchEvent(new Event('Enemy_Fired')); // this event is dispatching from enemy movieclip
because dispatchEvent is the same as this.dispatchEvent, which means your root class is dispatching the event.
You need to change it to this
yourEnemyMovieClip.dispatchEvent(new Event('ENEMY_FIRED',true,false);
Note that i am putting the bubbles property of your Event on true and cancelable on false. Bubbles means that your event will bubble up on the display chain. That is important , because you are listening for the event in your root class, which is one level higher than the movieclip that dispatched the event.
See the constructor of the Event class here:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/Event.html
in your eventlistener add the following
e.stopImmediatePropagation();
this will stop the event from bubbling any higher up on the displaychain, saving performance in your application.
I have a Player movieclip object being placed on frames, where an example player is, then making the example player invisible. But when it runs the player is placed where the example is in the first frame, instead of in each current frame.
parent class:
playerStartX = exPlayer.x;
playerStartY = exPlayer.y;
Is there a way to either look only at the example in the current frame or else to remove only the example in the current frame after it has already been "copied"?
Not sure, if I understood your question completely, but maybe you should use an event handler for the Event.ENTER_FRAME event. This event is dispatched in sync with the frame rate of your SWF. Your handler could look like this:
function enterFrameHandler(event:Event):void
{
playerStartX = exPlayer.x;
playerStartY = exPlayer.y;
}
Because I don't no enough about how you structured/organized your MovieClips on the stage, I cannot say where to add the handler. But somewhere you have to do:
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
I currently have a difficulty removing specific sounds from playing when I advance through the timeline on a particular project.
The user chooses a particular item on the timeline which will display a specific movieclip and will then play a specific sound on MOUSE_DOWN.
The eventListener for MOUSE_DOWN which exists as follows:
stage.addEventListener(MouseEvent.MOUSE_DOWN, sprayWater);
stage.addEventListener(MouseEvent.MOUSE_UP, stopWater);
function sprayWater(event:MouseEvent):void
{
waterarm.gotoAndStop(2);
trace("SPRAYING WATER");
}
function stopWater(event:MouseEvent):void
{
waterarm.water.gotoAndPlay("waterE");
}
on frame 2 of 'waterarm' is a movieclip called 'water' that contains an animation of water and the following code to start the water sound:
var sfxWater:sfxwater;
var waterChannel:SoundChannel;
sfxWater = new sfxwater;
waterChannel = sfxWater.play();
on the frame "waterE" an animation of the water disappearing exists and the code sfxWater.stop();.
When the user progresses beyond this frame on the root timeline, the sound effect of water still remains on MOUSE_DOWN despite the movieclip no longer existing on the timeline at that point.
The ideal outcome will be the individual sound playing on MOUSE_DOWN and stopping on MOUSE_UP only when this movieclip is visible on the main timeline. If anybody can provide any assistance in being able to prevent the sound from playing and removing this event listener (through code on the main timeline if possible) it would be greatly appreciated.
Regards,
Darren
If stopping the sound is all that you want why not use SoundMixer.stopAll().
You can use it in the MOUSE_UP event after checking if the said movieclip's visible property.
I am coding a drag and drop application where I can grab an object and then place it over different object containers. When I am dragging the object (keeping the mouse button pressed) and I leave the stage, I can still control the object with the mouse...this is not what I want.
I would like to lose control of the object when the mouse leaves the stage.
I tried to remove the event listener for MOUSE_DOWN on a MOUSE_LEAVE event but nothing.
I also tried to dispatch a MOUSE_UP event on a MOUSE_LEAVE event but it does not work either...it works only if I manually release the mouse button.
Is there any way to override the MOUSE_DOWN event when the user moves the mouse away from the screen but he is still pressing the mouse button???
Any suggestion???
Thanks in advance
Is the stage actually listening to the MOUSE_LEAVE event? In any case , check this article, it may help:
http://www.kirupa.com/developer/flashcs3/detecting_when_mouse_leaves_movie.htm
Here's a couple tricky traps not to fall into :
One bizarre thing is that in Chrome + Firefox, the MOUSE_LEAVE event isn't dispatched for a WMODE of OPAQUE orTRANSPARENT. It just doesn't fire - mouse down or up.
With WINDOW it works fine. That one took me a long time to find out! grr... http://bugs.adobe.com/jira/browse/FP-892
Second, make sure you're using Event for the parameter type for your Event.MOUSE_LEAVE handler and not MouseEvent. If you try to handle MOUSE_LEAVE with e:MouseEvent you'll get an error that you may never see (unless you're using the debug flash player). It's a very easy mistake to make because you're probably pointing all your other handlers to the same method.
Here's what I do: (just call my main endDrag from mouseLeave(e:Event)
stage.addEventListener(MouseEvent.MOUSE_MOVE, drag);
stage.addEventListener(MouseEvent.MOUSE_UP, endDrag);
stage.addEventListener(Event.DEACTIVATE, endDrag);
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeave);
private function mouseLeave(e:Event):void
{
endDrag(new MouseEvent("MOUSE_LEAVE"));
}
public function endDrag(evt:MouseEvent):void
{
/// handle end drag
}
I believe you are talking about the user leaving the flash content altogether with mouse clicked, and when he/she returns it continues the process right?
I suggest, you track the mouse x & y coordinates. Set a condition which triggers the mouse up event handler when the x or y is equal to the stage width or height respectively.
When you drag an object outside the flash movie, the object will fire a MOUSE_OUT event. You can listen to this event, use a variable to check if the object is being dragged, and, if so, dispatch a MOUSE_UP event.
some_object.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
some_object.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
some_object.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
private function mouseOutHandler(e:MouseEvent):void
{
if (isDragging)
e.target.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP));
}
private function mouseDownHandler(e:MouseEvent):void
{
e.target.startDrag();
isDragging = true;
}
private function mouseUpHandler(e:MouseEvent):void
{
e.target.stopDrag();
isDragging = false;
}