• 15
• 15
• 11
• 9
• 10

# Trouble with 2D ship rotation

This topic is 2814 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hey all,

I'm having trouble rotating my ship in XNA. I want to use the xbox controller's left stick to tell my ship which direction to point in, but I want my ship to smoothly turn in the last direction I moved my thumbstick to. I've almost got it, but the problem is that the ship will only move to the cardinal directions (N, S, E, W) and the 45's between the cardinals (NE, NW, SE, SW). I can't get it to lock on to the directions in between. And there's one or two configurations where the ship decides to move in the opposite direction. There's got to be a better way of doing this. Any advice for me?

Here's the relevant code snippets:

This is where I get the direction I want to turn to from the controller
[source lang = "C#"]      if ((Math.Abs(gamePadState.ThumbSticks.Left.X) > 0.2f) || (Math.Abs(gamePadState.ThumbSticks.Left.Y) > 0.2f))      {        //don't forget the picture is rotated 90 degrees (but in radians)        //90 degrees in radians = 1.5707964f, 270 degrees in radians = 4.712389f        directionDesired = (float)Math.Atan2((double)gamePadState.ThumbSticks.Left.X, (double)gamePadState.ThumbSticks.Left.Y) + 4.71238898f;      }

And this is where I update my ship's direction
[source lang = "C#"]      float diff = new float();      float circle = MathHelper.Pi * 2;      directionDesired = directionDesired % circle;      if (directionDesired != direction)      {        diff = directionDesired - direction;        float alternateDiff = directionDesired - (direction + circle);        if (Math.Abs(alternateDiff) < Math.Abs(diff))          diff = alternateDiff;        if (Math.Abs(diff) > spinRateAngleDamper)        {          if (diff > 0)          {            direction += maxspinrate;          }          else          {            direction -= maxspinrate;          }        }        else        {          if (diff > 0)          {            direction += MathHelper.Lerp(0, 1, diff / spinRateAngleDamper) * maxspinrate;          }          else          {            direction -= (1.0f - MathHelper.Lerp(0, 1, diff / spinRateAngleDamper)) * maxspinrate;          }        }        direction = direction % circle;        if (Math.Abs(directionDesired - direction) < EPSILON)        {          direction = directionDesired;        }      }

And a few declarations so you know what all of these variables mean
[source lang = "C#"]    protected float direction;    protected float directionToSteerTo = 0.0f;    private float directionDesired = 0.0f;    private float spinrate = 0.0f;    private float maxspinrate = 0.034906585f;    private float spinRateAngleDamper = 0.349065f;

I've been dorking around with this particular problem so much that it's destroying my motivation. So if anyone out there can give me some guidance, I can't tell you what that would mean to me.

- Goishin

##### Share on other sites
My tests seem to work fine. The only thing I can think of is that your epsilon value is not enough to catch floating point errors. I used a value of 0.018 for both if (diff > 0.018f) and if (abs(directionDesired - direction) < 0.018f) and it seems to work fine.

Also, your use of the modulus operator seems to be causing some issues for desired angles greater than 2 * PI. For example take a direction of 5.1f with a desired direction of 7.0f. The result of directionDesired % 2 * PI is 0.7 which will cause the ship the turn around and go back where it came.

EDIT: Thought I'd post the modified code snippet that I've got working here. I'm using C++ with my own framework but I can't see why the results would differ:

if (directionDesired != direction){	diff = directionDesired - direction;					if (diff > 0.018f)	{		direction += maxspinrate;	}	else	{		direction -= maxspinrate;	}					if (abs(directionDesired - direction) < 0.018f)	{		direction = directionDesired;	}}

Also is it possible that your trig up there is not working as expected. Is it returning the expected values?

[Edited by - Dom_152 on July 10, 2010 2:38:54 PM]