4
\$\begingroup\$

I am trying to implement a FLICK gesture for throwing a ball from point A to point B on the iPhone. This is my current plan....

Using touchesBegan and touchesEnd I can find the direction I need to move the ball, and with a small counter, I can impact a certain velocity on the object.

My question is simple...

Is there a better way to do this ?

I am unaware of the physics engine and how I could use it in this scenario. Any good suggestion will help !

\$\endgroup\$
4
  • \$\begingroup\$ Honestly this is the way I was going to recommend doing it as is. I'm pretty sure it's fine to do it that. But you should also do an over time sort of thing, (i.e) the milliseconds it takes to move it over a distance, should be how much force to apply, and the line from began to end is the (obviously) direction. \$\endgroup\$ Dec 25, 2011 at 3:22
  • \$\begingroup\$ Oh. Are you sure ? I thought there was a much easier way to do this.... What about UIPanGestureRecognizer ? \$\endgroup\$
    – Legolas
    Dec 25, 2011 at 11:13
  • \$\begingroup\$ @lurca has a good point about there being the subclass gestures, look into that first. I don't know much about it. \$\endgroup\$ Dec 26, 2011 at 4:26
  • \$\begingroup\$ @Legolas have you implemented this effect, if yes please let me know because i am unsure on how to implement this. \$\endgroup\$ Nov 2, 2012 at 12:48

2 Answers 2

9
\$\begingroup\$

The flick gesture is managed in two separate step: detection and conseguent dynamics.

Flick Check

The first one is the toughest. Basically you have to collect points in time and space when the touch starts as the touch moves. When the touch ends you have to look to what you gathered to see if there were a Flick.

A simple flick check can be done by looking to the last two recorded position. Computing the distance and the time that occurred between the two events one can easely find a velocity vector: if the vector is large enough a flick to that direction may be triggered. Tree or more points can be used to let filter noise.

Not everyone knows that a flick done with a finger moves quadratically versus time (ie accelerates) while a flick with mouse is linear (ie moves roughly with the same velocity): if you are sure that the flick will be done with a finger, you can use the records to compute a quadratic regression coefficients of determination, to see how good the last n records look like a parabola.

Another common problem is the reliability of the quantities reported by the event handler; large distance covered in few milliseconds are suspect: never trust super high flick speed.

This kind of problems are common when the device is busy so some event may be discarded while other old pending events may be posted at the same time.

The check for zero division you certainly do while computing speed, is a good place to check for near-zero division: if this appends you may discard that point and check some previous one that is recorded before.

Flick Dynamics

After checking if the flick happened for real, you should have a velocty vector: a speed and a direction. You may consider to bound that direction to one axis if you see that the speed in the other axis is small compared to the speed on the other axis as well as to "snap" the direction to one of the diagonals if the speed on both the axes are roughly the same.

Once you get the velocity vector the thing start to be fun: you have to simulate what would happen if you would actually impressed a thrust to the object.

If you try to push a bottle on your table you will see that it start to moving by itself when you release it whether it is standing or rolling then gradually slows to a stop.

This happens because of the friction where the slowing depends on the type of friction and the binding reaction, which in turn depends on the weight of the object.

The friction is manifested as a force that opposes motion so in the absence of forces that sustain the movement, the object decelerate following the Newton's second law.

If we call Fk the force due the (kinetic) friction and we assume that the object lies on a non inclined plane we can compute the deceleration due the friction ak:

ak=mu * g

The first line states that the force is proportional by mu to the object weight (that is the object's mass multiplied by the gravitational acceleration: m*g).

The second line is the second Newton's Law for the friction force: the deceleration ak is bounded to the friction force by the object mass.

The third line computes the deceleration using the frist two lines.

All this simply tell us that the deceleration is constant and it will appear realistic if you use the save value for big and small objects.

Apply Flick Dynamics

Once you have the initial velocity vector there are several way to apply the deceleration.

If you have to update yourself the position of the object, you may integrate dinamically the deceleration or use the equation of motion to establish the position when at a given time.

The first one can be used if you want to add variable to the simulation (like wind or variable friction areas or with user interaction); the second one is suitable if you are sure that the motion will not be perturbed.

If you are using a framework that allows transition and easing you can compute the final position and a quadratic easing to simulate constant decelleration.

Euler integration

To simulate the dynamics you have to store the object position, the current velocity,and the last update time (the touch release for the first time).

At each position update you have to compute the elapsed time from the last update (dt), multiply the ak by dt to obtain the velocity loss then substract that loss from the current velocity. Likewise multiplying the updated velocity by dt you will get the displacement to apply to the position to get the new position.

The euler integration works well if the elapsed time between updates is small-enough™. Here you can sum up all the accelerations, beside friction, to take in account other forces if there are.

Law of Motion

The law of motion is described by the initial velocity and the time elapsed taking into account the deceleration. This means that you have to store both the initial velocity and the time the flick start (when the touch is released) but you do not need to update them.

To make the things simple let's consider the velocity as a direction unit vector multiplied by a (positive) velocity value; in this case the aceleration has to be considered negative.

If the initial speed is V pixel/ms and deceleration is -A pixel/ms/ms then every millisecond the velocity loose A pixel/ms until it reaches 0 pixel/ms.

constant deceleration

The red area represents the distance covered in t milliseconds (the integral generalization of the formula space = speed * time).

Knowing V,A, the elapsed time you can compute the distance covered (the red area) using the formula for the trapezoid area:

(V + V - At) / 2 * t = Vt - At^2/2)

you can multiply Δx by the velocity unit direction to get the actual displacement and add it to the initial position to get the position after t ms.

Take into account that V reaches 0 when At = V i.e. after V/A milliseconds; if t > V/A then Δx remains to its final value:

final position V^2/(2A)

Implementation notes

In both cases it would be useful to delegate the position updating to external component. When an object has to "flick" you instatiate an instance of a "position Manager" giving the relevant initial parameters and the moving object reference. At each update you traverse the manager list and let them update their object (and destroy/recycle themself when finished).

Transition + easing

If your framework supports it you can set a quadratic transition by computing the final position, the transition duration and a quadratic easing.

The final position can be computed using the final Δx as explained before; the same for duration.

In summary if P is the initial position, v is the velocity unit vector, V is the velocity value and -A is the deceleration then:

transition summary

If your framework does not support the quadratic easing you can emulate it using a cubic bezier transition with the following control points:

P0 = (0,0); P1 = (0.33,0.66) P2 = (0.66,1) P3= (1,1)

(generally p0 and p3 are implied)

cubic bezier as parabolic easing

You should see the first branch of the parabola.

My favourite parameters

After some test I found some value you may use as starting point to find your own:

Flick treshold: 0.3 - 0.5 pixel/ms (no flick if slower than this)

Flick scaled speed: 60% - 90% of the flick speed; transfer less motion to the object than the final "flick speed" gives better results

Flick cap speed: 1-1.2 pixel/ms; I don't allow flick faster than this but this is very subjective

flick deceleration: 0.004 pixel/ms/ms; loose one pixel/ms 4 times in a second (4 pixel/ms in a second if you prefer)

\$\endgroup\$
3
\$\begingroup\$

The UIGestureRecognizer might be something you can use. There are subclasses for many different gestures.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .