Monogame/XNA 枪跟随鼠标,发射子弹问题
Monogame/XNA Gun following mouse, firing bullet issue
所以我有一把炮塔式枪,有一个基础精灵 () and a separate sprite for the shaft ()。轴在底座后面绘制,并旋转以指向鼠标位置。轴的角度存储为 _turretAngle
.
当我尝试正确定位子弹时,我的问题就出现了。有问题的子弹 () 需要始终从轴的尖端发射,角度正确,当然,方向正确。
为了调整子弹的角度,我直接用了_turretAngle
,方向是new Vector2(-Math.Cos(_turretAngle), -Math.Sin(_turretAngle));
,但是我无法得到正确的初始位置。
我目前的情况如下:
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 像素的任何位置。
目前的显示方式:
我希望它如何显示:
我知道我在这里可能有点挑剔,但我真的很想知道数学是怎么错的。
我知道可能缺少一些信息,所以如果我需要添加任何内容,请告诉我。
用一些代码示例和更具描述性的解释来扩展我的评论。
您没有指定您的角度是度数还是弧度,所以我假设您使用的是必须转换的度数。接下来是创建旋转和平移矩阵,然后将其应用于项目符号对象。
我的建议是像这样创建一个扩展 class :
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
的重载方法来使用此转换矩阵。
但是如果您仍然想使用您的 SetPosition
和 SetAngle
方法。您可以简单地使用此矩阵来提取新位置并使用 :
应用它
b.SetAngle(_turretAngle);
// M41 >> position.X
// M42 >> position.Y
// M43 >> position.Z
b.SetPosition((int)transformMatrix.M41, (int)transformMatrix.M42);
编辑:
这假设您的轴值定义如下:
Y +
^
|
|
|
-X +------------> X +
Y-
所以我有一把炮塔式枪,有一个基础精灵 (_turretAngle
.
当我尝试正确定位子弹时,我的问题就出现了。有问题的子弹 (
为了调整子弹的角度,我直接用了_turretAngle
,方向是new Vector2(-Math.Cos(_turretAngle), -Math.Sin(_turretAngle));
,但是我无法得到正确的初始位置。
我目前的情况如下:
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 像素的任何位置。
目前的显示方式:
我希望它如何显示:
我知道我在这里可能有点挑剔,但我真的很想知道数学是怎么错的。
我知道可能缺少一些信息,所以如果我需要添加任何内容,请告诉我。
用一些代码示例和更具描述性的解释来扩展我的评论。
您没有指定您的角度是度数还是弧度,所以我假设您使用的是必须转换的度数。接下来是创建旋转和平移矩阵,然后将其应用于项目符号对象。
我的建议是像这样创建一个扩展 class :
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
的重载方法来使用此转换矩阵。
但是如果您仍然想使用您的 SetPosition
和 SetAngle
方法。您可以简单地使用此矩阵来提取新位置并使用 :
b.SetAngle(_turretAngle);
// M41 >> position.X
// M42 >> position.Y
// M43 >> position.Z
b.SetPosition((int)transformMatrix.M41, (int)transformMatrix.M42);
编辑:
这假设您的轴值定义如下:
Y +
^
|
|
|
-X +------------> X +
Y-