C# 如何使纹理旋转以面对矢量2?

C# 如何使纹理旋转以面对矢量2?,c#,rotation,xna,C#,Rotation,Xna,我正在用C#xna4.0做一个游戏,我希望游戏中有旋转的枪面对玩家并向他们射击。我在下面附上了一张图片来总结这一点 我已经实现了射击AI,但我想知道如何使枪旋转,使其面向玩家。player类使用Vector2表示其位置,gun类使用float值表示其旋转,那么如何使gun旋转以指向向量?(我很确定我知道如何画旋转的枪,我只需要知道如何改变枪的旋转。) 编辑: 这是我的枪课。构造器需要一个位置(它将被放置在关卡中的位置)、一个射速(它每秒大约发射多少次)和一个子弹速度(子弹移动的速度)。有一个单

我正在用C#xna4.0做一个游戏,我希望游戏中有旋转的枪面对玩家并向他们射击。我在下面附上了一张图片来总结这一点

我已经实现了射击AI,但我想知道如何使枪旋转,使其面向玩家。player类使用Vector2表示其位置,gun类使用float值表示其旋转,那么如何使gun旋转以指向向量?(我很确定我知道如何画旋转的枪,我只需要知道如何改变枪的旋转。)

编辑:

这是我的枪课。构造器需要一个位置(它将被放置在关卡中的位置)、一个射速(它每秒大约发射多少次)和一个子弹速度(子弹移动的速度)。有一个单独的子弹类,但这不应该是解释枪类的必要条件

Vector2 m_position;
decimal m_fireRate;
decimal timer;
double m_bulletSpeed;
double rotation;
List<Bullet> bullets;

public Gun(Vector2 position, decimal fireRate, double bulletSpeed)
{
    m_position = position;
    m_fireRate = fireRate;
    timer = 0.0m;
    m_bulletSpeed = bulletSpeed;
    bullets = new List<Bullet>();
    rotation = 0.0;
}

public void Update()
{
    timer += 0.025m;

    if (timer % m_fireRate == 0)
    {
        //Create a new bullet based on the rate of fire (Obtain the gun texture from the main game class)
        bullets.Add(new Bullet(m_bulletSpeed, rotation, new Vector2(m_position.X + (MyGame.GunTex.Width / 3), m_position.Y + MyGame.GunTex.Height)));
    }

    foreach (Bullet bullet in bullets.ToList())
    {
        bullet.Update();

        //Delete the bullet if it is offscreen
        if (bullet.Position.X >= MyGame.WindowWidth || bullet.Position.X <= 0 || bullet.Position.Y >= MyGame.WindowHeight)
        {
            bullets.Remove(bullet);
        }
    }

    //ROTATE TO FOLLOW PLAYER POSITION
}

public void Draw(SpriteBatch spriteBatch)
{
    spriteBatch.Draw(MyGame.GunTex, m_position, Color.White);

    foreach(Bullet bullet in bullets)
    {
        bullet.Draw(spriteBatch);
    }
}
vector2mu位置;
十进位火灾率;
十进制定时器;
速度加倍;
双旋转;
列出项目符号;
公共火炮(矢量2位置,十进制射速,双子弹速度)
{
m_位置=位置;
m_fireRate=燃速;
计时器=0.0m;
m_bulletSpeed=bulletSpeed;
项目符号=新列表();
旋转=0.0;
}
公共无效更新()
{
定时器+=0.025m;
如果(计时器%m_fireRate==0)
{
//根据射速创建一个新子弹(从主游戏类获得枪纹理)
添加(新项目符号(m_Bullet速度、旋转、新矢量2(m_位置.X+(MyGame.GunTex.Width/3)、m_位置.Y+MyGame.GunTex.Height));
}
foreach(子弹中的子弹。ToList())
{
bullet.Update();
//删除屏幕外的项目符号
if(bullet.Position.X>=MyGame.WindowWidth | | bullet.Position.X=MyGame.WindowHeight)
{
子弹。移除(子弹);
}
}
//旋转以跟随玩家的位置
}
公共作废抽签(SpriteBatch SpriteBatch)
{
spriteBatch.Draw(MyGame.GunTex,m_位置,颜色.白色);
foreach(子弹中的子弹)
{
子弹。抽签(spriteBatch);
}
}

如果您只需要炮塔旋转中心之间的角度,它由(in)给出:

如果要将转台的旋转限制在某个最大角速度,可以执行以下操作:

    const double maxAngularVelocity = Math.PI / 18.0; // 10 degrees per second.  Or whatever, your choice

    void UpdateRotation(Vector2 playerPos, decimal timeStep)
    {
        UpdateRotation(playerPos, timeStep, maxAngularVelocity);
    }

    void UpdateRotation(Vector2 playerPos, decimal timeStep, double maxAngularVelocity)
    {
        var diffVec = playerPos - m_position;
        var angle = (float)Math.Atan2(diffVec.Y, diffVec.X);

        float newRotation;

        // To make the gun point at the player:
        newRotation = MathHelper.WrapAngle(angle); // Adjust to between -PI and PI.  Actually Atan2() returns in this range anyway.

        // To make rotate towards the player with a maximum angular rotation, using the smallest direction
        var timeStepf = (float)timeStep;
        var diffAng = MathHelper.WrapAngle(newRotation - (float)rotation); // Adjust difference to between -PI and PI.
        diffAng = timeStepf * MathHelper.Clamp(diffAng / timeStepf, (float)-maxAngularVelocity, (float)maxAngularVelocity); // Clamp the difference by the maximum angular velocity.
        newRotation = MathHelper.WrapAngle((float)rotation + diffAng); // Adjust to between -PI and PI.

        rotation = newRotation;
    }
注意,在这个方案中,如果玩家大致在炮手后面,并且在炮手后面180度到180度之间来回舞动,那么炮手可以在两个方向之间振动。你可以通过记住之前的旋转速度来解决这个问题,如果玩家靠近枪后180度,继续朝这个方向移动

另一种可能性是

  • 定义炮手的反应时间(比如说0.25秒)
  • 让炮手瞄准玩家0.25秒前的位置,并根据当时(0.25秒前)到玩家的距离和玩家当时的速度(可能被炮塔的最大角速度钳制),线性推断子弹到达时玩家的位置
  • 为了使比赛更容易或更难,在枪手的距离估计中引入更大或更小的误差

也许是一个起点:你能发布你的
课程吗?是的。gun类已经发布。@MickyDuncan-OP正在执行
子弹。ToList()
,因为他正在执行
子弹。在循环中移除(子弹)
。所以OP需要为(var i=bullets.Count-1;i>=0;i--)执行类似于
的操作,然后再执行
bullets.RemoveAt(i)@dbc啊,好地方,坏地方。干杯。工作很有魅力。:)
    const double maxAngularVelocity = Math.PI / 18.0; // 10 degrees per second.  Or whatever, your choice

    void UpdateRotation(Vector2 playerPos, decimal timeStep)
    {
        UpdateRotation(playerPos, timeStep, maxAngularVelocity);
    }

    void UpdateRotation(Vector2 playerPos, decimal timeStep, double maxAngularVelocity)
    {
        var diffVec = playerPos - m_position;
        var angle = (float)Math.Atan2(diffVec.Y, diffVec.X);

        float newRotation;

        // To make the gun point at the player:
        newRotation = MathHelper.WrapAngle(angle); // Adjust to between -PI and PI.  Actually Atan2() returns in this range anyway.

        // To make rotate towards the player with a maximum angular rotation, using the smallest direction
        var timeStepf = (float)timeStep;
        var diffAng = MathHelper.WrapAngle(newRotation - (float)rotation); // Adjust difference to between -PI and PI.
        diffAng = timeStepf * MathHelper.Clamp(diffAng / timeStepf, (float)-maxAngularVelocity, (float)maxAngularVelocity); // Clamp the difference by the maximum angular velocity.
        newRotation = MathHelper.WrapAngle((float)rotation + diffAng); // Adjust to between -PI and PI.

        rotation = newRotation;
    }