Navigaton menu. Pressing buttons in the AS3 application without keyboard and mouse - actionscript-3

I am writing an application for Arduino on AS3. Keyboard and mouse are not provided.
There are a lot of buttons in the application. All of them can work with a keyboard and mouse. Management is planned to be carried out by changing the number taken from the array. The application accepts data only from Arduino.
If Data[5] ==100, FocusManager moves to the next button.
If Data[5] ==600, the button on which FocusManager is installed is clicked.
package
{
import flash.events.*;
import fl.managers.*;
import flash.display.*;
dynamic public class Main extends MovieClip
{
public var fm:FocusManager;
public var myBtnFocus:InteractiveObject;
public var myBtnName:String = "";
public function Main()
{
addFrameScript(0, this.frame1);
fm = new FocusManager(this);
fm.setFocus( this ); //# manually set your button as default //# fm.setFocus( your button );
this.myBtnFocus = fm.getFocus(); //# update the reference to know currently focused
this.myBtnName = this.myBtnFocus.name; //# extract name from focused
return;
}// end function
public function Rendering() : void
{
this.Connect.Status.text = this.Data[5]; // view arduino Data[5]
if (this.Data[5] > 0)
{
if( ! Boolean(this.chkBtn))
{
if (this.Data[5] = 100)
{
//# SOLVED - FocusManager go to next button (component)
this.myBtnFocus = fm.getNextFocusManagerComponent(); //# find it as next one
fm.setFocus( this.myBtnFocus ); //# then set as current selection (focused)
this.chkBtn = true;
}
/*
if (this.Data[5] = 150) {FocusManager go to the previous button (component)}
if (this.Data[5] = 200) {move FocusManager left (Arrow left)}
if (this.Data[5] = 300) {move FocusManager righ(Arrow right)}
if (this.Data[5] = 400) {move FocusManager up(Arrow up)}
if (this.Data[5] = 500) {move FocusManager dwn(Arrow dwn)}
if (this.Data[5] = 600) {SOLVED - click on the button on which the FocusManager is installed with a mouse click }
*/
}
}
else //# if the button is pressed and Data[5]==0, deleting variables
{
if( Boolean(this.chkBtn))
{
delete this.chkBtn;
}
}
return;
}// end function
public function onMouseClick (event:MouseEvent = null) :void
{
if( event.currentTarget.name != null)
{ this.myBtnName = event.currentTarget.name; }
trace( ">> Got Click ... Button name is : " + this.myBtnName );
}
public function onFocusedBtn (event:FocusEvent) :void
{
trace (">> Got TAB ... Focus is now changed to : " + event.target.name)
}
function frame1()
{
this.Btn1.addEventListener( MouseEvent.CLICK, this.onMouseClick );
this.Btn2.addEventListener( MouseEvent.CLICK, this.onMouseClick );
this.Btn3.addEventListener( MouseEvent.CLICK, this.onMouseClick );
//# Focus listener
this.addEventListener( FocusEvent.FOCUS_IN, onFocusedBtn );
return;
}// end function
}
}
How to implement if Data[5] ==150 - FocusManager goes to the previous button? How to change the position of the FocusManager to the left, up, down, right (simulating pressing keys on the keyboard)

To test example code below..
To simulate "TAB", send from Arduino a code 100 each time to change the selected button's index.
To simulate "ENTER" or "CLICK", send from Arduino a code 600 to know which button was clicked.
For example to simulate clicking on btn2 you send Data 3 times with: 100 --> 100 --> 600
Try something like this:
//# index of the button that was selected via keypress TAB or mouse Click
public var index_OfSelected :uint = 0;
//# for handling keyboard pressing
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
//# for where/whenever you receive data from Arduino
process_Data ( this.Data ); //run function with Arduino "Data" as function input
public function process_Data ( inData :Array ) :void
{
//# we'll reference the function's input as "inData"...
if (inData[5] = 100) doKey_TAB(); //# selected target my buttons (TAB)
if (inData[5] = 200) doKey_left(); //# move target left (Arrow left)
if (inData[5] = 300) doKey_right(); //# move target right (Arrow right)
if (inData[5] = 400) doKey_up(); //# move target up (Arrow up)
if (inData[5] = 500) doKey_down(); //# move target down (Arrow down)
if (inData[5] = 600) doKey_Enter(); //# enter (mouse click)
//return; //# cannot return anything if return type is ":void"
}
function keyDownHandler(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.TAB) { doKey_TAB(); }
if (event.keyCode == Keyboard.ENTER) { doKey_Enter(); }
}
function doKey_TAB () :void
{
//# do TAB stuff/code here...
//# eg: highlight a selected button or menu option...
index_OfSelected++;
//# reset number if pressing TAB increases higher than 15 items
if( index_OfSelected > 15) { index_OfSelected = 1; }
trace(">> Pressed TAB : current button is : Btn" + String( index_OfSelected ) );
}
function doKey_Enter () :void
{
//# do Enter stuff/code here...
trace(">> Pressed ENTER or CLICK : current button is : Btn" + String( index_OfSelected ) );
}
public function onBtn1(event:MouseEvent) : void
{
index_OfSelected = 1; doKey_Enter();
}
public function onBtn2(event:MouseEvent) : void
{
index_OfSelected = 2; doKey_Enter();
}
public function onBtn15(event:MouseEvent) : void
{
index_OfSelected = 15; doKey_Enter();
}
function frame1()
{
this.Btn1.addEventListener(MouseEvent.CLICK, this.onBtn1); //# index = 1
this.Btn2.addEventListener(MouseEvent.CLICK, this.onBtn2); //# index = 2
this.Btn15.addEventListener(MouseEvent.CLICK, this.onBtn15); //# index = 15
//return; //# should Error since it does not seem to return anything...
}

According to your shown, you can try something like below to use focusManager.
Code is untested (no AS3 compiler here).
package
{
//# put imports here
import fl.managers.FocusManager;
dynamic public class Main extends MovieClip
{
//# put vars here (as public or private or static ... etc)
public var fm:FocusManager;
//# reference to the selected button object
public var myBtnComponent:InteractiveObject;
public var myBtnName :String = "";
//# /////////////////////////////////////////////////////////////
//# Main code and supporting functions...
//# /////////////////////////////////////////////////////////////
public function Main()
{
fm = new FocusManager(this);
addFrameScript(0, this.frame1);
//# use one of these to set a default (starting) selection...
fm.setFocus( btn1 ); //# try to manually set btn1 as default?
fm.defaultButton( btn1 ); //# or maybe this works better?
myBtnComponent = fm.getFocus(); //# update the reference to know currently focused
myBtnName = myBtnComponent.name; //# extract name from focused
}
public function Rendering() : void
{
//# cast numbers to String for using as text
this.Connect.Status.text = String( this.Data[5] ); // view arduino Data[5]
if (this.Data[5] > 0)
{
if( ! Boolean(this.chkBtn))
{
//# press Enter
if ( (this.Data[5] == 600) || (this.Data[5] == "600") )
{
//# set name manually because it's not an Event
//# meaning you cannot check with: event.currentTargetname
myBtnName = myBtnComponent.name; //# extract name from focused
doKey_Enter(); //# simulate ENTER press
}
//# press TAB
if ( (this.Data[5] == 100) || (this.Data[5] == "100") )
{
//# TAB = go to next button (component)
myBtnComponent = fm.getNextFocusManagerComponent(); //# find it as next one
fm.setFocus( myBtnComponent ); //# then set as current selection (focused)
}
//# this needs fixing ...
if (this.Data[5] == 200)
{
/*
var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN);
event.keyCode = keyCode.LEFT;
dispatchEvent(event);
this.chkBtn = true;
*/
//move FocusManager left (Arrow left),then the keyboard button with the left arrow should be pressed. This will be "KEY_DOWN".
//# just manually run the "onDown" keyboard function
onDown();
}
/*
if (this.Data[5] = 300) {move target righ(Arrow right)}
if (this.Data[5] = 400) {move target up(Arrow up)}
if (this.Data[5] = 500) {move target dwn(Arrow dwn)}
if (this.Data[5] = 600) {click on the button on which the FocusManager is installed with a mouse click }
*/
}
}
else
{
if( Boolean(this.chkBtn))
{
/*
var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP);
event.keyCode = which was pressed;
dispatchEvent(event);
delete this.chkBtn;
*/
}
}
}
public function onDown (e:KeyboardEvent = null) :void
{
var myKeyCode :int = -1; //# maybe create as public var (at top of code)
if( e.keyCode != null )
{ myKeyCode = e.keyCode; trace("key code is : " + myKeyCode ); }
//# key Left
if ( (this.Data[5] == 200) || (myKeyCode == 37) || (myKeyCode == "LEFT") )
{
//# do left key stuff or run some function...
}
}
public function onUp (e:KeyboardEvent = null) :void
{
if( e.keyCode != null ) { trace(e.keyCode + " UP"); }
}
public function onMouseClick (event:MouseEvent = null) :void
{
if( event.currentTarget.name != null)
{ myBtnName = event.currentTarget.name; }
trace( ">> Got Click ... Button name is : " + myBtnName );
fm.setFocus( myBtnComponent );
doKey_Enter();
}
public function onFocusedBtn (event:FocusEvent) :void
{
trace(">> Got TAB ... Focus is now changed to : " + event.target.name);
}
function doKey_Enter () :void
{
//# do Enter stuff/code here...
trace(">> Got ENTER ... current Button is : " + myBtnName );
if( myBtnName == "Btn1" ) { do_Btn1_stuff(); }
if( myBtnName == "Btn2" ) { do_Btn2_stuff(); }
}
function do_Btn1_stuff () :void
{
//# code for whatever task happens
//# whenever your button 1 is actually clicked or Enter pressed...
//# example: play some sound if app is like a virtual music instrument
trace(">> Got RUN FUNCTION ... doing Btn1 stuff here ... " );
}
function do_Btn2_stuff () :void
{
//# code for button 2 when pressed or clicked
trace(">> Got RUN FUNCTION ... doing Btn2 stuff here ... " );
}
function frame1()
{
this.addEventListener(KeyboardEvent.KEY_UP, onUp);
this.addEventListener(KeyboardEvent.KEY_DOWN, onDown);
//Btn1.name = "Btn1"; //# if needed for updating variable: myBtnName ...
Btn1.addEventListener( MouseEvent.CLICK, onMouseClick );
Btn1.addEventListener( FocusEvent.FOCUS_IN, onFocusedBtn );
Btn2.addEventListener( MouseEvent.CLICK, onMouseClick );
Btn2.addEventListener( FocusEvent.FOCUS_IN, onFocusedBtn );
Btn15.addEventListener( MouseEvent.CLICK, onMouseClick );
Btn15.addEventListener( FocusEvent.FOCUS_IN, onFocusedBtn );
}
} //end Class Main
} //end Package

Related

My Character Won't Move :( Multiple .as files AS3

I have a few .as files. They are: MainClass.as, FrontEnd.as, Levels.as, and Hero.as. My problem (as far as I know) is in my Hero.as file. Let me descibe how I have it all set up thusfar because I have been a bit concerned that there are better ways of doing things in AS3.
MainClass.as makes a variable of FrontEnd (menus, namely the main menu) and calls it up (addChild).
FrontEnd.as are my menus. buttons and whatnot...
Levels.as right now just calls up level 1 when the start new game button is pressed on the main menu. Had one hell of a time figuring out how to use functions from a different .as file. Hero.as I will add my code for. I'm posting the whole thing because I don't know where my problem is.
public class Hero extends MovieClip
{
public var roger:player = new player();
private var animationState:String = "down";
public var facing:String = "down";
private var isLeft:Boolean = false;
private var isRight:Boolean = false;
private var isUp:Boolean = false;
private var isDown:Boolean = false;
public var currentPlayer:MovieClip = roger;
public function Hero()
{
addEventListener(Event.ENTER_FRAME, loop);
addEventListener(Event.ADDED_TO_STAGE, onStage);
trace(currentPlayer);
}
public function onStage( event:Event ):void
{
removeEventListener( Event.ADDED_TO_STAGE, onStage );
}
public function addCurrentPlayer():void
{
roger.x = stage.stageWidth * .5;
roger.y = stage.stageHeight * .5;
addChild(roger);
currentPlayer = roger;
setBoundaries();
}
public function keyDownHandler(event:KeyboardEvent)
{
if (event.keyCode == 39)//right press
{
isRight = true;
}
if (event.keyCode == 37)//left pressed
{
isLeft = true;
}
if (event.keyCode == 38)//up pressed
{
isUp = true;
}
if (event.keyCode == 40)//down pressed
{
isDown = true;
}
}
public function keyUpHandler(event:KeyboardEvent)
{
if (event.keyCode == 39)//right released
{
isRight = false;
}
if (event.keyCode == 37)//left released
{
isLeft = false;
}
if (event.keyCode == 38)//up released
{
isUp = false;
}
if (event.keyCode == 40)//down released
{
isDown = false;
}
}
public function loop(Event):void
{
if (currentPlayer == null)
{
addCurrentPlayer();//make sure at least roger is on the screen
}
currentPlayer.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
currentPlayer.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
//----------------------------------0
//Animation States
//----------------------------------0
if (isDown == true)
{
currentPlayer.y += 5;
animationState = "walk_down";
facing = "down";
currentPlayer.gotoAndStop(animationState);
}
else if (isUp == true)
{
currentPlayer.y -= 5;
animationState = "walk_up";
facing = "up";
currentPlayer.gotoAndStop(animationState);
}
else if (isRight == true)
{
currentPlayer.x += 5;
animationState = "walk_right";
facing = "right";
currentPlayer.gotoAndStop(animationState);
}
else if (isLeft == true)
{
currentPlayer.x -= 5;
animationState = "walk_left";
facing = "left";
currentPlayer.gotoAndStop(animationState);
}
//----------------------------------0;
//IDLE STATES
//----------------------------------0
else if (isDown == false)
{
currentPlayer.gotoAndStop(facing);
}
else if (isUp == false)
{
currentPlayer.gotoAndStop(facing);
}
else if (isRight == false)
{
currentPlayer.gotoAndStop(facing);
}
else if (isLeft == false)
{
currentPlayer.gotoAndStop(facing);
}
}
public function setBoundaries():void
{
var halfHeight:int = currentPlayer.height * .5;
var halfWidth:int = currentPlayer.width * .5;
if(currentPlayer.y <= 1)
{
currentPlayer.y += halfHeight;
}
else if(currentPlayer.y > stage.stageHeight)
{
currentPlayer.y -= halfHeight;
}
else if(currentPlayer.x <= 1)
{
currentPlayer.x += halfWidth;
}
else if(currentPlayer.x > stage.stageWidth)
{
currentPlayer.x -= halfWidth;
}
}
}
}
trace(currentPlayer); is giving me [object player] instead of the instance name "roger". (Later on I want more playable characters.) I'm not sure if the problem is there or in my levels file, which I'll post here. (not as long as Hero.as)
public class Levels extends MovieClip
{
var currentLevel:MovieClip;
public function Levels()
{
addEventListener(Event.ADDED_TO_STAGE, onStage);
}
private function onStage(event:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, gotoLevelOne);
}
public function gotoLevelOne():void
{
var levelOne:LevelOne = new LevelOne();
var hero:Hero = new Hero();
addChild(hero);
levelOne.x = stage.stageWidth * .5;
levelOne.y = stage.stageHeight * .5;
addChild(levelOne);
currentLevel = levelOne;
hero.currentPlayer.x = 100;
hero.currentPlayer.y = 100;
addChild(hero.currentPlayer);
}
}
}
If I remove = roger; from var currentPlayer:MovieClip = roger; it gives me #1009 null object even though I told it in addCurrentPlayer() to change currentPlayer to roger. On level 1, everything shows up but I can't move my character. I know that it worked when I was working on his animations and I would call him to the main menu. Everything worked on him. What's the problem now?
Firstly, there's a lot of things wrong with your code:
In your Hero Class, the 'onStage' Event handler doesn't actually do anything other than remove the event listener that triggers it. While it's good practice to remove the event listener, there should be some other purpose to the Event handler. If there isn't you can remove it and not bother listening for the ADDED_TO_STAGE Event.
Similarly, in your Levels Class 'onStage' Event handler you attempt to remove the event, but name the wrong handler. I assume you want to remove the event handler and then run the 'gotoLevelOne' method. If so, just have the Event.ADDED_TO_STAGE listener call 'gotoLevelOne' and then remove the Event listener there:
public function Levels()
{
addEventListener(Event.ADDED_TO_STAGE, gotoLevelOne);
}
public function gotoLevelOne():void
{
removeEventListener(Event.ADDED_TO_STAGE, gotoLevelOne);
// class continues....
OK, so to your question:
You will be getting the null error because you are referring to currentPlayer from outside the Hero Class, before calling addCurrentPlayer (where it is set).
If you temporarily define currentPlayer as a private variable, the compiler should give you a line number where you first refer to currentPlayer from OUTSIDE the Hero Class (the error will be something like 'Class X is trying to access a private (or non-existent) property of Y Class').
You can then sort out WHY you are accessing currentPlayer before calling addCurrentPlayer. You may also want to think about if currentPlayer NEEDS to be public (if so, then what is 'addCurrentPlayer' for? That function effectively works as a setter for currentPlayer).
EDIT:
At the moment you are adding new KEY_DOWN and KEY_UP event listeners EVERY frame of your game loop. This is unnecessary. Add them both ONCE in the initialisation of your game (perhaps in your Hero's onStage handler), and count on them to trigger the appropriate handlers.
You will want to add the KEY_DOWN and KEY_UP listeners to 'stage', not currentPlayer, so:
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
You will need to add the listeners AFTER your Hero instance has been added to the Stage though, so it has access to 'stage'. That's why it makes sense to add the listeners in the Hero's onstage handler.

AS3 flash keyboard events spacebar issue

hi guys thank you so much for trying to help
Ok so the question is this. I am trying to move a movieclip automatically with
movieClip.x += xspeed ;
ofcourse this works but the point is i want this to be triggered with keyboard press ..problem is i couldn't a keyboard event which works as a mouse click..it works as long as space bar is pressed but if i release it ..it stops working..i want it to be like onclick it should start moving automatically.
Any ideas? thanks
hi thanks so much for your reply and sorry for the delay. Your code gave me an idea but I tried to write it without classes . It doesnt throw up any errors however it doesnt work either . I must be doing something stupid , please have a look and let me know . //rope coding
var ropey = MovieClip(this.root).boat_mc.rope_mc.fishyrope_mc.hitbox_mc.y ;
trace(ropey);
var ropemove:Boolean;
stage.addEventListener(Event.ENTER_FRAME,ropeCode);
function ropeCode(e:Event):void
{
//detect keyboard spacebar click
stage.addEventListener(KeyboardEvent.KEY_UP,onSpacebarUp);
function onSpacebarUp(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.SPACE)
{
ropemove = true;
} else if(ropey > 600 ) {
ropemove = false;
}
}
//drop rope if variable = true
function dropRope(e:Event):void
{
if(ropemove = true) {
MovieClip(this.root).boat_mc.rope_mc.y += xSpeed;
} else if (ropemove = false) {
MovieClip(this.root).boat_mc.rope_mc.y -= xSpeed;
}
}
}
MyObj extends MovieClip (or Sprite). Basically alls that's happening is you should just toggle a variable when you get the KEY_UP (not KEY_DOWN, as that will repeat if the key is held down). Then, every frame, check this variable, and if's it's good, move
Something like:
private var m_shouldMove:Boolean = false;
// constructor
public function MyObj()
{
// add our listener for when we're added to the stage as we'll be adding events on it
this.addEventListener( Event.ADDED_TO_STAGE, this._onAddedToStage );
}
private function _onAddedToStage( e:Event ):void
{
// NOTE: the keyboard listener goes onto the stage
// you'll also need to remove the events when your object is removed (e.g. REMOVED_FROM_STAGE)
this.removeEventListener( Event.ADDED_TO_STAGE, this._onAddedToStage );
this.addEventListener( Event.ENTER_FRAME, this._onEnterFrame );
this.stage.addEventListener( KeyboardEvent.KEY_UP, this._onKeyUp );
}
private function _onEnterFrame( e:Event ):void
{
// every frame, if we should move, do so
if( this.m_shouldMove )
this.x += this.speed;
}
private function _onKeyUp( e:KeyboardEvent ):void
{
if( e.keyCode == Keyboard.SPACE )
this.m_shouldMove = !this.m_shouldMove; // toggle our var
}
Update
I've reworked your code sample, so it should work now:
var rope = MovieClip(this.root).boat_mc.rope_mc.fishyrope_mc.hitbox_mc;
var ropeMove:Boolean = false;
stage.addEventListener(Event.ENTER_FRAME, ropeCode);
stage.addEventListener(KeyboardEvent.KEY_UP, onSpacebarUp);
function onSpacebarUp(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.SPACE)
ropeMove = !ropeMove; // toggles ropeMove (i.e. if it's true, sets it to false, and vice versa)
}
function ropeCode(e:Event):void
{
// move the rope
if( ropeMove )
{
rope.y += xSpeed;
// stop moving if we've gone too far
if( rope.y > 600.0 )
{
rope.y = 600.0;
ropeMove = false;
}
}
}
What I changed:
Held your rope as a variable to make it easier to access
Removed ropey as it's not needed (for your > 600.0 check, you need to recalculate it anyway
The keyboard event is now added with the enter frame event (you were adding a new keyboard event every frame
The keyboard event listener just toggles the ropeMove var (there's no point checking for > 600.0 here as it means you only check when any other key is pressed)
The enter frame event simply moves the rope y
In the enter frame event, if our y is too big, we stop moving
What the code is doing:
We set up our vars - rope and ropeMove - ropeMove is used to know if we can move the rope or not
We add our event listeners - one for the keybard event, to catch the spacebar key, and one enter frame event, so we can move our rope if necessary
In the keyboard event, if our key is the spacebar, we toggle our ropeMove variable
In the enter frame event, if ropeMove is true, we move our rope
If our rope.y is greater than 600, we clamp it to 600, and set ropeMove to false so we stop moving
Update 2
With the addition of a variable ropeDir, the rope will now continuously move up and down (assuming ropeMove is true)
var rope = MovieClip(this.root).boat_mc.rope_mc.fishyrope_mc.hitbox_mc;
var ropeMove:Boolean = false;
var ropeDir:int = 1;
stage.addEventListener(Event.ENTER_FRAME, ropeCode);
stage.addEventListener(KeyboardEvent.KEY_UP, onSpacebarUp);
function onSpacebarUp(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.SPACE)
ropeMove = !ropeMove; // toggles ropeMove (i.e. if it's true, sets it to false, and vice versa)
}
function ropeCode(e:Event):void
{
// move the rope
if( ropeMove )
{
rope.y += xSpeed * ropeDir;
// stop moving if we've gone too far
if( rope.y > 600.0 && ropeDir == 1 )
ropeDir = -1;
else if( rope.y < 0.0 && ropeDir == -1 )
ropeDir = 1;
}
}
addEventListener(KeyboardEvent.KEY_DOWN, moveStarter);
function moveStarter():void
{
addEventListener(Event.ENTER_FRAME, startMove);
}

add MouseEvent.CLICK to starling image

i have a container have many image with scroll , i add TouchEvent.TOUCH as event listener instead of MouseEvent.CLICK , because starling doesn't support MouseEvent .
the problem is when i navigate between images it will listener to TouchEvent while i don't need to this ? is there any solution instead of TouchEvenet ?
the code :
private function onComplete (event:flash.events.Event):void
{
bitmapData = Bitmap(LoaderInfo(event.target).content).bitmapData;
var newImage:Image = Image.fromBitmap(Bitmap(LoaderInfo(event.target).content));
newImage.height = 154;
newImage.width = 180;
addChild(newImage);
newImage.addEventListener(starling.events.TouchEvent.TOUCH,image_clickHandler);
}
private function image_clickHandler(event:starling.events.TouchEvent):void
{
var touch:Touch = event.getTouch(stage);
if (touch != null)
{
if (touch.phase == TouchPhase.BEGAN)
{
//some code
}
}
}
It's a good practice not to attach event listeners to every objects on scene . You should attach only one listener to stage and after that read touch event's target property.Here the example from "Inroducing Starling" book:
private function onClick(e:TouchEvent):void
{
var touches:Vector.<Touch> = e.getTouches(this);
var clicked:DisplayObject = e.currentTarget as DisplayObject;
if ( touches.length == 1 )
{
var touch:Touch = touches[0];
if ( touch.phase == TouchPhase.ENDED )
{
trace ( e.currentTarget, e.target );
}
}
}
Here , currentTarget is Stage , and target will be your image

Starling mouseover detection

I'm making a point & click game where is clickable objects. When player moves mouse over the object, there appear a tooltip beside the cursor. It works almost as intended with the code below:
private function added():void
{
removeEventListener(Event.ADDED, added);
this.addEventListener(TouchEvent.TOUCH, onTouch);
}
protected function onTouch(e:TouchEvent):void
{
var touchHover:Touch = e.getTouch(this, TouchPhase.HOVER);
if (touchHover)
{
trace("show");
//mouse is hovered over this object. Therefore call Hovertext:
if (Game.hoverText.message != name_)
Game.hoverText.message = name_
}
else
{
//mouse leaves the object
trace("hide");
Game.hoverText.hideMessage(name_);
}
}
However, it has a strange problem I don't understand. If I move mouse over object and then move it downwards still staying over the object, it triggers hiding function in every second frame or so. Same thing happens when I move cursor to the right, but not when moving it up or left.
So my question is what is wrong with my code? Is this even the best way to go to detect when mouse rolls over object and when it rolls away?
EDIT: I have been going through following iterations with each of them the same problem:
var touch:Touch = event.getTouch(this);
if (touch == null) {
// Set Object alpha to 0;
//trace("pois");
Game.hoverText.hideMessage(name_);
}
else if (touch.phase == TouchPhase.HOVER) {
// Set Object alpha to 1;
//trace("paalla");
if (Game.hoverText.message != name_)
Game.hoverText.message = name_;
}
else {
// for a phase BEGIN/MOVE/STATIONARY case
// see if the touch is over the bounds of the tile (assuming 'this' is the tile)
HELPER_POINT.x = touch.globalX;
HELPER_POINT.y = touch.globalY;
this.globalToLocal(HELPER_POINT, HELPER_POINT);
if(this.hitTest(HELPER_POINT, true) != null)
{
// Set Object alpha to 1; over tile
trace("paalla");
}
else
{
// Set Object alpha to 0; not over tile
trace("pois");
}
}
var touchHover:Touch = e.getTouch(this);
if (touchHover && touchHover.phase == TouchPhase.HOVER)
{
trace("show");
//mouse is hovered over this object. Therefore call Hovertext:
if (Game.hoverText.message != name_)
Game.hoverText.message = name_
}
if (touchHover == null)
{
//mouse leaves the object
trace("hide");
Game.hoverText.hideMessage(name_);
}
Also here is swf for demonstating the problem:
http://www.students.tut.fi/~salmi26/ScorpionBox.html
private function isPressed(event:TouchEvent):void
{
var touch:touch = event.getTouch(this);
if(touch.phase == TouchPhase.BEGAN){
trace("show");
//mouse is hovered over this object. Therefore call Hovertext:
if (Game.hoverText.message != name_)
Game.hoverText.message = name_
} else if(touch.phase == TouchPhase.ENDED){
trace("release");
//stop doing stuff
removeEventListener(Event.ENTER_FRAME, onButtonHold);
}
}
import starling.events.Touch;
import starling.events.TouchEvent;
import starling.events.TouchPhase;
private var touches:Vector.<Touch>;
private var touch:Touch;
private var touchStage:Touch;
private function onTouch(e:TouchEvent=null):void {
touches= e.getTouches(DisplayObject(e.target));
if (touches.length == 1)
{
touch = touches[0];
if (touch.phase == TouchPhase.BEGAN){
m_TouchTarget = touch.target;
//HERE IS A MOUSE DOWN
}
if (touch.phase == TouchPhase.ENDED){
m_TouchEndedPoint = new Point(touch.globalX, touch.globalY);
if (stage.hitTest(m_TouchEndedPoint, true) == m_TouchTarget)
{
//HERE IS A MOUSE UP
}
}
if (touch.phase == TouchPhase.MOVED){
m_TouchEndedPoint = new Point(touch.globalX, touch.globalY);
//HERE IS A MOUSE OUT
if (stage.hitTest(m_TouchEndedPoint, true) != m_TouchTarget)
{
//HERE IS A MOUSE OVER
}
}
}
}

Flash AS3 hit test go to next frame

I have a object that can be dragged into another object. I have set up a hit test for the collision. When the collision occurs I would like to progress to the next frame however, I have to click on the draggable object for it to do so. I would like it to move to the next frame right away without clicking. Is there anyway to fix this?
I mean after I have dragged the objected to create the collision I need to click on the object again to progress to the next frame. I do not want to have to click on the object again I want it to go to the next frame as the collision occurs.
This is my code
bottle.buttonMode = true;
bottle.addEventListener(MouseEvent.MOUSE_DOWN, drag);
bottle.addEventListener(MouseEvent.MOUSE_UP, drop);
function collision():void{
if(bottle.hitTestObject(hit)){
nextFrame();
}
}
function drag(e:MouseEvent):void{
bottle.startDrag();
collision();
}
function drop(e:MouseEvent):void{
bottle.stopDrag();
}
You should be checking for collisions after the drop, not at the start of the drag:
function collision():void{
if(bottle.hitTestObject(hit)){
nextFrame();
}
}
function drag(e:MouseEvent):void{
bottle.startDrag();
}
function drop(e:MouseEvent):void{
bottle.stopDrag();
collision();
}
Change collision() into an event listener and attach it to bottle.
Try this one ( adapted from Gary Rosenzweig ) :
bottle.buttonMode = true;
bottle.addEventListener( MouseEvent.MOUSE_DOWN, startBottleDrag );
stage.addEventListener( MouseEvent.MOUSE_UP, stopBottleDrag );
function collision():void {
if( bottle.hitTestObject( hit ) ) {
stopBottleDrag();
nextFrame();
}
}
// to keep bottle location as it is when clicked
var clickOffset:Point = null;
function startBottleDrag( e:MouseEvent ) {
clickOffset = new Point( e.localX, e.localY );
bottle.addEventListener( Event.ENTER_FRAME, dragBottle );
}
function stopBottleDrag( e:MouseEvent = null ) {
clickOffset = null;
bottle.removeEventListener( Event.ENTER_FRAME, dragBottle );
}
function dragBottle( e:Event ) {
bottle.x = mouseX - clickOffset.x;
bottle.y = mouseY - clickOffset.y;
collision();
}