how to capture mouseclick in actionscript 3.0 - actionscript-3

How do I capture the position of a mouseclick from the user in my Flash window using Actionscript 3.0?

Ron DeVera is close, but I wouldn't use an inline function, and the object passed to the function is not Event, but MouseEvent.
stage.addEventListener(MouseEvent.CLICK, _onStageMouseDown);
function _onStageMouseDown(e:MouseEvent):void
{
trace(e);
}
//traces
//[MouseEvent type="click" bubbles=true cancelable=false eventPhase=2 localX=96 localY=96 stageX=96 stageY=96 relatedObject=null ctrlKey=false altKey=false shiftKey=false buttonDown=false delta=0]
All of the properties in the output above are available through the object that gets passed to the Event Listener Method, _onStageMouseDown(e:MouseEvent); Hence the following
function _onStageMouseDown(e:MouseEvent):void
{
trace(e.localX);
trace(e.stageX);
//Note that the above two traces are identical as we are listening to the stage for our MouseEvent.
}

They explained it well, but here's the full code to illustrate it a little more for you:
addEventListener(MouseEvent.CLICK, clickHandler);
function clickHandler(event: MouseEvent) : void
{
// these are the x and y relative to the object
var localMouseX: Number = event.localX;
var localMouseY: Number = event.localY;
// these are the x and y relative to the whole stage
var stageMouseX: Number = event.stageX;
var stageMouseY: Number = event.stageY;
}

Location defined by what context? The whole page? One or more specific clickable controls?

You may query any DisplayObject's mouseX and mouseY whenever you like.

Related

addEventListener of random MovieClips

I'm making a game in AS3.
I've got in my code :
public var _classes:Array = new Array(poubelle1, poubelle2, poubelle3);
public var _movieClips:Array = new Array();
public function apparitionDechet(event : TimerEvent):void{
_movieClips.push(new _classes[Math.floor(Math.random() * _classes.length)]());
stageRef.addChild(_movieClips[_movieClips.length-1]);
I'm trying to put an addEventListener on the MovieClips.
The player should be able to click on a MovieClip when it's appearing or he can wait. Few will appears, and he can click on them at any moments.
Each clicks will make the MoviClip disapear..
So I've put :
_movieClips[1].addEventListener(MouseEvent.CLICK, removePoubelle, false, 0, true);
}
public function removePoubelle(e:MouseEvent):void{
if(e.target=="_movieClips[0]"){
trace("ok1");
}
if(e.target=="_movieClips[1]"){
trace("ok2");
}
if(e.target=="_movieClips[2]"){
trace("ok3");
}
but it's not that...
Do you know how I can do that ?
It's my first time that I'm using the randomly apparition of MovieClips...
Thank you very much,
EDIT
So I've followed your tips and did this :
public function apparitionDechet(event : TimerEvent):void{
var mc:DisplayObject = new _classes[Math.floor(Math.random() * _classes.length)]();
_movieClips.push(mc);
stageRef.addChild(mc);
mc.addEventListener(MouseEvent.CLICK, removePoubelle, false, 0, true);
}
public function removePoubelle(e:MouseEvent):void{
var mc:DisplayObject = e.target;
var i:int=_movieClips.indexOf(mc);
if (i>=0){
_movieClips.splice(i,1);
mc.parent.removeChild(mc);
}
}
But I've got the error 1118 Implicit coercion of a value with static type Object to a possibly unrelated type flash.display:DisplayObject
EDIT 2
Quick question though, is it possible to do :
if(stageRef.contains(poubelle1)) {
trace("poubelle1détécté");
}
if(stageRef.contains(poubelle2)) {
trace("poubelle2 détécté");
}
?
movieClips poubelle1 and poubelle 2 are defined like this
public var _classes:Array = new Array(poubelle1, poubelle2, poubelle3);
public var _movieClips:Array = new Array();
it doesn't seem to work if I do that.(error 1027 Contrainte implicite d'une valeur du type Class vers un type sans rapport flash.display:DisplayObject) Any idea why ?
Do you want me to create a new post ?
Thank you
If you are to remove the movieclip that was clicked, you already have it as the event's target. So you get its parent and call removeChild(). Don't forget to remove the event listener off the target.
public function removePoubelle(e:MouseEvent):void {
var mc:DisplayObject = e.target as DisplayObject;
if (!mc) return; // typecast failed
mc.parent.removeChild(mc);
// mc.removeEventListener(MouseEvent.CLICK, removePoubelle, false, 0, true);
// the line above might not be needed as the listener weakly references the mc
}
And you put the listener as soon as you create your new movie clip.
public function apparitionDechet(event : TimerEvent):void {
var mc:DisplayObject = new _classes[Math.floor(Math.random() * _classes.length)]();
_movieClips.push(mc);
stageRef.addChild(mc);
mc.addEventListener(MouseEvent.CLICK, removePoubelle, false, 0, true);
}
See, how you can avoid referencing the newly created movie clip without ugly _movieClips[_movieClips.length-1] construction? You just make a local variable which is then instantiated for your random MC out of _classes, and you then use the variable to do everything else that's needed at the time of creation.
But, this is still not enough - your "poubelle" is still inside your _movieClips array, so it'll grow. You need to clean up the array too. So, add this code to removePoubelle:
var i:int=_movieClips.indexOf(mc);
if (i>=0) _movieClips.splice(i,1);
This gets the position of the clicked movie clip inside your array, and if it's a valid one (zero or more) the array is told to remove that element.
You shouldn't be using just _movieClips[1]. That refers specifically to the SECOND object in your _movieClips Array.
You should add your eventListener as soon as the MovieClip is added to the _movieClips Array. You can add it to the most recently '.push'ed MovieClip, like this:
_movieClips[_movieClips.length-1].addEventListener(MouseEvent.CLICK, removePoubelle);
Do that on the next line after the line where MovieClip is pushed into the _movieClips Array.
Your event handler (the removePoubelle function) will be passed a MouseEvent and you can refer to the .target of this event to isolate WHICH MovieClip has been clicked:
private function removePoubelle(e:MouseEvent):void {
var mcToRemove:DisplayObject = e.target;
removeChild(mcToRemove); // note there is no need to refer to .parent as the MovieClip was added in this Class
// more code to come - see below
}
Also note: Because each MovieClip has an eventListener added WHEN IT IS CREATED, e.target will ALWAYS refer to whichever MovieClip was clicked.
The only other thing you may want to implement is removing the MovieClip from the _movieClips Array. This can be done in the removePoubelle function too:
var removalIndex:int = _movieClips.indexOf(MovieClip(e.target)); // here I am 'casting' the e.target to the type MovieClip. That basically just means I'm changing it's type from DisplayObject to MovieClip (which is a subclass of DisplayObject)
if (removalIndex>-1) {
_movieClips.splice(removalIndex, 1); // this line removes one item at the index returned from the _movieClips.indexOf... line above.
}
Let me know if any of this doesn't make sense.
}

referencing objects in different functions as3

I have an object in my mouse event functions that I want to reference in my time function.
Example, I basically created tiles and have mouse events:
var cell:MovieClip = new Tile();
cell.gotoAndStop(floor1[i][u]);
cell.x = ((u-i)*tileh)+365;
cell.y = ((u+i)*tileh/2)+70;
addChild(cell);
cell.addEventListener(MouseEvent.ROLL_OVER, mouseover);
cell.addEventListener(MouseEvent.ROLL_OUT, mouseout);
cell.addEventListener(MouseEvent.CLICK, mouseclick);
enemyMoveTimer.addEventListener(TimerEvent.TIMER, timerListener);
In the mouse events, I have something called event.currentTarget. Since I have tiles lined up with each other, I wanted to differentiate each individual tile. Thus creating that event.currentTarget. I wanted to use this in my time event, but it isn't recognizing event.currentTarget as an object, rather it's own timer. Is there any way to have the time function recognize the event.currentTarget from the mouse events?
Event.currentTarget is the last object to dispatch that specific event (and Event.target is the original object to dispatch the event). It can be absolutely anything that extends EventDispatcher.
The only way to do what you want is like this:
var currentTile:Tile;
cell.addEventListener(MouseEvent.ROLL_OVER, mouseEventsHandler);
cell.addEventListener(MouseEvent.ROLL_OUT, mouseEventsHandler);
cell.addEventListener(MouseEvent.CLICK, mouseEventsHandler);
enemyMoveTimer.addEventListener(TimerEvent.TIMER, timerListener);
function mouseEventsHandler( e:MouseEvent ):void {
this.currentTile = e.currentTarget as Tile;
}
function timeListener( e:TimerEvent ):void {
this.currentTile.blah.blah();
}
Basically you save the tile that most recently was interacted with into currentTile and then that is what you access in your timeListener.
You should really look through the LiveDocs to get a basic understanding of how events work and possibly look into how scope works as well.
Some explanation:
Your Event-Listener receives an Event-Object. Always. What kind of Event-Object it is depends on the Event. In your MouseListener you receive a MouseEvent, in you TimerListener a TimerEvent and so on.
EVERY Event-Object has two specific attributes.
event.currentTarget
is the Object, which binds the event listener (in your case "cell")
event.target
is the object, which "caused" the Event. If e.g. in you "cell"-MovieClip is another MovieClip called "nucleus" and you click on the the it, event.currentTarget would be "cell", but even.target would be "nucleus".
Since the event-object is a passed as a function parameter, it is destroyed, once the function is finished. If you wand to use parts of it in another function, you need to do it like this
var myCell:MovieClip;
function mouseClick(event:MouseEvent):void{
myCell = event.currentTarget as MovieClip;
}
function timeListener(event:TimerEvent):void{
if(myCell){
///what ever you want to do with it
myCell = null;
}
}
I hope I explained it clearly.
Here's one way you could do this :
enemyMoveTimer.addEventListener(TimerEvent.TIMER, timerListener(cell));
enemyMoveTimer.start();
public function timerListener(cell:MovieClip):Function
{
var doStuffToCell:Function = new Function(e:TimerEvent)
{
trace (cell.x + " : " + cell.y);
// do whatever you want with cell
}
return doStuffToCell;
}
I should note that I don't think it's a good idea to call your handler timerListener, as it's a handler.
Listeners do just that, they listen for an event. A handler, handles an event. The second parameter in the addEventListener method specifies a function to handle the event. Naming your handler timerListener is not a good idea in my opinion, as it's really not that.

Need to move this Object in one direction

I am trying to move this seatBelt object just on the horizontal plane. I have posted what I did so far. it's not really working out because it seems like once I press the button the seat belt is only able to move towards the right side and MOUSE_UP doesn't work. can somebody guide me on how to go about doing this?
seatBelt.addEventListener (MouseEvent.MOUSE_DOWN, prsing);
seatBelt.addEventListener (MouseEvent.MOUSE_UP, lfting);
seatBelt.addEventListener (MouseEvent.MOUSE_MOVE, mving);
function prsing (e:MouseEvent){
posX= seatBelt.x ;
posY = seatBelt.y ;
mouseclick = 1;
}
function mving (e:MouseEvent) {
if (mouseclick == 1) {
seatBelt.x = mouseX ;
}
}
function lfting (e:MouseEvent){
seatBelt.x = posX;
seatBelt.y = posY;
mouseclick =0;
}
So your intended functionality is to be able to drag the seatBelt along the x-axis and on release for it to go back to its original position?
You need to change the MOUSE_UP and MOUSE_MOVE to listen to the stage rather than the seatBelt. This is because it is possible for you to release the button when it is no longer over the seatBelt and so the function never gets called. The stage however will receive the event.
stage.addEventListener(MouseEvent.MOUSE_UP, lifting);
stage.addEventListener(MouseEvent.MOUSE_MOVE, moving);
I am not sure where you are declaring the mouseX variable but if you are after dragging functionality alter the listener to:
function moving (e:MouseEvent) {
if (mouseclick == 1) {
seatBelt.x = e.stageX;
}
}
What you have mostly looks okay code-wise, except what I think is happening is that you are "mousing up" on the stage/somewhere off the seatBelt object. I'm guessing this as to make the object move you have it reacting to mouse moving...to which I am guessing you are moving the mouse all over the stage and off the seatbelt object at which point you are then releasing the mouse.
To check if this is the case, try releasing the mouse over your seatBelt object to see if your MOUSE_UP event does get triggered.
I'm guessing the behaviour you want is that you want to have the object stop moving at any point regardless of where the mouse is released. To do this, try adding the MOUSE_UP event listener to the stage:
this.stage.addEventListener (MouseEvent.MOUSE_UP, lfting);
Though, since you may not always want this listener to be active, perhaps only add it when the mouse is pressed down over the object by adding and removing the listener only as needed.
I've edited your code a bit to show what I mean and taken out the "mouseclick" boolean as it wouldn't really be needed to keep track of the mouse down/up event anymore:
seatBelt.addEventListener(MouseEvent.MOUSE_DOWN, prsing);
function prsing(e:MouseEvent){
posX= seatBelt.x ;
posY = seatBelt.y ;
this.stage.addEventListener(MouseEvent.MOUSE_MOVE, mving);
this.stage.addEventListener(MouseEvent.MOUSE_UP, lfting);
}
function mving(e:MouseEvent) {
seatBelt.x = mouseX;
}
function lfting(e:MouseEvent){
seatBelt.x = posX;
seatBelt.y = posY;
this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mving);
this.stage.removeEventListener(MouseEvent.MOUSE_UP, lfting);
}
You can use the Sprite.startDrag method to do what you need. No MOUSE_MOVE listener is needed. Lookup the params if you need to: Sprite. I like to only have only one of the MOUSE_DOWN or MOUSE_UP listeners active at a time.
seatBelt.addEventListener (MouseEvent.MOUSE_DOWN, prsing);
function prsing (e:MouseEvent){
seatBelt.startDrag(false, new Rectangle(0,seatBelt.y,stage.width,seatBelt.y));
seatBelt.removeEventListener (MouseEvent.MOUSE_DOWN, prsing);
seatBelt.addEventListener (MouseEvent.MOUSE_UP, lfting);
}
function lfting (e:MouseEvent){
seatBelt.stopDrag();
seatBelt.addEventListener (MouseEvent.MOUSE_DOWN, prsing);
seatBelt.removeEventListener (MouseEvent.MOUSE_UP, lfting);
}

HTML5 + JavaScript - Mouse Positioning

I'm fairly new to HTML5, but I'm learning, and for now - I'm working on a really simple game.
What I'm trying to do is get the mouse X and Y position related to the canvas, and have an image to follow the mouse (like a crosshair, to aim).
But for now, I just want to pull the mouse values.
So, I have a function called init, which initialises everything. It's called when an image sprite is loaded:
function init(){
drawBg();
startDrawing();
document.addEventListener('keydown', checkKeyDown, false);
document.addEventListener('keyup', checkKeyUp, false);
document.addEventListener('ommousemove', mouseTarget, false);
}
I'm not 100% if the 'ommousemove' is correct, not sure what I'm suppose to put their. I then have the mouseTarget function:
function mouseTarget(e){
var mouseX;
var mouseY;
if(e.offsetX){
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if(e.layerX){
mouseX = e.layerX;
mouseY = e.layerY;
}
console.debug("Mouse X: " + mouseX + " Mouse Y: " + mouseY);
}
I also have a function called 'draw', which is called every 5 frames (every update), so I'm assuming I need to check the mouse position within that?
function draw(){
mouseTarget();
}
But then I get an error: Uncaught: TypeError: Cannot read property 'offsetX' of undefined.
What am I doing wrong here?
Thanks
The problem (as you suspected) is with this line
document.addEventListener('ommousemove', mouseTarget, false);
It should be
document.addEventListener('mousemove', mouseTarget, false);
The e parameter in the mouseTarget function will only contain the event information when called via an event. In your case it is never being called via an event, but only via the draw function.
That is why you are getting the Cannot read property 'offsetX' of undefined. error, as in reality you are trying to access undefined.offsetX
What you should do is keep a the mouse position in separate variables and then just reference them in the 'draw' function.

Make an object snap to another ojbect, then follow its path with pure ActionScript?

I am still trying to come to grips with how make an object snap to another ojbect, then follow its path with pure ActionScript (snap an arrow oject to a circle, then the circle follows the direct of the arrow when play button in hit).
Can somebody please help me with an small example so I can get my head round it, any help will be much appreciated. I am trying to create an application aimed towards something like this
http://itunes.apple.com/us/app/basketball-coachs-clipboard/id317785081?mt=8
I have got my drawing line working but do now know how to make the object follow the line, here is how I have drawn my line on the stage. Please could you give me a clue of how to do this.
function startPencilTool(e:MouseEvent):void
{
pencilDraw = new Shape();
board.addChild(pencilDraw);
pencilDraw.graphics.moveTo(mouseX, mouseY);
pencilDraw.graphics.lineStyle(shapeSize.width);
board.addEventListener(MouseEvent.MOUSE_MOVE, drawPencilTool);
}
function drawPencilTool(e:MouseEvent):void
{
pencilDraw.graphics.lineTo(mouseX, mouseY); /
}
function stopPencilTool(e:MouseEvent):void
{
board.removeEventListener(MouseEvent.MOUSE_MOVE, drawPencilTool);
}
1st
If you mean by "following its path", that the object follows another object, then simply do
obj2.x = obj1.x;
obj2.y = obj1.y;
to follow the exact coordinates. If you want to make some distance between them, then
obj2.x = obj1.x + dx;
obj2.y = obj1.y + dy;
choose dx and dy according to your wish.
2nd
If you want to make an app, where you can "draw an arrow" or "draw a path" and then an object should follow it, then you can try to store the coordinates of the mouse, while "drawing the arrow", then snap the object you want to these coordinates.
var coordinates:Array = [];
stage.addEventListener("mouseDown", md);
function md(evt:*):void
{
//empty the coordinates
coordinates = [];
//add listener when mouse is released
stage.addEventListener("mouseUp", mu);
//add a listener for enterframe to record the mouse's motion
addEventListener("enterFrame", recordMouse);
}
function mu(evt:*):void
{
stage.removeEventListener("mouseUp", mu);
removeEventListener("enterFrame", recordMouse);
//snap the object to the drawn line and play it
addEventListener("enterFrame", playRecording);
}
function recordMouse(evt:*):void
{
coordinates.push(new Point(stage.mouseX, stage.mouseY));
}
function playRecording(evt:*):void
{
//snap object to the recorded coordinates
myObject.x = coordinates[0].x;
myObject.y = coordinates[0].y;
//delete first element of array
coordinates.splice(0, 1);
//stop playing if there are no more points
if(coordinates.length == 0) removeEventListener("enterFrame", playRecording);
}
Place a movieclip on the stage and name it myObject. Then add the code and compile the swf.
Also, while "recoring" the coordinates, you can also draw some lines.
Change md function to this:
function md(evt:*):void
{
//empty the coordinates
coordinates = [];
//add listener when mouse is released
stage.addEventListener("mouseUp", mu);
//add a listener for enterframe to record the mouse's motion
addEventListener("enterFrame", recordMouse);
//clear graphics, and initialize line
with(graphics) clear(), lineStyle(1, 0xff0000), moveTo(stage.mouseX, stage.mouseY);
}
and recordmouse to this.
function recordMouse(evt:*):void
{
coordinates.push(new Point(stage.mouseX, stage.mouseY));
//draw the line
with(graphics) lineTo(stage.mouseX, stage.mouseY);
}
3rd
If you want to follow a pre-drawn line, then you have several options depending on your task. But everything depends on, how you exactly want to "snap" your object.