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