Missile System Math Problem (very few code)
I want a Missile to follow a player with following rules:
- when the player is at the right side relative to the missile, change the rotation to the right at a fixed rate - else change the rotation to the left at the same rate if (missile.Rotation > 0 && missile.Rotation < Math.PI)
{
if (angle > missile.Rotation && angle < missile.Rotation + Math.PI)
{
missile.Rotation += 0.05f;
}
else
{
missile.Rotation -= 0.05f;
}
}
else
{
if (angle < missile.Rotation && angle > missile.Rotation - Math.PI)
{
missile.Rotation -= 0.05f;
}
else
{
missile.Rotation += 0.05f;
}
}
missile.Position += new Vector2((float)(5 * gameTime.ElapsedGameTime.TotalSeconds * Math.Cos(missile.Rotation)), (float)(5 * gameTime.ElapsedGameTime.TotalSeconds * Math.Sin(missile.Rotation)));
With this code, some missiles seem to bug, when I jump with the player, the missiles go into a endless loop which cannot be stopped (they fly in a circle)
the coordinate system is like in XNA (360/0° is at the right, 270° is top...)
an开发者_如何学Goyone can help me?
Using Euler angles is a very inefficient way to do this. It is much easier to use vectors.
Let P be the position of the player and M the position of the missile. You need to calculate two vectors from these: MP and Mr where MP = vector from missile to player and Mr is the vector pointing to the missile's right hand side. Now calculate the dot product between the vectors MP and Mr. The sign of the result tells you which way to turn the missile. If it's positive then turn the missile clockwise, if it's negative then turn the missile anticlockwise.
Why does this work?
The dot product of two vectors A and B can be written as:
Ax.Bx + Ay.By
and also:
|A|.|B|.cos (theta)
where theta is the angle between the two vectors and |x| is the magnitude of vector x. This gives us:
cos (theta) = (Ax.Bx + Ay.By) / (|A|.|B|)
Since we only want to know the sign of the value cos (theta), positive values being angles between +- 90 degrees and negative values being angles between 90 and 270 degrees, we only need to work out the sign of the numerator, the denominator is always positive! Thus the sign of the dot product will tell us which side the target is on.
But, you're thinking, aren't vectors harder to use than angles? Won't I need to do some trig functions to calculate the missile's right vector?
Ideally, you shouldn't be using Euler angles at all for anything. You should be using matrices to store the position and rotation of objects in your world. The missile's right vector is just the top row of the missile's position/orientation matrix (or first column, depends how you set up your system). And matrices are what the rendering hardware uses to draw objects so you're not adding any overhead by using them (in fact, using angles adds overhead as the angle notation needs to be converted to matrices for the rendering).
EDIT: You code should end up looking like this:
if (VectorDotProduct (missile.right, player.pos - missil.pos) > 0)
{
missile.rotate clockwise
}
else
{
missile.rotate anti-clockwise
}
精彩评论