TransformGestureEvent.GESTURE_PAN event does not fire - actionscript

I have the following code for ios app,
Multitouch.inputMode = MultitouchInputMode.GESTURE;
var mySprite:Sprite = new Sprite();
mySprite.addEventListener(TransformGestureEvent.GESTURE_PAN, onPan);
mySprite.addEventListener(TransformGestureEvent.GESTURE_SWIPE, onSwipe);
mySprite.addEventListener(TransformGestureEvent.GESTURE_ZOOM, onZoom);
mySprite.addEventListener(MouseEvent.CLICK, onClick);
mySprite.graphics.beginFill(0x336699);
mySprite.graphics.drawRect(0, 0, 80, 80);
mySprite.x = 100;
mySprite.y = 100;
var myTextField:TextField = new TextField();
myTextField.y = 200;
addChild(mySprite);
addChild(myTextField);
myTextField.text = "Wait";
function onClick(e:MouseEvent):void {
myTextField.text = "onClick";
}
function onPan(e:MouseEvent):void {
myTextField.text = "onPan";
}
function onSwipe(e:TransformGestureEvent):void {
myTextField.text = "onSwipe";
}
function onZoom(e:TransformGestureEvent):void {
myTextField.text = "onZoom";
}
When I test the app on itouch, everything works except onPan. It seems the TransformGestureEvent.GESTURE_PAN event never fires no matter what I do. When I move my finger while pressiing down, the onSwipe gets called. If I comment out the event listener for TransformGestureEvent.GESTURE_SWIPE then nothing gets called when I move my finger while pressing down.
Am I doing the pan gesture wrong? What is the difference between TransformGestureEvent.GESTURE_PAN and TransformGestureEvent.GESTURE_SWIPE gestures?
Thank you very much for any answer.

TransformGestureEvent.GESTURE_PAN works with two fingers.
Try it and you will check that when you press the screen with two fingers and move, the object will start panning.
Use instead MouseEvent.MOUSEMOVE
EDIT: Look this sentence from one Manual:
When a user grabs an object with two fingers and drags it, the TransformGesture
Event.GESTURE_PAN event is triggered and the onGesturePan method is called. Within the
onGesturePan method, the offsetX and offsetY values of this event are written to the
text property of the TextArea component. Adding the event’s offsetX and offsetY values
sets the object’s x and y to move the object across the stage.
Hope this help.

Pan only worked for me when I did double-finger press and move. I cant find a proper description of what these different gestures actually are, but that's what it seems to be.

function onPan(e:MouseEvent): must be onPan(e:TransformGestureEvent)

Related

making a UIimage move every 1 second

I have a UIimage which I want to move according to X and Y given by certain equations ( physics projectile time equations) and I want it to move every 1 second so that it would appear to the user as if it's actually moving not just disappearing and reappearing at the last position, plus the positions given off are wrong I think. I would appreciate any help for either or both problems.
So far I tried this:
The movement function:
func moveCannonBall(toX:Int , toY:Int ){
var frm: CGRect = ballimageview.frame
frm.origin.x = frm.origin.x + CGFloat(toX)
frm.origin.y = frm.origin.y - CGFloat(toY)
ballimageview.frame = frm
}
On button click it's supposed to take the user's inputs (gravity, angle, and the initial speed)
#IBAction func getAlpha( sender:AnyObject){
gravity = Float(g[pickerView.selectedRow(inComponent: 0)])
xMax = ((V0*V0)*sin(2.0*angle))/gravity
It's supposed to stop every 1 second but only the calculations pause every 1 second and the UIimage just disappears and reappears just
while Int(toX) < Int(xMax) {
sleep(1)
t = t + 1
toX = V0*cos(angle)*t
toY = -0.5*gravity*t*t + V0*sin(angle)*t
moveCannonBall(toX: Int(toX), toY: Int(toY))
}
}
Any help is appreciated.
As Losiowaty said UIView.animationWithDuration is the way to go. Check out this answer to see how the syntax is: https://stackoverflow.com/a/30992214/5257729

How do I calculate the speed of which a user drags an image?

I have an image that the user can drag to the right and it will spring back when the user releases it. I want to execute some code when a user drags it quickly and releases it. Now I have a very awkward requirement that the user can drag the image, then keep it still for any length of time (for example 5 seconds), then drag it quickly and release it. As long as the image is moving above a certain speed when it is released, it will execute the code. If it falls below the minimum speed, it executes some different code. So that means I can't calculate the length of time between the beginning of the gesture and the end and execute the code depending on the length of time. What can I do? I guess I somehow need to know the speed at which the image is moving in it's last 500 milliseconds before the gesture ends. However I've hit a brick wall figuring out how to do that. Any help would be greatly appreciated.
Can you please include an explanation and possible example code with your answer as that would be a great help.
If you get the start X,Y coordinates of when the image is dragged, and the X,Y coordinates for when the mouse is released, you can use pythagoras' theorm to calculate the distance between the two points: http://en.wikipedia.org/wiki/Pythagorean_theorem
Also, if you start a timer when the mouse is moved (and mouse button is down), and stop it in the mouseup event, you can calculate the speed using the time and distance (speed = distance / time)
edit following comments:
point delayedMousePos;
point previousMousePos;
bool secondDrag = false;
bool isStopped = false;
var timeFirstStopped;
var positionCount = 0;
array previousMousePositions[3];
// timer which monitors mouse position (set to an interval of say, 10ms)
function timerMonitorMousePos_Elapsed() {
point currentMousePos = getMousePos();
if (isStopped == false) {
if (positionCount >= 2) {
array_shift(previousMousePositions); // remove the first element of the array and move everything down to reindex numerical array to start counting from zero
positionCount = 2; // keep positionCount within array bounds
}
previousMousePositions[positionCount] = currentMousePos; // add the new position to the end of the 'stack'
positionCount++;
}
if (currentMousePos == previousMousePos) { // start check for stationary
isStopped = true;
if (timeFirstStopped == null) {
timeFirstStopped = NOW();
} else {
if (NOW() - timeFirstStopped >= 500) { // we have been stopped for at least 500ms (assumes time is counted in milliseconds)
secondDrag = true;
// previousMousePositions[0] = the mouse position 30ms before the mouse stopped
}
}
} else {
isStopped = false;
timeFirstStopped = null;
}
previousMousePos = currentMousePos;
}
I wouldn't use a timer. I would just save the starting date/time along with x,y position when the dragging starts.
When the dragging has ended, save the ending date/time and position. From those information, I can calculate the distance in pixel and duration in milliseconds.
After searching some more on the internet, I finally answered my own question.
I worked out what I needed to do:
My UIPanGestureRecognizer:
- (IBAction)handlePan3:(UIPanGestureRecognizer *)recognizer3
Get the velocity of the users finger moving across the screen:
CGPoint vel = [recognizer velocityInView:self.myView];
Then:
if (vel.x > /*value*/) {
// Your code
}
I was about to give up, but no! I got there in the end. Thanks for everyones help. I've upvoted one or two answers because they were helpful. bobnoble actually gave the suggestion to use velocityInView and I found this other stack overflow question which gave me the info I needed: iOS - Making sense of velocityInView on UIPanGesture

Updating amount of "lifes" that the player has

I'm making this small flash game where a user has to fly and try to dodge stuff... when the user hits an object it has to remove one of his lives that is shown by a feather.
Everything of the game works perfectly however the feathers don't want to update on the frame (they keep showing 3 which is the starting amount of lives).
This function adds the feathers (illustrating the lives of the player).
var levens = 3;
stage.addEventListener(Event.ENTER_FRAME, leeft);
function leeft(evt:Event):void {
for(var i = 0; i < levens; i++)
{
var v:MovieClip = new feather_mc();
addChild(v);
v.x = 50 + i*12;
v.y = 382;
}
}
Following function is a hittest object function that updates the variable "levens"... as soon as the user hits an object
function raak(evt:Event):void {
if(eagle_mc.hitTestPoint(evt.target.x,evt.target.y, true)==true)
{
removeChild(MovieClip(evt.target));
evt.target.removeEventListener(Event.ENTER_FRAME,raak);
levens--;
if(levens==0)
{
gotoAndStop(41);
}
}
}
You are constantly adding new feathers since the "leeft" function is called on each frame. The result is that the feathers are stacked on top of each other, so if you remove one, the other at the same location appears. I suppose you'll want to execute this method once during initialization.

how to stop a rotating movieclip at different angles with other movieclips following, actionscript 3

I have a manometer, this needs to spin from a minimum value to a maximum. right now I have the manometer as a picture and the arrow as a movieclip. I've got it spinning at the right speed, but don't know how to stop it at the lowest/highest pressure.
It's suppose to work like this:
I have two movieclip/buttons; one for simulating more pressure, and one for less.
when the user presses the "more pressure" movieclip/button the pressure begins to rise and the arrow inside the manometer begin to turn.
At the same time as the pressure rises, another movieclip ("stamp") will push uppwards.
then another movieclip/button, "less pressure" simulates pressure drop; when pressed, the same point as the arrow stopped at when pressure rised, will start sinking towards minimum, and the stamp will go down again.
so, when the user presses "more pressure" pressure rises towards maximum, and as soon as the user stop pressing the button, the animation stops (both the stamp and the arrow). And if the user presses "lower pressure", the arrow starts sinking from where it stopped.
heres my code so far: pil1 = manometerarrow, the stamp = stamp, and "less pressure"/"more pressure" = Lpress / mpress
addEventListener (Event.ENTER_FRAME, rotate);
function rotate(event:Event):void
{
pil1.rotation = pil1.rotation+1;
}
ymutlu is on the right track. The mouse down event will only execute once when the mouse is depressed. To make the object rotate continuously while the mouse is depressed you need to increment or decrement the rotation of the object on each frame. I think the following should do the trick:
import flash.events.MouseEvent;
import flash.events.Event;
var rotate = 0;
Hpress.addEventListener(MouseEvent.MOUSE_DOWN, Hpressed);
Hpress.addEventListener(MouseEvent.MOUSE_UP, removeEnterFrame);
Lpress.addEventListener(MouseEvent.MOUSE_DOWN, Lpressed);
Lpress.addEventListener(MouseEvent.MOUSE_UP, removeEnterFrame);
function Hpressed(e:MouseEvent):void
{
rotate = 1;
addEnterFrame();
}
function Lpressed(e:MouseEvent):void
{
rotate = -1;
addEnterFrame();
}
function addEnterFrame():void
{
this.addEventListener(Event.ENTER_FRAME, update);
}
function removeEnterFrame(e:MouseEvent):void
{
this.removeEventListener(Event.ENTER_FRAME, update);
}
function update(e:Event):void
{
pil1.rotation += rotate;
}
hold to varaible that states if max button down or min button down, and check it in enterframe loop. Edited answer on your comment, hope you can sort it out.
addEventListener (Event.ENTER_FRAME, rotate);
function rotate(event:Event):void
{
if(isMaxDown) // true when max button down
pil1.rotation = Math.min(presMax,pil1.rotation+1); // presMax is max value that pressure can go
if(isMinDown) // true when min button down
pil1.rotation = Math.max(presMin,pil1.rotation-1);// presMin is min value that pressure can go
}
// isMaxDown and isMinDown are global values.
Hpress.addEventListener(MouseEvent.MOUSE_DOWN, Hpressed);
Lpress.addEventListener(MouseEvent.MOUSE_DOWN, Lpressed);
Hpress.addEventListener(MouseEvent.MOUSE_UP, H_up);
Lpress.addEventListener(MouseEvent.MOUSE_UP, L_up);
function H_up(e:MouseEvent):void {
isMaxDown=false;
}
function L_up(e:MouseEvent):void {
isMinDown=false;
}
function Hpressed(e:MouseEvent):void {
isMaxDown=true;
}
function Lpressed(e:MouseEvent):void {
isMinDown=true;
}
This code would help you but prob this is not a path to fallow to do somthing like that.

Changing Shape on Button Press Action Script 3.0

Alright, sorry if this is a pretty easy question to get answered, but I looked around through pages and pages on google and couldn't find anything somewhat related. I got a lot of help, but I still can't seem to get this part of my ActionScript working. I have a program, that when running, allows me to paint random color squares on mouse click. I added a button, that is supposed to be able to change the shape being painted from rectangle to circle. I can't seem to get that button to work. This is what my code looks like so far.
var color:Number;
stage.addEventListener(MouseEvent.MOUSE_DOWN, startDrawing);
stage.addEventListener(MouseEvent.MOUSE_UP, stopDrawing);
function startDrawing(e:MouseEvent):void {
stage.addEventListener(MouseEvent.MOUSE_MOVE, makeShapes);
color = Math.random() * 0xFFFFFF;
}
function stopDrawing(e:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, makeShapes);
}
function makeShapes(e:MouseEvent):void {
var rect:Rect = new Rect(10,10,color);
addChild(rect);
rect.x = mouseX;
rect.y = mouseY;
}
shape_btn.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
function mouseDownHandler(event:MouseEvent):void {
}
At the bottom I left it blank, it seems to be the part I'm stuck on. I've tried simply setting the VAR to my "Ellipse" class I had made, which gets it to work, but only that one time when I click the button. It doesn't stay a circle and allow me to paint with the shape. Again I'm sorry, I felt like I was getting pretty close to the solution, and then I hit a wall.
Hard to understand what the difficulty is, but I'll try to address what I understand.
First, the stage mouse down event will capture your button event, so you might as well get rid of it and stick to one mouse event.
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
private function onMouseDown(ev:Event):void
{
if (ev.target==shape_btn)
changeShape();
else if (ev.target==stage)
startDrawing();
}
Or something along those lines.
Second, I don't know what Rect is. Is it a class you have an access to? This is how I'd do it without a special class:
private function makeShape():void
{
switch (shapeType)
{
case "rect":
drawRect();
break;
case "circle":
drawCircle();
break;
}
}
private function drawRect():void
{
var rect:Shape = new Shape();
rect.graphics.beginFill(color);
rect.graphics.drawRect(0, 0, 10, 10);
rect.x = mouseX;
rect.y = mouseY;
addChild(rect);
}
private function drawCircle():void
{
var circle:Shape = new Shape();
circle.graphics.beginFill(0xff0000);
circle.graphics.drawCircle(0, 0, 10);
circle.x = mouseX;
circle.y = mouseY;
addChild(circle);
}
and finally, the changeShape function:
private function changeShape():void
{
shapeType = shapeType=="rect"?"circle":"rect";
}
There are better ways to go about it, but when dealing with two shape types only this is acceptable.
Of course you need to have a var shapeType:String = "rect" somewhere in your code, outside the functions.
I also think the color randomization should be in the mouse move handler rather than the mouse click. Is that on purpose?

Resources