精灵旋转XNA

时间:2012-03-02 01:36:08

标签: c# math xna sprite

我正在尝试通过使用转弯半径递增和递减旋转来旋转精灵以面向鼠标。它工作正常,直到鼠标左上角移动到右上角。我有它,如果角度差大于当前的旋转值,精灵的旋转增加,否则它会减少。因此当它从6.5弧度变为0时,它逆时针旋转350度,而不是顺时针旋转15度。我和其他人一整天都在努力,不知道如何解决这个问题。我的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using System.IO;

namespace Physics
{
public class Ship
{
    public Texture2D Texture { get; set; }
    public Vector2 Position { get; set; }
    public double Rotation { get; set; }
    MouseState prevState, currState;

    Vector2 A, B;

    public const double NINETY_DEGREES = 1.57079633;

    double turningRadius = 2 * (Math.PI / 180);
    double targetRotation, rotationDifferential;

    public Ship(Texture2D texture, Vector2 position)
    {
        Texture = texture;
        Position = position;
        A = new Vector2(Position.X, Position.Y);
        B = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
        Rotation = 0;
    }

    public void Update()
    {
        currState = Mouse.GetState();
        A.X = Position.X;
        A.Y = Position.Y;
        B.X = currState.X;
        B.Y = currState.Y;

        if (B.Y > A.Y)
            if (B.X > A.X) //Bottom-right
                targetRotation = Math.Atan((B.Y - A.Y) / (B.X - A.X)) + NINETY_DEGREES;
            else //Bottom-left
                targetRotation = (Math.Atan((A.X - B.X) / (B.Y - A.Y))) + (NINETY_DEGREES * 2);
        else
            if (B.X > A.X) //Top-right
                targetRotation = Math.Atan((B.X - A.X) / (A.Y - B.Y));
            else //Top-Left
                targetRotation = Math.Atan((A.Y - B.Y) / (A.X - B.X)) + (NINETY_DEGREES * 3);

        if (Rotation > targetRotation)
            Rotation -= turningRadius;
        else
            Rotation += turningRadius;

        prevState = currState;
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(Texture, Position, null, Color.White, (float)Rotation, new Vector2(Texture.Width / 2, Texture.Height / 2), 0.5f,
            SpriteEffects.None, 0.0f);
    }
}

}

4 个答案:

答案 0 :(得分:3)

让我确保理解。你有一个向量(Cos(Rotation), Sin(Rotation),表示你的对象面向哪个方向;另一个向量(B.X-A.X, B.Y-A.Y)表示您想要对象的方向;并且您想要知道是否顺时针或逆时针旋转对象(第一个矢量)以面对它 第二个向量的方向?

简单,只需将它们视为3D矢量(设置Z = 0)并取用cross product

  • 如果生成的矢量具有正Z分量,则逆时针旋转
  • 如果它具有正Z成分,则顺时针旋转
  • 如果Z分量为0,则两个矢量是平行的,因此只需检查它们是否面向相反的方向(并以任一方向旋转)或相同的方向(无事可做!)

这是因为right-hand rule定义了交叉产品。

答案 1 :(得分:1)

这应该反转方向,以更快的速度。

spin = targetRotation - Rotation;  
if (abs(spin) > Math.PI) 
  spin *= -1;
if (spin > 0
  Rotation += turningRadius;
else
  Rotation -= turningRadius;

编辑:将180更改为Math.PI

答案 2 :(得分:0)

编辑我的道歉我从我的后方移开了我的头,这次实际上读了这个问题。所以这是一个很好的小方法,我今晚花了大约3个小时写作。

private float AngleLerp(float nowrap, float wraps, float lerp) {

    float c, d;

    if (wraps < nowrap) {
        c = wraps + MathHelper.TwoPi;
        //c > nowrap > wraps
        d = c - nowrap > nowrap - wraps
            ? MathHelper.Lerp(nowrap, wraps, lerp)
            : MathHelper.Lerp(nowrap, c, lerp);

    } else if (wraps > nowrap) {
        c = wraps - MathHelper.TwoPi;
        //wraps > nowrap > c
        d = wraps - nowrap > nowrap - c
            ? MathHelper.Lerp(nowrap, c, lerp)
            : MathHelper.Lerp(nowrap, wraps, lerp);

    } else { return nowrap; } //Same angle already

    return MathHelper.WrapAngle(d);
}

它将nowrapwraps值移动。 wraps角度可以是从0跳到TwoPi并返回的角度,因此在这种情况下是鼠标的角度。 nowrap应该是你的对象角度。

希望这次我真的很有帮助。

答案 3 :(得分:0)

尝试以下(这是我制作的坦克游戏中的一些代码,不确定它是否仍适用于此场景)。我把它修剪成了必需品:

using System;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace Physics
{
    public class Ship
    {
        public Texture2D Texture { get; set; }
        public Vector2 Position { get; set; }
        public double Rotation { get; set; }
        private MouseState currState;

        public Ship(Texture2D texture, Vector2 position)
        {
            Texture = texture;
            Position = position;
            Rotation = 0;
        }

        public void Update()
        {
            currState = Mouse.GetState();

            var mouseloc = new Vector2(currState.X, currState.Y);
            Vector2 direction = Position - mouseloc;
            Rotation = Math.Atan2(direction.Y, direction.X) + MathHelper.PiOver2;
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(Texture, Position, null, Color.White, (float) Rotation,
                             new Vector2(Texture.Width/2, Texture.Height/2), 0.5f,
                             SpriteEffects.None, 0.0f);
        }
    }
}

我认为你只需要更多的数学来修改旋转速度,如果我想出一个解决方案,我会回来的。 此外,此代码将根据精灵的默认旋转而有所不同。在我的例子中,它假定精灵面朝下(6点钟)。希望这能指出你正确的方向!