startdrag start point limitations? - actionscript-3

I have a slider that controls a movie clip by dragging it through the frames to animate and this works great when dragging from left to right, But i want the slider to start in the middle and drag through the movie clip from a center point being able to go 350 to the right and 350 to the left.
Is this possible?
Heres my code so far and as you can see it drags 350 to the right through dialSpin_mc.
Is there a way to make the slider start at a certain frame and go backwards and forwards?
dialSpin_mc.stop();
slider_mc.knob_mc.buttonMode = true;
slider_mc.knob_mc.addEventListener(MouseEvent.MOUSE_DOWN, onDragKnob);
stage.addEventListener(MouseEvent.MOUSE_UP, onReleaseKnob)
slider_mc.knob_mc.buttonMode = true;
function onDragKnob(myEvent:Event):void
{
slider_mc.knob_mc.startDrag(false, new Rectangle(0,0,350,0));
slider_mc.knob_mc.addEventListener(Event.ENTER_FRAME, onScrubMovie);
}
function onReleaseKnob(myEvent:Event):void
{
slider_mc.knob_mc.stopDrag();
slider_mc.knob_mc.removeEventListener(Event.ENTER_FRAME, onScrubMovie);
}
function onScrubMovie(myEvent:Event):void {
var playHead:int=Math.round((slider_mc.knob_mc.x/350*8)+1);
dialSpin_mc.gotoAndStop(playHead);
}

As discussed in comments this is how you could code the slider functionality without using the startDrag() and stopDrag() functions.
The idea is that when you press the mouse button down over the slider, an ENTER_FRAME listener is created. Every frame the sliders X position will be updated to match the mouseX position, and to make sure it can only travel 175 pixels either way we also check the sliders new position.
After making sure the sliders position is valid, you can use the same code to set the dialSpin_mc frame.
Once the mouse button is released, the enter frame listener is removed.
The sliderOrigin declared at the top of the code will need to be changed to whatever is appropriate for your project (whatever the sliders xposition is when you move it to the middle of the slide area rather than the very left).
var sliderOrigin:int = 150; // The x position the slider is in when in the center of the slide bar
slider_mc.x = sliderOrigin;
slider_mc.addEventListener(MouseEvent.MOUSE_DOWN, mDown);
slider_mc.addEventListener(MouseEvent.MOUSE_UP, mUp);
function mDown(e:MouseEvent):void
{
addEventListener(Event.ENTER_FRAME, UpdateDrag);
}
function mUp(e:MouseEvent):void
{
removeEventListener(Event.ENTER_FRAME, UpdateDrag);
}
function UpdateDrag(e:Event):void
{
slider_mc.x = mouseX;
// Check if the slider is 'out of bounds' and change its position if it is
if(slider_mc.x < sliderOrigin - 175)
slider_mc.x = sliderOrigin - 175;
else if(slider_mc.x > sliderOrigin + 175)
slider_mc.x = sliderOrigin + 175
var playHead:int = Math.round((slider_mc.x/350*8)+1);
dialSpin_mc.gotoAndStop(playHead);
}
Depending on the start position of the slider the range of playHead will change (so if the slider starts at x pos 200 the range would be between 2 and 10, at x pos 400 the range is between 6 and 14 - simple fix by changing the offset from +1 to whatever is necassary).

Related

How to make a slider where you have to hit the middle of it in order to cause it to go to another scene

I am new to flash and want to make a slider where something moves back and for until you hit space bar in order to make land in the middle which would trigger a new scene. Sort of like a mini game.
Again im really new to actionscript so any help would be nice. I was thinking of calling like a function where the pointer is continuously moving until the space bar is hit. But Im really stuck. Please and thank you for your time.
Make sure your slider has the instance name "slider". Then try this code:
//x position of the most left position of the slider
var left_limit:Number = 50
//x position of the most right position of the slider
var right_limit:Number = 250
var speed:Number = 10
var dir:int = 1
//How close the slider has to be to the middle to trigger the next scene
var tolerance:Number = 10
addEventListener(Event.ENTER_FRAME,loop)
addEventListener(KeyboardEvent.KEY_DOWN,keydown)
function loop(e:Event){
slider.x += speed*dir
if(slider.x>right_limit){
slider.x = right_limit
dir = -1
}else if(slider.x<left_limit){
slider.x = left_limit
dir = 1
}
}
function keydown(e:KeyboardEvent){
if(e.keyCode==Keyboard.SPACE){
removeEventListener(Event.ENTER_FRAME,loop)
if(Math.abs((slider.x-left_limit)-(right_limit-left_limit)/2)<tolerance){
//succeeded go to next scene
gotoAndStop("scene2")
}else{
//failed
}
}
}

AS3 swipe gesture not very responsive

Here I go:
I'm doing this mobile app using AS3-AIR.
A deck of playing cards is shown in the center of the screen, and using the finger, you are able to flick off the top card to reveal the next one, using a swipe action.
It's a bird view, so only one card is showing, the user will assume that the rest of the deck is beneath the top card.
Cards are face down, so every time the user swipes a card off the screen, the same back image is displayed in the center over and over.
When the user double taps the back of a card, it flips over and the face of the card is revealed.
Here's my code (my questions come right after):
//Adding three same backs of cards to the stage:
addChild(backBlue3); //No event listener will be attached to this card
addChild(backBlue2);
addChild(backBlue1);
//backBlue1 and backBlue2 will alternate their Indexes/depths to create the illusion of an infinite deck of cards. So, when backBlue1 is thrown out of the screen, backBlue2 immediately fills the center of screen.
Multitouch.inputMode = MultitouchInputMode.GESTURE;
backBlue1.addEventListener(TransformGestureEvent.GESTURE_SWIPE, backCard_handler_swipe);
backBlue2.addEventListener(TransformGestureEvent.GESTURE_SWIPE, backCard_handler_swipe);
backBlue1.addEventListener(MouseEvent.DOUBLE_CLICK, cardFlipper);
backBlue2.addEventListener(MouseEvent.DOUBLE_CLICK, cardFlipper);
public function backCard_handler_swipe(e:TransformGestureEvent):void
{
//*********************************** Setting the random positions for swiped off cards ***********************************
//Swipe is done towards the left
if (e.offsetX == -1)
{
randomX = Math.floor(Math.random() * (randomMaxX - randomMinX + 1)) + randomMinX;
}
//Swipe is done towards the right
if (e.offsetX == 1)
{
randomX = Math.floor(Math.random() * (randomMaxX2 - randomMinX2 + 1)) + randomMinX2;
}
randomY = Math.floor(Math.random() * (randomMaxY - randomMinRotation + 1)) + randomMinY;
randomRotation = Math.floor(Math.random() * (randomMaxRotation - randomMinRotation + 1)) + randomMinRotation;
//*********************************** Creating a GreenSock TimeLineMax timeline to tween the "ejected" card ***********************************
var tl15 = new TimelineMax();
tl15.addLabel("cardOnScreen"); //At this point of the Timeline (the very beginning), a "Swiping sound" will be played.
if (e.target == backBlue1)
{
//backBlue1 is tweened off the screen
tl15.to(e.target, 1, {y:randomY, x:randomX, rotation:randomRotation, ease:Circ.easeOut});
//backBlue2 is instantly placed in the center of the screen, behind backBlue1
tl15.to(backBlue2, 0, {y:initialY2, x:initialX2, rotation:0, ease:Linear.easeNone}, "-=1");
tl15.addLabel("cardOffScreen", "-=0.5"); //The exact middle of the backBlue1 tween animation
tl15.addCallback(playSlide, "cardOnScreen"); //Playing the "Swiping Sound".
tl15.addCallback(swapingBacks, "cardOffScreen"); //swapingBacks function is called to place backBlue2 on top of backBlue1
}
if (e.target == backBlue2)
{
tl15.to(e.target, 1, {y:randomY, x:randomX, rotation:randomRotation, ease:Circ.easeOut});
tl15.to(backBlue1, 0, {y:initialY2, x:initialX2, rotation:0, ease:Linear.easeNone}, "-=1");
tl15.addLabel("cardOffScreen", "-=0.5");
tl15.addCallback(playSlide, "cardOnScreen");
tl15.addCallback(swapingBacks, "cardOffScreen");
}
}
public function swapingBacks()
{
swapChildren(backBlue1, backBlue2);
}
public function cardFlipper(e:MouseEvent)
{
//Flipping of the card is working fine
}
Here are my two main problems:
-1-
The swipe gesture is not very responsive: One out of four or five swipes, nothing happens. I have to do the swipe action twice or sometimes even more to finally flick the card off.
I removed the double click listener in case of conflict with the gesture listener, the problem is still there.
Is it the standard AS3 gesture listener that is not performant?
Ideally, the swipe gesture should be as in the TINDER app: very reponsive (and with drag action).
Is there any alternative to the standard GESTURE_SWIPE solution?
Any suggestions to my code above?
-2-
If the user swipes very fast, the SECOND card (beneath the first one) is swiped off, not the first. How can I avoid that?
Thanks a lot for your ideas, and thanks for reading!
BR
UPDATE ON FEBRUARY 10th
So I followed Mark Knol's advice (see answers below) and used a MOUSE_DOWN & MOUSE_UP events handlers instead of SWIPE GESTURE handlers.
The result is better, but not perfect.
The result is better, because the dragging that happens when mouse is down solves the issue of second card flying out the screen.
The result is not perfect because there's a conflict between MOUSE_DOWN/MOUSE_UP events with the DOUBLE_CLICK event: When I double tap a card, the two taps are both detected as two micro-drags of the card but also as a double tap action!!
So I did the following:
For a clear and big drag of the card towards the edges of the screen, the card is tweened off the screen when the mouse/finger is released.
For a small drag of the card, the card is tweened back to its original position. This way, in case of double tap of the card, the flipping will happen from the original position of the card.
I'm still stuck with the following issues:
Why in the ANDROID AIR compiled application, the double clicking is detected, but on windows flash player the double clicking is not detected?
Is there a way to solve the conflict between "double click" & "Click" events? (maybe by delaying the dragging action until the system makes sure it's not a double click occuring?)
backBlue1.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
backBlue2.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
backBlue1.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
backBlue2.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
backBlue1.addEventListener(MouseEvent.DOUBLE_CLICK, cardFlipper);
backBlue2.addEventListener(MouseEvent.DOUBLE_CLICK, cardFlipper);
function mouseDownHandler(e:MouseEvent):void
{
e.target.startDrag();
}
function mouseUpHandler(e:MouseEvent):void
{
e.target.stopDrag();
ecartX = initialX2 - e.target.x; //ecartX is the distance of the final card position with the original one.
if (Math.abs(ecartX) < limitX) //For a very small drag, the card is tweened back to its initial place
{
var tl25 = new TimelineMax();
tl25.to(e.target, 0.5, {y:initialY2, x:initialX2, rotation:0, ease:Linear.easeNone}, "-=0");
}
if (Math.abs(ecartX) > limitX) //For a clear long drag, the card is tweened off the screen
{
//Swipe to the left
if (ecartX > 0)
{
randomX = Math.floor(Math.random() * (randomMaxX - randomMinX + 1)) + randomMinX;
}
//Swipe to the right
if (ecartX < 0)
{
randomX = Math.floor(Math.random() * (randomMaxX2 - randomMinX2 + 1)) + randomMinX2;
}
randomY = Math.floor(Math.random() * (randomMaxY - randomMinRotation + 1)) + randomMinY;
randomRotation = Math.floor(Math.random() * (randomMaxRotation - randomMinRotation + 1)) + randomMinRotation;
var tl15 = new TimelineMax();
tl15.addLabel("cardOnScreen");
if (e.target == backBlue1)
{
tl15.to(e.target, 1, {y:randomY, x:randomX, rotation:randomRotation, ease:Circ.easeOut});
tl15.to(backBlue2, 0, {y:initialY2, x:initialX2, rotation:0, ease:Linear.easeNone}, "-=1");
tl15.addLabel("cardOffScreen", "-=0.5");
tl15.addCallback(playSlide, "cardOnScreen");
tl15.addCallback(swapingBacks, "cardOffScreen");
}
if (e.target == backBlue2)
{
tl15.to(e.target, 1, {y:randomY, x:randomX, rotation:randomRotation, ease:Circ.easeOut});
tl15.to(backBlue1, 0, {y:initialY2, x:initialX2, rotation:0, ease:Linear.easeNone}, "-=1");
tl15.addLabel("cardOffScreen", "-=0.5");
tl15.addCallback(playSlide, "cardOnScreen");
tl15.addCallback(swapingBacks, "cardOffScreen");
}
}
}
public function cardFlipper(e:MouseEvent)
{
//...
}
You could consider to make your own swipe detection. Basically you register a startpoint on DOWN, and check if endpoint is greater on UP, then that is a swipe to right. Of course for a swipe to left, the other end position is lower.
While dragging you move the card at touch position and on UP you tween the card to desired target position.
I also would disable user interaction (mouseEnabled, mouseChildren to false?) on the cards below the current one, enable as soon as possible after a valid swipe.

How to create a loop between the mask and the background image in AS3 when mouseover

I am new in AS3, for one of my assignment, I need to modified the existing code(copy paste and modify) to create certain effect. The effect that I need to create is when I MouseOver on the stage, the mask will form a loop with background image and back to normal(mask layer not visible) when I MouseOut of the stage. Here is the code that need to modifly.
var mymask:Sprite=new Sprite();
var isOver:Boolean=false;
var spotSize:Number=0;
pic2.addChild(mymask);
pic2.mask=mymask;
pic2.mouseEnabled=false;
mymask.x=0;
mymask.y=0;
function drawSpot(r:Number):void{
mymask.graphics.clear();
mymask.graphics.lineStyle(1,0x000000);
mymask.graphics.beginFill (0x00000F);
mymask.graphics.drawRect(0,0,r,900);
mymask.graphics.endFill();
spotSize=r;
}
pic1.addEventListener(MouseEvent.ROLL_OVER, mouseOver);
function mouseOver(e:MouseEvent):void{
isOver=true;
}
pic1.addEventListener(MouseEvent.ROLL_OUT, mouseOut)
function mouseOut(e:MouseEvent):void{
isOver=false;
}
stage.addEventListener(Event.ENTER_FRAME, enter);
function enter(e:Event):void{
var cursorSize:Number=spotSize;
if(isOver==true && cursorSize<1)
drawSpot(cursorSize+999);
if(isOver==false && cursorSize>10)
drawSpot(cursorSize-999);
}
Sounds like you're trying to animate a circular mask by modifying the code above?
If so, this is the code changes needed.
In your drawSpot method, change the line:
mymask.graphics.drawRect(0,0,r,900);
to:
mymask.graphics.drawCircle(pic2.width * .5, pic2.height * .5, r);
Then in your enter method,
function enter(e:Event):void{
var cursorSize:Number=spotSize;
if(isOver==true && cursorSize<999)
drawSpot(cursorSize+1);
if(isOver==false && cursorSize>0)
drawSpot(cursorSize-1);
}
What you're doing is saying IF the mouse is over and the cursorSize is less than the full value (you had 999 before so I kept that) then increment the size by 1. It will keep doing this every frame until the size is 999 or higher (or the mouse is no longer over).
If the mouse isn't over and the mask isn't 0 in size, it will decrease the size by 1 every frame until it's 0 or less.
If you want it to go faster, simply change the +1 and -1 to a higher number

actionscript 3 position textfield N pixels from bottom or 90% from top

I'm new to actionscript 3. I want to create a textfield that is either N number of pixels from the bottom of the stage or 90% from the top of the stage.
Basically i want the textfield to always appear near the bottom of the stage. What property of the TextField() object do I configure to achieve this?
function updateTextPosition():void
{
var newPositionY:Number = (stage.stageHeight * .90);
myTextField.y = newPositionY;
}
Now if you want to account for the height of the actual text for whatever reason, you change it to this:
function updateTextPosition():void
{
var newPositionY:Number = (stage.stageHeight * .90) - myTextField.textHeight;
myTextField.y = newPositionY;
}
Remember the origin of the field is top left, so the bottom of the text will appear at myTextField.x + myTextField.textHeight;.
Also, you can listen for the RESIZE event on the stage and update your TextField like so:
stage.addEventListener(Event.RESIZE, onStageResized);
function onStageResized(e:Event):void
{
updateTextPosition();
}

Problem rotating image with MOUSE_MOVE

Hey gang. Stumped on something.
I have a disc I am rotating with the mouse with event.MOUSE_MOVE, like a jog wheel on some audio equipment. Everything almost works as expected, but the problem I am experiencing is that the disc always jumps to the point where the user clicks on the disc. I need the point on the disc that the user clicks on to remain under the mouse while the user spins the disc but I can't seem to come up with the correct math to make it happen. Here's the code i am using:
var xd = (_knob.x - _stageRef.stage.mouseX);
var yd = (_knob.y - _stageRef.stage.mouseY);
var radAngle = Math.atan2(yd, xd);
_knob.rotation = int(radAngle * 360/(Math.PI * 2) - 90);
_knob is a vector circle wrapped in a movieclip, with the circle centered on the movieclip's reg point. _stageRef represents the main stage.
Any help would be awesome. I've scoured the interweb and can't come up with anything.
Thx!
You are setting _knob rotation to the angle between _knob and mouse cursor. So if rotation was 0, and angle 45, rotation becomes 45, therefore it jumps. What you need is measure changes in this angle, not setting it instantly:
var _mouseAngle:Number;
function getMouseAngle():Number
{
var xd = (_knob.x - _stageRef.stage.mouseX);
var yd = (_knob.y - _stageRef.stage.mouseY);
return Math.atan2(yd, xd);
}
function onMouseDown(event:MouseEvent):void
{
_mouseAngle = getMouseAngle();
}
function onMouseMove(event:MouseEvent):void
{
var newAngle:Number = getMouseAngle();
_knob.rotation += (newAngle - _mouseAngle) * 180.0 / Math.PI; //EDIT: forgot to convert into degrees
_mouseAngle = newAngle;
}
(Code not tested)