I'm making this game in flash in which I want the user to draw straight lines (to create an unclosed shape) and I want to stop drawing the lines by double clicking.
My drawing board is a movie clip (not the stage).
I've put the double click event listener on the board and also added the doubleClickEnabled = true to the board.
However, no matter what I do, the board won't recognise my double click.
The click event gets triggered when there is some clickable entity at the event location. In other words, by for example, "double clicking" on a "transparent" region in your "drawing board", the associated event handler will not be called.
As a solution to the issue, however, you may utilize the stage object, since it occupies the entire display area; thus receives the mouse events anyways. The idea is to let the stage's event handler to inform the drawing-board's counterpart about the event occurrence:
board.doubleClickEnabled = true;
board.addEventListener(MouseEvent.DOUBLE_CLICK, onBoardDBLClick);
stage.doubleClickEnabled = true;
stage.addEventListener(MouseEvent.DOUBLE_CLICK, onStageDBLClick);
function onStageDBLClick(e:MouseEvent):void {
trace("STAGE double clicked.");
// if the location is inside the "board", then inform the "board" about the event!
if (board.getBounds(stage).contains(e.stageX, e.stageY)) {
onBoardDBLClick(e);
}
}
function onBoardDBLClick(e:MouseEvent):void {
trace("The Double-click logic of the board.");
e.stopPropagation();
}
Related
I have created a business tool using html canvas.
It contains numerous elements that can be dragged and dropped. I have coded this functionality myself basically saying (pseudocode):
if(mouseIsDown && mouseInBoundsOfIcon){
icon.grabbed = true;
}
if(icon.grabbed){
icon.x = mouseX;
icon.y = mouseY;
}
Now I would like some of these icons to implement an onClick event as well, making them both clickable and 'drag & droppable'.
The problem is the mousedown event gets fired as soon as I click down on a mouse button (obviously). I'm thinking I could use a short timer, when mousedown fires and mouseInBoundsOfIcon==true, I can start it, when it hits 0.5 seconds for example icon.grabbed = true, else if the button is released it counts as a click?
I'm not sure how to go about this. Any suggestions?
There are at least 2 common ways of differentiating between clicks and drag-starts.
Both these methods involve taking a measurement during mousedown and comparing it to another measurement taken in either mouseup or mousemove.
Measure the distance the mouse moves. For example, if it moves more than 5 pixels before mouseup it's a drag.
Measure the time between mousedown and mouseup. For example, if mouseup occurs within 200ms of mousedown, then it's a click.
Helpful Hint: Let mousedown default to drag-start rather than click. Start dragging on mousedown. If you later determine the user intended a click then put the icon back at its starting position so they don't have slightly nudged icons when intending clicks.
I'm currently programing a little flash game and I've encountered some kind of a problem:
I have a sprite, let's call it gameBoard, which contains a background image and a lot of other small sprites. My problem is when gameboard put a click listener on itself, if I happened to click on one of the numerous sprites contained in the gameboard, the localX and localY are the one of the small sprite.
So, my question is:
How can I get the coordinate of my click relative to the event listener?
Pretty sure this is what you're asking.
Trigger event from child to parent in AS3
This is a fairly common question - you can use the event.currentTarget
property instead of event.target to reference the object to which you
added the event listener.
To trigger the mouse event for the gameboard only:
[gameboard_instance_name].mouseChildren = false;
//[gameboard_instance_name].addEventListener(...);
So somewhere you've attached your click handler:
gameboard.addEventListener( MouseEvent.CLICK, clickHandler );
Then in your handler you can do the following:
function clickHandler( event:MouseEvent ):void
{
// First way use stage point and convert to gameboard
var stagePoint:Point = new Point( event.stageX, event.stageY );
var gameboardPoint:Point = gameboard.globalToLocal( stagePoint );
// Second way, use the mouse position on the gameboard
// making sure that you only use this handler with the above listener
event.currentTarget.mouseX;
event.currentTarget.mouseY;
}
I have a DisplayObject docked at the top of my interface that displays debug information (frames per second, etc.) and is translucent with an alpha of 60%.
I would like to interact with items under this surface, such that when the mouse rolls over it, it dims to 10% alpha, and mouse events pass through it to the underlying objects.
Normally, I have this debug info panel's mouseEnabled and mouseChildren properties set to false, so objects under it receive mouse events.
The problem is that in order to hide it when the mouse rolls over it, it needs to have mouseEnabled set to true. However, if mouseEnabled is true, the mouse events are not picked up by objects underneath it.
As far as I know, I can't selectively enable mouseEvents, so it's either going to receive them all or none of them. That means that I'd have to handle and forward ALL events, if I took that approach.
I really wish the mouseEnabled property had a "peek" mode or something, so that it could receive the events if it is on top, but also allow them to pass through to objects underneath.
If a DisplayObject has mouseEnabled=true it means that its events will be sent to its container not to whateve is underneath the object. So this solution will not work. The best solution would be to reroute events from it manually using getObjectsUnderPoint as described here.
I've been using this approach for years in multi-touch apps. With multiple touch points I don't see any processor overhead. And you got only one cursor.
I feel your pain. Unfortunately, I don't know of a way to enable/disable specific mouse events. You could get creative with the solution though. For instance, maybe try adding a MOUSE_MOVE listener to your stage and track the coordinates of the mouse. Then, if the stageX,stageY of the mouse is in the area of your panel, set the visibility. You might also be able to use getObjectsUnderPoint() to determine which objects are under the mouse. But, my guess is that it would get a little intense on the processor to run that on each frame iteration.
I believe you are looking for mouseEnabled = false
But another last ditch attempt you can do is on mouse over move it to the other side of the screen.
One approach you can take, although not ideal, is to add an enter frame listener and check the mouse position every frame. something along the lines of:
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
private function onEnterFrame(e:Event):void {
if(mouseX > width || mouseY > height){
//hide stats
}
}
I'm assuming you have this display hierarchy:
Debug Window
Debug Control 1
Debug Control 2
...
Overlay
Why not make the overlay a mask on DebugWindow and have your mouseEvents attached to DebugWindow itself? See this page for some inspiration: http://blog.shaperstudio.com/2010/11/as3-inverse-mask/
I had this same problem.. i made function to check is mouse over certain object:
public function isMouseOverObject(mPos: Point, pObject:DisplayObject, pContainer:DisplayObjectContainer) {
var under_objects:Array = pContainer.getObjectsUnderPoint(mPos);
var is_under:Boolean = false;
for (var i:int = 0; i < under_objects.length; i++) {
if (under_objects[i] == pObject) {
is_under = true;
break;
}
}
return is_under;
}
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;
}
Is there something like the java 'glasspane' in as3?
The glass pane is useful when you want to be able to catch events or paint over an area that already contains one or more components. For example, you can deactivate mouse events for a multi-component region by having the glass pane intercept the events. Or you can display an image over multiple components using the glass pane. http://java.sun.com/docs/books/tutorial/uiswing/components/rootpane.html
Why do this? While some animations are underway in flash, I want to prevent any mouseevents from firing. I could remove all listeners systematically, then re-add them after the animation, but if there is something like a glasspane, it might be an easier way to achieve the same effect.
My current thinking is to:
add a sprite to the stage
stretch to width and height of the stage,
give the sprite the highest z-order,
grab all events on this sprite, and stop their propagation?
if you set
enabled=false;
mouseChildren=false;
on to the top most DisplayObject it should disable all mouse events for your app. I've used it and it works a treat.
For a more specific approach, e.g. only block clicks but let mouse down etc. through I use this approach. It uses a 'clickBlocker' stage event handler during capture phase, stopping propagation to any other object.
public function blockClicks():void{
if(!stage) return;
stage.addEventListener(MouseEvent.CLICK, clickBlocker, true); //useCapture!
}
private function clickBlocker(event:MouseEvent):void{
trace("Me (the stage) gets the "+event.type+" first, and I block it #"+event.stageX+"/"+event.stageY);
event.stopImmediatePropagation();
}