C# Monogame/XNA枪跟踪鼠标,发射子弹问题

C# Monogame/XNA枪跟踪鼠标,发射子弹问题,c#,xna,trigonometry,monogame,C#,Xna,Trigonometry,Monogame,所以我有一个炮塔型枪,有一个基础精灵()和一个单独的轴精灵()。轴在底座后面绘制,并旋转指向鼠标位置。轴的角度存储为\u转塔角度 当我试图正确定位子弹时,我的问题就出现了。有问题的子弹()需要始终从轴的顶端发射,角度正确,当然,方向正确 为了调整子弹的角度,我只需使用\u炮塔角度,方向是新矢量2(-Math.Cos(\u炮塔角度),-Math.Sin(\u炮塔角度))但我无法获得正确的初始位置 我目前的情况如下: int i = _bullets.Count - 1; Bullet b = _b

所以我有一个炮塔型枪,有一个基础精灵()和一个单独的轴精灵()。轴在底座后面绘制,并旋转指向鼠标位置。轴的角度存储为
\u转塔角度

当我试图正确定位子弹时,我的问题就出现了。有问题的子弹()需要始终从轴的顶端发射,角度正确,当然,方向正确

为了调整子弹的角度,我只需使用
\u炮塔角度
,方向是
新矢量2(-Math.Cos(\u炮塔角度),-Math.Sin(\u炮塔角度))但我无法获得正确的初始位置

我目前的情况如下:

int i = _bullets.Count - 1;
Bullet b = _bullets[i];

b.SetAngle(_turretAngle);

float cos = (float)Math.Cos(_turretAngle);
float sin = (float)Math.Sin(_turretAngle);

b.SetDirection(new Vector2(-cos, -sin));

var posX = (Position.X - (Shaft.Width * cos) - (b.Width * cos)) + (Width / 2) - ((b.Width / 2) * cos);
var posY = Position.Y - (Shaft.Height * sin) - (b.Height * sin);

b.SetPosition((int)posX, (int)posY);

b.BulletState = Bullet.State.Active;
子弹非常接近正确的位置,但它不是位于轴上,而是(取决于炮塔的角度)位于炮塔前面5-15像素的任何位置

当前的显示方式:

我希望它看起来如何:

我知道我可能有点吹毛求疵,但我真的很想知道数学是怎么错的


我意识到可能缺少一些信息,因此如果需要添加任何内容,请告诉我。

使用一些代码示例和更具描述性的解释扩展我的注释。
您没有指定角度的单位是度还是弧度,所以我假设您使用的是必须转换的度。下一步是创建旋转和平移矩阵,然后将其应用于bullet对象

我的建议是创建如下扩展类:

public static class TransformEx
{
    // method to convert degree into radians
    public static double ToRadians(this double degree)
    {
        return ( ( degree % 360.0D ) / 180.0D ) * Math.PI;
    }

    // get the rotation matrix
    public static Matrix GetRotationMatrix(this double angle, Vector2 rotationCenter)
    {
        double radians = angle.ToRadians();
        double cos = Math.Cos(radians);
        double sin = Math.Sin(radians);

        return new Matrix
        {
            M11 = cos,
            M12 = sin,
            M21 = -sin,
            M22 = cos,
            M41 = ( rotationCenter.X * ( 1.0 - cos ) ) + ( rotationCenter.Y * sin ),
            M42 = ( rotationCenter.Y * ( 1.0 - cos ) ) - ( rotationCenter.X * sin )
        };
    }

    // get translation matrix
    public static Matrix GetTranslationMatrix(this Vector2 position)
    {
        return new Matrix
        {
            M41 = position.X,
            M42 = position.Y,
            M43 = 0
        };
    }
}
有了这个,你现在可以继续计算并设置你的子弹。请记住,要正确显示项目符号,必须计算X轴上的平移

// spawn the bullet
Bullet b = _bullets[i];

// get size of bullet and turret for further calculations
Vector2 bulletSize = new Vector2(b.Width, b.Height);
Vector2 turretSize = new Vector2(turret.Width, turret.Height);

// move bullet to the same position as turret
b.Position = turret.Position;

// calculate new translation depending on the size difference
double deltaX = (turretSize.X - bulletSize.X) / 2;
Vector2 bulletNewPos = new Vector2(b.Position.X + deltaX, b.Position.Y + turretSize.Height);

// using extension methods get rotation matrix
// this will rotate referencing the middle point of your bullet
Matrix mtxRotation = _turretAngle.GetRotationMatrix(new Vector2(bulletSize.X / 2, bulletSize.Y / 2));

// now you have to create translation matrix
// but remember to calculate position correctly
Matrix mtxTranslation = bulletNewPos.GetTranslationMatrix();

// now all you have to do is to rotate and then translate your bullet
Matrix transformMatrix = mtxTranslation * mtxRotation;
现在,
transformMatrix
包含了您需要的所有必要的转换细节。您可以对SpriteBatch.Begin使用重载方法来使用此转换矩阵

但是如果您仍然想使用
设置位置
设置角度
方法。您可以简单地使用该矩阵提取新位置,并使用以下方法应用该矩阵:

b.SetAngle(_turretAngle);
// M41 >> position.X
// M42 >> position.Y
// M43 >> position.Z
b.SetPosition((int)transformMatrix.M41, (int)transformMatrix.M42);
编辑:
这假设轴值的定义如下:

   Y +
   ^
   |
   |
   |           
-X +------------> X +
   Y-

使用一些代码示例和更具描述性的解释扩展我的注释。
您没有指定角度的单位是度还是弧度,所以我假设您使用的是必须转换的度。下一步是创建旋转和平移矩阵,然后将其应用于bullet对象

我的建议是创建如下扩展类:

public static class TransformEx
{
    // method to convert degree into radians
    public static double ToRadians(this double degree)
    {
        return ( ( degree % 360.0D ) / 180.0D ) * Math.PI;
    }

    // get the rotation matrix
    public static Matrix GetRotationMatrix(this double angle, Vector2 rotationCenter)
    {
        double radians = angle.ToRadians();
        double cos = Math.Cos(radians);
        double sin = Math.Sin(radians);

        return new Matrix
        {
            M11 = cos,
            M12 = sin,
            M21 = -sin,
            M22 = cos,
            M41 = ( rotationCenter.X * ( 1.0 - cos ) ) + ( rotationCenter.Y * sin ),
            M42 = ( rotationCenter.Y * ( 1.0 - cos ) ) - ( rotationCenter.X * sin )
        };
    }

    // get translation matrix
    public static Matrix GetTranslationMatrix(this Vector2 position)
    {
        return new Matrix
        {
            M41 = position.X,
            M42 = position.Y,
            M43 = 0
        };
    }
}
有了这个,你现在可以继续计算并设置你的子弹。请记住,要正确显示项目符号,必须计算X轴上的平移

// spawn the bullet
Bullet b = _bullets[i];

// get size of bullet and turret for further calculations
Vector2 bulletSize = new Vector2(b.Width, b.Height);
Vector2 turretSize = new Vector2(turret.Width, turret.Height);

// move bullet to the same position as turret
b.Position = turret.Position;

// calculate new translation depending on the size difference
double deltaX = (turretSize.X - bulletSize.X) / 2;
Vector2 bulletNewPos = new Vector2(b.Position.X + deltaX, b.Position.Y + turretSize.Height);

// using extension methods get rotation matrix
// this will rotate referencing the middle point of your bullet
Matrix mtxRotation = _turretAngle.GetRotationMatrix(new Vector2(bulletSize.X / 2, bulletSize.Y / 2));

// now you have to create translation matrix
// but remember to calculate position correctly
Matrix mtxTranslation = bulletNewPos.GetTranslationMatrix();

// now all you have to do is to rotate and then translate your bullet
Matrix transformMatrix = mtxTranslation * mtxRotation;
现在,
transformMatrix
包含了您需要的所有必要的转换细节。您可以对SpriteBatch.Begin使用重载方法来使用此转换矩阵

但是如果您仍然想使用
设置位置
设置角度
方法。您可以简单地使用该矩阵提取新位置,并使用以下方法应用该矩阵:

b.SetAngle(_turretAngle);
// M41 >> position.X
// M42 >> position.Y
// M43 >> position.Z
b.SetPosition((int)transformMatrix.M41, (int)transformMatrix.M42);
编辑:
这假设轴值的定义如下:

   Y +
   ^
   |
   |
   |           
-X +------------> X +
   Y-

我建议只在与turet相同的位置生成此子弹,然后应用相同的旋转矩阵,然后应用平移矩阵,该矩阵应在y方向上移动对象,移动方向等于炮塔高度+子弹高度。原因是首先应用旋转矩阵,然后移动对象。它应该与一个像素间距完全对齐。我建议只在与turet相同的位置生成此项目符号,然后应用相同的旋转矩阵,然后应用平移矩阵,该矩阵应在y方向上移动对象,移动方向等于炮塔高度+项目符号高度。原因是首先应用旋转矩阵,然后移动对象。它应该与一个像素间距完全对齐。