Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I've spent the last three days trying to work out how to rotate a sprite smoothly depending on the velocity.x value of the sprite. I'm using this:

float Proportion = 9.5;
float maxDiff = 200;
float rotation = fmaxf(fminf(playerVelocity.x * Proportion, maxDiff), -maxDiff);
player.rotation = rotation;

The behaviour is what I required but if the velocity changes rapidly then it will look like the sprite will jump to face left or jump to face right.

I'll go into the behaviour in a little more detail:

0 velocity = sprite faces forwards

negative velocity = sprite faces left depending on value.

positive velocity = sprite faces right (higher velocity the more it faces right) same as above.

I've read about using interpolation rather than an absolute angle to rotate it to but I don't know how to implement that.

I have a physics engine available.

There is one other way to get around this: to use += on the rotation angle. The thing is that I would then have to change the equation to produce positive and negative values then to make sure the sprite faces 0 once it reaches 0 velocity again. If I add that in now, it keeps the previous angle even after the velocity has dropped / is dropping.

Any ideas/code snippets would be greatly appreciated.

share|improve this question
add comment

1 Answer

up vote 4 down vote accepted

There are numerous ways of smoothening a rotation. If there is any physical meaning to it, we'll need to know what that is, but if you are merely doing it to make it appear less jerky, it is pretty arbitrary. Note that unless you know what the velocity is going to do in advance, any attempt to smoothen the corresponding rotation will cause it to lag behind to some degree, which may lead to weird oscillatory behaviour. It also prevents you from smoothly setting the rotation to zero simultaneously with the velocity hitting zero.

A simple way would be to make the rotation respond exponentially, i.e. use an angular velocity proportional to the difference between the sprite's current and target rotation.

targetrotation = fmaxf(fminf(playerVelocity.x * Proportion, maxDiff), -maxDiff);
angularvelocity = (targetrotation - player.rotation) * rotationspeed;
player.rotation += angularvelocity * timestep;

Let's say your playerVelocity.x looked like this:

Without exponential smoothening

The plots below indicate an example rotation against time using various values for rotationspeed using this exponential smoothening method.

Fast smootheningMedium smootheningSlow smoothening

You may want to cap the angular velocity to zero under a specified magnitude. The integration method is very crude and given enough time to settle, the timestep will eventually be too large and the rotation will overshoot its target. The resulting oscillation might even consistently increase in amplitude. An example:

Imagine the rotation being very close to its target. As it comes closer, the angular velocity should gradually decrease until it eventually stops. However, the angular velocity isn't constantly updated; it is updated once every timestep. During these steps, the angular velocity should be decreasing, but instead, the rotations keeps changing at a constant rate. Below is what might happen.

Unwanted oscillation

The yellow line indicates the intended behaviour. You can see the blue line (timesteps of 0.1) starts with the right slope, but isn't updated for a while. It's a little high, but doesn't cause any major issues. The red line has more time in between steps (0.2). By the time the slope is updated, the rotation has overshot its target.

There are more elaborate ways of tackling this problem, but you are somewhat handicapped by the fact that the target rotation might be changing too. The simplest way would be to specify a range around the target where the rotation is 'close enough' and should stop moving. How large this range should be depends on your timestep and maximum angular velocity, but I suggest some experimentation.

share|improve this answer
    
Excellent answer, thank you so much, very descriptive. I'll play around with the values and get this working 100%. –  Lewis Jun 23 '12 at 21:13
    
What value would you suggest I cap the angular velocity at? I'm guessing by this you mean wrapping the rotation code in an if statement? The velocity of the sprite ranges from -15 to 15. Rather than using timestep do you think using the accelerometer input work? –  Lewis Jun 24 '12 at 1:12
    
I have added a more detailed section about capping the angular velocity. I'm not quite sure what you mean by using the accelerometer input. The timestep is simply the time between two update routines. You can leave it out, but the behaviour will then depend on your framerate. –  Marcks Thomas Jun 24 '12 at 10:30
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.