1
\$\begingroup\$

Basically I am working on following application of android version Party Games: Drinking Wheel

For this I want to rotate wheel and want to stop wheel at specific point. But I want this with gradually decreasing speed. For example at start I have speed of 10 then at stop time it at 0. So wheel stop smoothly.

At presently I have working code but it stop suddenly.

registerEntityModifier(new RotationModifier(desireTime, 359f,
            desireRotation, new IEntityModifierListener() {

                @Override
                public void onModifierStarted(IModifier<IEntity> pModifier,
                        IEntity pItem) {
                }

                @Override
                public void onModifierFinished(
                        IModifier<IEntity> pModifier, IEntity pItem) {

                    mPointer.stopRotation();
                    showWindowAfterSomeTime(randomSegment);
                }
            }, EaseLinear.getInstance()));

I want some help in this. Thanks for your time.

\$\endgroup\$
1

1 Answer 1

1
\$\begingroup\$

Instead of mPointer.stopRotation() you need to gradually apply negative acceleration (torque) to get to your desired point.

So, you have currentPoint, targetPoint and currentSpeed (I will measure all of them in grades as I guess that's also how you do it - for currentSpeed grades/second).

The distance in grades that the wheel must travel from currentPoint to targetPoint is

distance = targetPoint - currentPoint + r * 360f

Notice that if you don't want the wheel to do any spins before it reaches targetPoint, then r = 0;

And the deceleration needed in order to stop it at targetPoint is

deceleration = -( currentSpeed * currentVelocity / distance ) / 2.f

or

deceleration = -( currentSpeed * currentVelocity  /
                ( targetPoint - currentPoint + r * 360f ) ) / 2.f

and the time along which the wheel stops is

time = currentSpeed / ( -deceleration )

If you don't want the wheel to do a complete spin, then r = 0 and that's all you need to know, just apply the deceleration and it will stop until reaching the point, but at a high currentSpeed it will stop really fast. So, you might want to have a non-null r. Even if you choose to have r = 0, read further below to the Update part.

In order to choose a good r, we need to consider which range should time fall into. I think a good pick is the biggest value lower than 10. So now, we do the following:

float_type time = 0;
float_type r = -1;

LOOP ( as long as time < 10  )
{
    r = r + 1;
    deceleration = -( currentSpeed * currentVelocity  /
                    ( targetPoint - currentPoint + r * 360f ) ) / 2.f
    time = currentSpeed / ( -deceleration );
}

// at very low speeds it will take more than 10 seconds to get to
// targetPoint so r = 0, but we have to wait more than 10 seconds
if ( r > 0 ) 
    r = r - 1;
deceleration = -( currentSpeed * currentVelocity  /
                ( targetPoint - currentPoint + r * 360f ) ) / 2.f
time = currentSpeed / ( -deceleration );

Now when updating the wheel, make sure you do it like that:

// suppose after last update call diff seconds have passed
float_type t = currentSpeed / ( -deceleration );
if ( t < diff ) // in this timestep we reach our target and stop right on it
{
    currentPos = currentPos + t * currentSpeed / 2;
    currentSpeed = 0;
}
else
{
    currentSpeed = currentSpeed + deceleration * diff; // deceleration is negative and (+) * (-) = (-)
    currentPos = currentPos + ( currentSpeed + currentSpeed - deceleration * diff ) * diff / 2.f;
}

Sorry for not posting in your coding language, but I hope you can understand it.

\$\endgroup\$

You must log in to answer this question.

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