Moving A MovieClip to Left/Right Using Touch Events with simultaneous touches - actionscript-3

I am Developing a game, AS3 Adobe air targeted for both android and ios, in which you have a movie clip in the center, and two buttons ( left and right ) that should move that movie clip. My goal is to make the shift between the left/right as smooth as possible :
- if the player is touching the left button, the movie clips moves left. if he removes he's finger from the left button, and touches immediately the right button, the movie clip won't move, it's until he re-touches the right button , that the movie clips moves right. I have tried to implement multitouch events, but i seem to have something wrong since this is the behavior i'm getting.
- if the player is touching the left button, the movie clips moves left as expected, if he touches the right button, the movie clip stops as expected, but if he removes his finger from the left button while keeping it on the right button, the movie clip still freezes and don't move, it should move then to the right
This is the code i am using :
leftButtonCreated.addEventListener(TouchEvent.TOUCH_BEGIN,mouseDown);
rightButtonCreated.addEventListener(TouchEvent.TOUCH_BEGIN,mouseDown2);
stage.addChild(leftButtonCreated);
stage.addChild(rightButtonCreated);
function mouseDown(e:TouchEvent):void
{
stage.addEventListener(TouchEvent.TOUCH_END,mouseUp1);
//listen for mouse up on the stage, in case the finger/mouse moved off of the button accidentally when they release.;
addEventListener(Event.ENTER_FRAME,myButtonClick);//while the mouse is down, run the tick function once every frame as per the project frame rate
}
function mouseUp1(e:TouchEvent):void
{
removeEventListener(Event.ENTER_FRAME,myButtonClick);//stop running the tick function every frame now that the mouse is up
stage.removeEventListener(TouchEvent.TOUCH_END,mouseUp1);
}
function mouseDown2(e:TouchEvent):void
{
stage.addEventListener(TouchEvent.TOUCH_END,mouseUp2);
//listen for mouse up on the stage, in case the finger/mouse moved off of the button accidentally when they release.;
addEventListener(Event.ENTER_FRAME,stopDragging);//while the mouse is down, run the tick function once every frame as per the project frame rate
}
function mouseUp2(e:TouchEvent):void
{
removeEventListener(Event.ENTER_FRAME,stopDragging);//stop running the tick function every frame now that the mouse is up
stage.removeEventListener(TouchEvent.TOUCH_END,mouseUp2);
}
function stopDragging(ev2:Event):void
{
if (MC.x <= rightButtonCreated.x)
{
MC.x = MC.x + 10;
}
}
function myButtonClick(ev:Event):void
{
if (MC.x > leftButtonCreated.x)
{
MC.x = MC.x - 10;
}
else
{
}
}
The Code was initially set for mouseEvents, so i tried to shift to touch events so i could fix this problem, and the code above is what i got. Thank you for your time.
EDIT:
And, i use the following code :
var leftButtonCreated:leftB= new leftB();

Your current problem is that both mouseUp1 and mouseUp2 are triggered once you release the left button, as they are both attached to stage. But your actual problem is deeper. You should first move the object left and right if corresponding buttons are pressed, and use TouchEvent.touchPointID to track which touch has been released to understand which button was released.
Also a potential caveat: If you touch both left and right button, then swap fingers while retaining both touches, then release the finger that's over the right button - where should your object move, left or right? I say the correct answer is to the right, as the finger released corresponds to the left button.
leftButtonCreated.addEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
rightButtonCreated.addEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
leftButtonCreated.addEventListener(TouchEvent.TOUCH_END,touchUp);
rightButtonCreated.addEventListener(TouchEvent.TOUCH_END,touchUp);
addEventListener(Event.ENTER_FRAME,moveObject);
function touchDown(e:TouchEvent):void {
var button:DisplayObject=e.currentTarget as DisplayObject;
if (!button) return; // can't fail typecast to DisplayObject in this context, but leave for good measure
if (button==leftButtonCreated) {
leftButtonPressed=true;
leftButtonTouchID=e.touchPointID;
return;
}
if (button==rightButtonCreated) {
rightButtonPressed=true;
rightButtonTouchID=e.touchPointID;
return;
}
}
function touchUp(e:TouchEvent):void {
var button:DisplayObject=e.currentTarget as DisplayObject;
if (!button) return;
var ti:int;
if (button==leftButtonCreated) {
ti=leftButtonTouchID;
if (ti==e.touchPointID) {
leftButtonPressed=false;
}
}
if (button==rightButtonCreated) {
ti=rightButtonTouchID;
if (ti==e.touchPointID) {
rightButtonPressed=false;
}
}
}
function moveObject(e:Event):void {
if (leftButtonPressed) MC.x-=10;
if (rightButtonPressed) MC.x+=10;
if (MC.x<leftButtonCreated.x) MC.x=leftButtonCreated.x;
if (MC.x>rightButtonCreated.x) MC.x=rightButtonCreated.x;
}
EDIT: Apparently SimpleButtons don't allow the events to propagate outside to their parents. Okay, this can still be remedied, but you will have to store the required properties in your Main class.
var leftButtonPressed:Boolean=false;
var rightButtonPressed:Boolean=false;
var leftButtonTouchID:int=0;
var rightButtonTouchID:int=0;
The above code has been updated. Please return to using SimpleButtons directly, as you were using with var leftButtonCreated:leftB= new leftB();.

Related

AS3 Apache Flex: click randomly not updating stage until mouse moves

I have a SWF that displays a field of stars as a single BITMAP added to the Stage. The image is dynamically generated through the Bitmap's BitmapData, to allow trackball interaction with the star field. Planets and other buttons are also on the stage with hint Labels underneath.
All works as expected. However, sometimes clicking a button, performs an operation, that does not show up until the mouse moves. For example, clicking the button to toggle planet labels, will immediately update the stage with labels turning on and off. But sometimes, the click does nothing, until the mouse is moved, or another click is made and then both clicks activate in series.
Same goes for a button that resets the star field to show either the Sun to Earth or Earth to Sun view. Click the image (button) and the background star field updates immediately. However, sometimes it does nothing until the mouse moves. It seems like an interface timing issue beyond my control.
Anybody encounter this situation? Working on MAC with Firefox, all latest updates.
Here's the event code.
private function moveRespond(e:MouseEvent):void {
var X:int=mouseX,Y:int=mouseY,R:int=Assets.Assets.radius/10; if(R<15){R=15}
if( moveActive ) {
Assets.Assets.STUFF.view.rotateMatrix(PT.x,PT.y,X,Y);
FIELD.update(w,h);
}
else {
Assets.Assets.STUFF.line.hover(X,Y,R);
var btn:Vector.<Button>=Assets.Assets.BTN_list;
var i:int,I:int=btn.length;
for( i=0; i<I; i++ ) {
btn[i].label.visible=btn[i].hover(X,Y);
} }
DP.x=PT.x-X; PT.x=X;
DP.y=PT.y-Y; PT.y=Y;
}
private function upRespond(e:MouseEvent):void { moveActive=false }
private function downRespond(e:MouseEvent):void { moveActive=true;
var X:int=mouseX,Y:int=mouseY;
PT.x=X; PT.y=Y;
}
private function clickRespond(e:MouseEvent):void {
...
//lots of button management, similar to above
//FIELD.update(w,h); and new zodiac sign fetch...
//but if there was a soft error in here,
//then the click at the end would get skipped,
//and it doesnt.
...
if( click ) { Assets.Assets.soundClick(X); }
}
Because of the randomness of the error, I'm assuming a memory thrashing somewhere in my code that is interrupting the next event, but kinda hoping its a communications issue because the missed-click is Event-queued. It just doesnt get sent to my App until either a move or another click. The App.swf can be run without the wrapper (preloader basically), and it has the same randomness. Even though it is very rare, it is still very annoying.
There is also a ConstantUpdate timer:
public function constantUpdate(evt:TimerEvent):void {
Mouse.hide(); Mouse.show();
dateMessage();
if( !Assets.Assets.BTN_help.glowing && Math.random()<0.05 ) { Assets.Assets.BTN_help.glow(); }
if( !Assets.Assets.BTN_logo.glowing && Math.random()<0.01 ) { Assets.Assets.BTN_logo.glow(); }
if( !Assets.Assets.BTN_next.glowing && Math.random()<0.05 ) { Assets.Assets.BTN_next.glow(); }
Assets.Assets.BTN_help.update();
Assets.Assets.BTN_logo.update();
Assets.Assets.BTN_next.update();
Assets.Assets.BTN_star.update();
Assets.Assets.BTN_note.update();
Assets.Assets.BTN_moon.update();
}
Just more button management. The Mouse hide/show pings the Mouse after the contextMenu deactivates. Otherwise, the mouse turned into an arrow over the contextMenu and would stay that way until mouse left the window and returned. Still have some mouse hick-ups on startup though - not setting my cursor after App.swf loaded. Have no idea if that is related to the clicking issue, but here's that code:
var cursor:MouseCursorData=new MouseCursorData();
cursor.hotSpot=new Point(
Assets.Assets.BTN_sun.icon.width/2,
Assets.Assets.BTN_sun.icon.height/2);
var pointer:Vector.<BitmapData>=new <BitmapData>[Assets.Assets.BTN_sun.icon.bitmapData];
cursor.data=pointer;
Mouse.registerCursor("myCursor",cursor);
Mouse.cursor="myCursor";
I dont keep a local handle to the cursor object.

swipe gesture is not smooth for frame jumping

I have made an as3 android app where I have used swipe gesture for going next frame and previous frame. but I want when I jump to next or previous frame it swipes smoothly.I have tried to use tween max but it is not working.I have found that tween plugins always work for movie clips.So how can I make the swipe smooth.Can I make it smooth without tween plugins?here is my code....
Multitouch.inputMode = MultitouchInputMode.GESTURE;
stage.addEventListener (TransformGestureEvent.GESTURE_SWIPE, SwipeHandler);
function SwipeHandler(event:TransformGestureEvent):void
{
switch(event.offsetX)
{
// swiped right
case 1:
{
prevFrame();
break;
}
// swiped left
case -1:
{
if(currentFrame == 10)
{
stop();
}
else
{
nextFrame();
break;
}
}
}
}
In order for you to be able to smooth swap you need to have both frames on your screen, which is not the case with genuine Flash frames. Smooth transitions are animated via ENTER_FRAME handlers, with a potential hide of actual frame change process. So, in order to do a smooth transition, you need to move a picture of one frame to the left, and for the other frame to move in from the right instead of plain nextFrame(). Let's say you have a 60fpa stage, and try to smooth transition left. You will need two screen-sized objects, one depicting current frame and one the frame to be displayed, ready to be displayed as a single transition. An example:
var transition:Sprite;
var bitmaps:Array;
var leftSide:Bitmap
var rightSide:Bitmap;
// initialization code, best placed in constructor
leftSide=new Bitmap();
rightSide=new Bitmap();
bitmaps=[];
transition=new Sprite();
transition.addChild(leftSide);
transition.addChild(rightSide);
rightSide.x=stage.stageWidth; //left side and right side should be aside each other
This is the declaration of the needed structures. The plan is to show the transition, giving it two Bitmaps that will be linked to two different BitmapData objects that'll hold pictures of new frame and old frame. We will draw our current frame on current frame's bitmapdata, then take a stored next frame bitmap data and the do transition.
function swipeHandler((event:TransformGestureEvent):void {
var doSwitch:Boolean=false;
var targetFrame:int=currentFrame;
switch(event.offsetX) {
// swiped right
case 1: {
if (currentFrame>2) {
// let's say we're not allowed to swipe right from frame 2
targetframe=currentFrame-1;
doSwitch=true;
}
break;
}
// swiped left
case -1: {
if(currentFrame < 10) {
targetFrame=currentFrame+1;
doSwitch=true;
}
break;
}
}
if (!doSwitch) return;
// prepare transition
if (!bitmaps[targetFrame]) bitmaps[targetFrame]=new BitmapData(stage.stageWidth,stage.stageHeight,false,0xffffff);
// ^ make a new bitmap if there's none for target frame
if (!bitmaps[currentFrame]) bitmaps[currentFrame]=new BitmapData(stage.stageWidth,stage.stageHeight,false,0xffffff);
// the same for source frame
bitmaps[currentFrame].fillRect(bitmaps[currentFrame].rect,0xffffff);
bitmaps[currentFrame].draw(stage); // draw current frame on the bitmap
// with this and stored bitmaps, old frame would remain drawn on the cached bitmap
// and able to be used as a transition image
if (targetFrame>currentFrame) {
leftSide.bitmapData=bitmaps[currentFrame];
rightSide.bitmapData=bitmaps[targetFrame];
transition.x=0;
// here is the place to initialize TweenMax tween to move "transition"
// and don't forget to removeChild(transition) at the end of the tween
} else {
rightSide.bitmapData=bitmaps[currentFrame];
leftSide.bitmapData=bitmaps[targetFrame];
transition.x=-1*stage.stageWidth;
// same here for tweening
}
stage.addChild(transition);
gotoAndStop(targetFrame);
}
This places a prepared transition object on screen above all the underlying items, effectively masking the exact frame switch, done by gotoAndStop() call. This object's x coordinate can be tweened afterwards, and the object should be removed from stage once the tween is ofer.
Hope this helps.

Problems disabling movieclip button flash/as3

I've got a screen which involves a movie-clip where the object has a outline to symbolize that it can be clicked. Upon clicking the object, I'm requesting it to do numerous functions, disable itself and then go to another frame which removes the outline symbolizing it cannot be clicked anymore. But once you disable an object it goes to the original frame.
The object itself consists of these 3 frames.
Frame 1: Original State (Glow)
Frame 2: Hover over giving stats
Frame 3: No glow
To summerise i'd like to click the object and for it to go to the no glow frame and disable the movieclip.
The movieclip enabled = 1 is for when the user returns to the this frame, so the scene is aware of the button press.
Movieclip.addEventListener(MouseEvent.CLICK, Fun_Movieclip);
Movieclip.addEventListener(MouseEvent.MOUSE_OVER, Fun_MovieclipMouseOver);
Movieclip.addEventListener(MouseEvent.MOUSE_OUT, Fun_MovieclipMouseOut);
function Movieclip(event:MouseEvent):void
{
MovieclipEnabled = 1;
Movieclip.gotoAndStop(1);
Movieclip.mouseEnabled = false;
}
function Fun_MovieclipMouseOver(event:MouseEvent):void
{
Movieclip.gotoAndStop(2);
}
function Fun_MovieclipMouseOut(event:MouseEvent):void
{
Movieclip.gotoAndStop(3);
}
For some reason when ever the movieclip is disabled, it always reverts back to the glow state. Does anyone have a solution for this? Cheers
Edit: Inside the movieclip, the first frame has Stop();. Don't know if this would interfere with it.
mc.addEventListener(MouseEvent.CLICK, clickHandler);
mc.addEventListener(MouseEvent.MOUSE_OVER, mouseoverHandler);
mc.addEventListener(MouseEvent.MOUSE_OUT, mouseoutHandler);
function clickHandler(event:MouseEvent):void
{
mc.gotoAndStop(3);
mc.removeEventListener(MouseEvent.CLICK, clickHandler);
mc.removeEventListener(MouseEvent.MOUSE_OVER, mouseoverHandler);
mc.removeEventListener(MouseEvent.MOUSE_OUT, mouseoutHandler);
}
function mouseoverHandler(event:MouseEvent):void
{
mc.gotoAndStop(2);
}
function mouseoutHandler(event:MouseEvent):void
{
mc.gotoAndStop(1);
}
Not entirely sure what you meant by:
The movieclip enabled = 1 is for when the user returns to the this frame, so the scene is aware of the button press.
My suggestion for getting the scene to recognize the button click is to have the scene also listen to the mouse click handler

Scrolling Left To Right With Actionscript 3.0

maybe someone can help me with this Adobe Flash Actionscript 3.0 question.
I'm trying to make a timeline with "buttons" on the left and right most part of the screen so the timeline can be scrubbed when the mouse goes to those parts of the screen. The buttons themselves are simply there as a means to show the user where they need to hover over in order to make the timeline scroll in that direction.
I've been able to get the timeline to scrub once with the code below, but I want to make it so that it keeps scrolling for the duration of time that the user keeps their mouse over it.
Also I placed an If statement that prevents the timeline from being scrolled off the screen.
Currently the code is only used once and goes left to right on the X axis by 15. How do I make it so it keeps steadily moving to the left or right until the mouse is off the scroll buttons?
//Scroll Logic
backScroll_btn.addEventListener(MouseEvent.ROLL_OVER, backScroll);
function backScroll(e:MouseEvent){
if(timeLine.x < 1406.55){
timeLine.x = timeLine.x + 15;}
}
forwardScroll_btn.addEventListener(MouseEvent.ROLL_OVER, forwardScroll);
function forwardScroll(e:MouseEvent){
if(timeLine.x > 0){
timeLine.x = timeLine.x - 15};
}
Since you want a continuous scroll, use an enter frame event listener to trigger the scroll. The buttons will then have two listeners triggering the scrolling on/off for either side.
var scrollingBack:Boolean;
var scrollingForward:Boolean;
backScroll_btn.addEventListener(MouseEvent.ROLL_OVER, backScrollOn);
backScroll_btn.addEventListener(MouseEvent.ROLL_OUT, backScrollOff);
function backScrollOn(e:MouseEvent):void { scrollingBack=true; }
function backScrollOff(e:MouseEvent):void { scrollingBack=false; }
forwardScroll_btn.addEventListener(MouseEvent.ROLL_OVER, forwardScrollOn);
forwardScroll_btn.addEventListener(MouseEvent.ROLL_OUT, forwardScrollOff);
function forwardScrollOn(e:MouseEvent):void { scrollingForward=true; }
function forwardScrollOff(e:MouseEvent):void { scrollingForward=false; }
timeline.addEventListener(Event.ENTER_FRAME,doScroll);
function doScroll(e:Event):void {
if (scrollingForward) {
if(timeLine.x > 0){
timeLine.x = timeLine.x - 15};
} else if (scrollingBack) {
if(timeLine.x < 1406.55){
timeLine.x = timeLine.x + 15;}
}
}
I think this may work, have enterframe event listen when the item is rollover and increase the X by every frame unitl the mouse roll out of the button.
backScroll_btn.addEventListener(MouseEvent.ROLL_OVER, backScroll);
function backScroll(e:MouseEvent):void
{
addEventListener(Event.ENTER_FRAME,myButton);
backScroll_btn.addEventListener(MouseEvent.ROLL_OUT, backScrollOut);
}
function backScrollOut(e:MouseEvent):void
{
removeEventListener(Event.ENTER_FRAME,myButton);
}
function myButton(e:Event):void
{
timeLine.x+=15;
}

AS3 - MouseWheelDown listener

Is there any way to detect if the mouse wheel is held down? I need to pan my scene while the middle button or mouse wheel is pushed down (I thought holding the mouse wheel down was the same as middle mouse button, but it aint working).
Thanks!
Though I never used it there's MIDDLE_CLICK event which works only in AIR apps. Does your app run in browser or on desktop?
Also, just my 2 cents, it's so damn inconvenient to use scrollwheel button in an application. Each time I am forced to do that in some 3D modelling tool I want to smash my monitor. I'd use just shift/alt/ctrl + mouse1/mouse2.
How about trying out this:
this.onEnterFrame = function() {
if (ASnative(800, 2)(1)) {
trace ("You have pressed or depressed the left mouse button");
}
}
this detects the left mouse... if you substitute the argument (1) with (2) you get the right mouse button so...
this.onEnterFrame = function() {
if (ASnative(800, 2)(2)) {
trace("You have pressed or depressed the right mouse button");
}
}
and if you put in a (4) you get the middle mouse or often the wheel button...
this.onEnterFrame = function() {
if (ASnative(800, 2)(4)) {
trace("You have pressed or depressed the middle mouse or wheel button");
}
}
Source: http://www.actionscript.org/forums/showthread.php3?t=68209
PS: I would suggest not using the middle mouse or wheel button because not everyone has a middle mouse button. So if you still want the usability of a middle mouse button, please adjust your functions accordingly so a person without a middle mouse button can still pan the canvas.
EDIT:
Ok, I made a booboo! Didn't catch it had to be for AS 3.0.
The support for the middle/right mouse button click is no longer available in AS 3.0.
Atleast not directly.
One way to do it is using JS to detect the mouse button that's being pressed and then giving that variable as a string into Flash.
How to detect a mouse click in JS:
http://www.quirksmode.org/js/events_properties.html
How to put this variable into Flash: (ExternalInterface)
http://learn.adobe.com/wiki/display/Flex/External+Interface
Or you can do it directly through a hack in AS 3.0: (limited browser & OS support)
http://flashpunk.net/forums/index.php?topic=2549.0
DEMO: http://www.shinyhappypixels.com/punk-forums/clicky-hook/
This is possible with as3, came across this so here it is:
import flash.events.MouseEvent;
function handleMouseWheel(event:MouseEvent):void {
if ((event.delta > 0 && box_mc.y < 270) || (event.delta < 0 && box_mc.y > 0)) {
box_mc.y = box_mc.y + (event.delta * 3);
}
}
stage.addEventListener(MouseEvent.MOUSE_WHEEL, handleMouseWheel);