Trying to think about simulating momentum / inertia using the UIRotationGestureController

Okay, so I'm trying to create a Wheel of Fortune effect with a wheel shape in iOS, where I can grab and rotate the wheel. Currently, I can pull and turn the wheel to my heart contents, but when I release my finger, it stops working. I need to apply some impulse or inertia to it to simulate a wheel spinning naturally.

I have a speed calculation in place, so when I lift my finger up, I NSLog go out of speed (between a minimum of 1 and a maximum of 100), which ranges from somewhere between 1 and more than 1800 (at my hardest click!), now I'm just trying to establish how I'm going to convert this speed to actual rotation to apply to an object, and how I will slow it down over time.

My initial thoughts were something like: start spinning full circles on a loop at the same speed as a given speed, and then at each subsequent rotation slow down the speed by a small percentage. This should result in a harder rotation to accelerate and take longer to slow down.

I am not a mathematician, so my approach may be wrong, but if anyone has any advice on how I can get this to work, at least in a basic state, I would be very grateful. There is a really useful answer here: iPhone adds inertia / momentum physics for animating the โ€œwheel of luckโ€ as a spinning control , but it is more theoretical and does not contain practical information on how to accurately apply the calculated speed to an object, etc. I think I will need animation support too.

EDIT: I will also need to figure out if they drag the wheel clockwise or counterclockwise.

Thank you very much!

+4
source share
2 answers

I wrote something similar for my Beat program, but my case, I think, is a bit more complicated, because I rotate in 3D: https://itunes.apple.com/ua/app/bit/id366236469?mt=8

Basically, I create NSTimer, which calls some method regularly. I just take the direction and speed to create a rotation matrix (as I said, 3D is a little nastier: P), and I multiply the speed with some number less than 1, so it drops. The reason for multiplying instead of subtracting is because you donโ€™t want the object to rotate twice as long if the rotation from the user is twice as large, as it becomes annoying to wait for me to find.

To find out in which direction the wheel is spinning, just save it in the toucedEnded: withEvent: methods where you have all the information. Since you are saying that you already have tracking while the user has a thumbs down, this should be obvious.

What I have in 3D is something like:

 // MyView.h @interface MyView : UIView { NSTimer *animationTimer; } - (void) startAnimation; @end // MyAppDelegate.h @implementation MyAppDelegate - (void) applicationDidFinishLaunching:(UIApplication *)application { [myView startAnimation]; } @end // MyView.m GLfloat rotationMomentum = 0; GLfloat rotationDeltaX = 0.0f; GLfloat rotationDeltaY = 0.0f; @implementation MyView - (void)startAnimation { animationTimer = [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)((1.0 / 60.0) * animationFrameInterval) target:self selector:@selector(drawView:) userInfo:nil repeats:TRUE]; } - (void) drawView:(id)sender { addRotationByDegree(rotationMomentum); rotationMomentum /= 1.05; if (rotationMomentum < 0.1) rotationMomentum = 0.1; // never stop rotating completely [renderer render]; } - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { } - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { UITouch *aTouch = [touches anyObject]; CGPoint loc = [aTouch locationInView:self]; CGPoint prevloc = [aTouch previousLocationInView:self]; rotationDeltaX = loc.x - prevloc.x; rotationDeltaY = loc.y - prevloc.y; GLfloat distance = sqrt(rotationDeltaX*rotationDeltaX+rotationDeltaY*rotationDeltaY)/4; rotationMomentum = distance; addRotationByDegree(distance); self->moved = TRUE; } - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { } - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { } 

I did not take into account the addRotationByDegree function, but it uses the rotationDeltaX and rotationDeltaY global variables and applies the rotation matrix to the already saved matrix, and then saves the result. In your example, you probably want something much simpler, for example (I assume that only movements in the X direction rotate the wheel):

 - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { UITouch *aTouch = [touches anyObject]; CGPoint loc = [aTouch locationInView:self]; CGPoint prevloc = [aTouch previousLocationInView:self]; GLfloat distance = loc.x - prevloc.x; rotationMomentum = distance; addRotationByDegree(distance); self->moved = TRUE; } void addRotationByDegree(distance) { angleOfWheel += distance; // probably need to divide the number with something reasonable here to have the spin be nicer } 
+1
source

This will be a rude answer since I do not have a detailed example.

If you have speed when you lift your finger, then it should not be hard. The speed you have pixels per second or something like that. First you need to convert this linear speed to angular speed. This can be done by knowing the perimeter of the circle 2*PI*radius , and then 2*PI/perimeter*velocity to get the angular velocity in radians per second.

If your wheel did not have any friction on its axis, it will work forever at that speed. Well, you can simply adjust the value of this friction, which is the acceleration and can be represented in pixels per second squared or radian per second squared to accelerate angular. Then itโ€™s just a matter of dividing the angular speed by this angular acceleration, and you get the time before it stops.

Over time, you can use the equation finalAngle = initialAngle + angularSpeed*animationTime - angularAcceleration/2*animationTime*animationTime to get the final angle that your wheel will be at the end of the animation. Then just do the animation while transforming and rotate it this angle for the time you got and say that your animation should weaken.

It should look realistic enough. If not, you need to specify an animation path for the rotation property of your wheel based on some selections from the equation above.

+1
source

All Articles