How can i capture Keyboard and Mouse events at same time AS3 - actionscript-3

When i watch some video's about starling i saw a triggered event. That event capture both keyboard and touch events.
I wonder is there any way to capture Mouse and Keyboard Events at the same time ?
You can check this video for an example:
https://vimeo.com/109564325

In my experience, usually, it might be done with implementing some common used InputManager, which can save information about pressed keys/mouse buttons and other classes might get this information through methods, something like:
checkIfKeyPressed(keyCode:int):boolean
{
}
Also, if you need to know about only some specific keys (e.g. alt, ctrl, cmd, shift, etc.), there are some public properties in the MouseEvent objects, which can help you (e.g. altKey, ctrlKey, shiftKey, etc.). See: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/MouseEvent.html

Can't you add listeners for both keyboard and mouse events, and call a shared 'handler' from there on?
...
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(MouseEvent.CLICK, clickHandler);
private function clickHandler(e:MouseEvent):void {
inputHandler(e, 'mouse');
}
private function keyDownHandler(e:KeyboardEvent):void {
inputHandler(e, 'keyboard');
}
private function inputHandler(e:Event, type:String):void {
// Do logic here
}

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.

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

Is it possible to SIMULATE a mouse click using a mouse down and up events?

A previous question has gotten me thinking. Is it possible to simulate a MouseEvent.CLICK to get fired by just firing first a MOUSE_DOWN followed by a MOUSE_UP.
As per Adobe's doumentation.
"... For a click event to occur, it must always follow this series of events in the order of occurrence: mouseDown event, then mouseUp. The target object must be identical for both of these events; otherwise the click event does not occur. Any number of other mouse events can occur at any time between the mouseDown or mouseUp events; the click event still occurs." http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/InteractiveObject.html#event:click
From my tests it shows that the CLICK event is NOT constructed from the ActionScript 3 event queue. Or is something wrong with the code?
See:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
[SWF(backgroundColor="0xFFFFFF", frameRate="30", width="800", height="600")]
public class Test extends Sprite
{
private var spr:Sprite = new Sprite();
public function Test()
{
trace("Test()");
this.addEventListener(Event.ADDED_TO_STAGE,init);
}
public function init(e:Event):void
{
trace("init()");
spr.graphics.beginFill(0xFF0000);
spr.graphics.drawRect(0,0,200,80);
spr.graphics.endFill();
addChild(spr);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
spr.addEventListener(MouseEvent.CLICK, onClick);
}
private var tick:int = 0;
private function onEnterFrame(e:Event):void
{
if (tick == 1) spr.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_DOWN,true,false));
if (tick == 2) spr.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP,true,false));
if (tick == 3) spr.dispatchEvent(new MouseEvent(MouseEvent.CLICK,true,false));
tick++;
}
private function onClick(e:MouseEvent):void
{
trace("onClick() MouseEvent.CLICK dispatched");
}
}
}
I should get TWO 'onClick()' events instead of one.
The reason you cannot is that all three types are created by the plugin, and are not dependent upon each other.
MouseEvent.MOUSE_DOWN is fired as soon as you press on an interactive object.
MouseEvent.MOUSE_UP is fired as soon as you release the mouse, it does not depend upon the mouse click having started a MOUSE_DOWN within the same InteractiveObject.
MouseEvent.CLICK will only be fired when both events take place in the same object without the cursor leaving the object between the itnerval of mouse down and mouse up.
So you can see that there is a simple case, or two even, in which both MOUSE_DOWN and MOUSE_UP are fired, but CLICK is not called because the event is not a CLICK.
Furthermore, the ability to simply dispatch a MouseEvent.CLICK event makes it unnecesasry to create fake user interaction by firing multiple mouse events, when only one is called for. It would be awkward to have to track each object clicked in the mouse down listener, in order to check that the moue up should also trigger a click. You would also need to remove references when a ROLL_OUT event happened.
In short, the CLICK event is really a lot more than the MOUSE_DOWN and MOUSE_UP events. It is also managing that the events happened in succession and on the same display object without leaving the object. When that happens, and ONLY when that happens flash dispatches a CLICK event.
it's impossible, this code:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
/**
* ...
* #author www0z0k
*/
public class Main extends Sprite {
public function Main():void {
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(MouseEvent.CLICK, onClick);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onStageKeyDown);
}
private function onStageKeyDown(e:KeyboardEvent):void {
trace('pressed');
stage.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_DOWN));
stage.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP));
stage.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
}
private function onClick(e:MouseEvent):void{
trace('clicked');
}
}
}
outputs just:
pressed
clicked
after a key is pressed on the keyboard
not sure about this for flash. But when i was learning windows MFC and was clueless. What i did was that I sent WM_MOUSEDOWN followed by WM_MOUSEUP after a short delay. It did work and the button's visual states also changed - without any mouse click!
If I understand what you're asking then the answer is YES.
I am curious if I have over simplified the solution here especially after reading your code attempt. It is very simple to "simulate" a mouse click. The code below outputs two "I have been clicked" statements when the object is clicked and none when you mouse down then move out of the objects boundaries.
This class extended a MovieClip I created on the stage so I didn't have to code a box.
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class clickMe extends MovieClip {
public function clickMe() {
// constructor code
this.addEventListener(MouseEvent.CLICK, clicked);
this.addEventListener(MouseEvent.MOUSE_DOWN, mDown);
}
private function clicked(e:MouseEvent):void{
trace("I have been clicked");
this.removeEventListener(MouseEvent.MOUSE_UP, clicked);
}
private function mDown(e:MouseEvent):void{
this.addEventListener(MouseEvent.MOUSE_UP, clicked);
}
}
}
In your code I believe the problem is that you are trying to run event listener dispatches through an "onEnterFrame" which will only ever fire one event per frame - never two. Also after testing your code I'm not sure what your were trying to accomplish with the "tick" variable because you never reset it. So the the MOUSE_UP event fires once (when tick = 2, unless your holding the mouse down) then none of the other dispatches will ever fire again.
Not quite sure why everybody's making these complex spikes. Or maybe I'm just overseeing something.
Anyway, here's a very easy way to check it:
import flash.events.MouseEvent;
stage.addEventListener(MouseEvent.CLICK, function(){
trace( 'clicked' );
} );
stage.dispatchEvent( new MouseEvent( MouseEvent.MOUSE_DOWN ) );
stage.dispatchEvent( new MouseEvent( MouseEvent.MOUSE_UP ) );
And the answer would be, "no, it's not possible"...
...and probably should be followed by a counter-question: WHY would I want to simulate a click event using a sequence of mousedown and mouseup, when I can dispatch a click event just as well?
Am I a button, having an existential crisis?
Or is it a question out of mere curiosity? But you know what happened to the cat... Right, but maybe it's schrödinger's cat, which means that at the end of this completely irrelevant train of thought, curiosity REALLY did and did NOT kill the cat.
Except if the cat's out of a box.
Then it probably just got wasted.
See, thinking out of the box can get you killed.

Is every MOUSE_DOWN guaranteed a MOUSE_UP?

Are there any circumstances under which a Flash application could receive two MouseEvent.MOUSE_DOWN without a MouseEvent.MOUSE_UP in between?
In my ActionScript 3 application, I want to track the user dragging a sprite. My plan is to listen for a MouseEvent.MOUSE_DOWN, start an indefinitely repeating timer that records the mouse position, and stop the timer on MouseEvent.MOUSE_UP. Is that a good plan?
Click but do not release the button.
While keeping the button down move the cursor outside.
Release the button outside.
Come back inside and click again.
You will get two down event without an up event.
A better solution to drag-and-drop might be to listen MOUSE_MOVE event and in the event handler check buttonDown property. If the button is down while moving, this will be true, otherwise false.
EDIT: For stage even if you release the button outside the flash window then up event is fired. So for stage this can work, but still instead of timer using MOUSE_MOVE with buttonDown looks better to me. You can check yourself with the following code:
public class StageEventTest extends Sprite
{
public function StageEventTest()
{
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
}
private function onDown(evt:MouseEvent):void {
trace("down");
}
private function onUp(evt:MouseEvent):void {
trace("up");
}
private function onMove(evt:MouseEvent):void {
trace("move", evt.buttonDown);
}
}
it will miss the mouse up event if the mouse is outside of the stage and continue it's mouse tracking when mousing over the stage since the mouse up event was never called. this likely problem can be mitigated by using Event.MOUSE_LEAVE - forward the mouse leave event to the mouse up event handler so that if the user mouses away from the stage the mouse up event will be called.
Yes, but unless you are listening to the stage, I think you can miss the mouseup event if the mouse has gone outside the Flash movie. Nothing beats an experiment though.
Below you can find the code I always use for custom dragging. Normally, it should work fine. I listen to the MOUSE_MOVE-event for repositioning and tracking the sprite, but you can just as well use the Event.ENTER_FRAME-event or use a timer instead.
ObjectToDrag.addEventListener(MouseEvent.MOUSE_DOWN, startCustomDrag);
public function startCustomDrag(e:MouseEvent):void
{
_prevX= e.stageX;
_prevY= e.stageY;
stage.addEventListener(MouseEvent.MOUSE_MOVE, dragObject); //REPLACE BY TIMER OR Event.ENTER_FRAME
stage.addEventListener(MouseEvent.MOUSE_UP, stopCustomDrag);
}
private function dragObject(e:MouseEvent):void
{
ObjectToDrag.x += _prevX - e.stageX; //OR ANY OTHER CALCULATION
ObjectToDrag.y += _prevY - e.stageY; //OR ANY OTHER CALCULATION
_prevX= e.stageX;
_prevY= e.stageY;
}
public function stopCustomDrag(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragObject); //REPLACE BY TIMER OR Event.ENTER_FRAME
stage.removeEventListener(MouseEvent.MOUSE_UP, stopCustomDrag);
}