在我的 XNA 游戏中,我可以用 A 和 D 键旋转我的精灵,一切正常。但对于我的问题:
如何计算 X 和 Y 以将精灵移动到精灵倾斜的方向,我有这个:
float x = (float)Math.Cos(MathHelper.ToRadians(getRotation()));
float y = (float)Math.Sin(MathHelper.ToRadians(getRotation()));
但这根本行不通。每次按住 W 键时,我都想将我的精灵移动 +4 像素。
在我的 XNA 游戏中,我可以用 A 和 D 键旋转我的精灵,一切正常。但对于我的问题:
如何计算 X 和 Y 以将精灵移动到精灵倾斜的方向,我有这个:
float x = (float)Math.Cos(MathHelper.ToRadians(getRotation()));
float y = (float)Math.Sin(MathHelper.ToRadians(getRotation()));
但这根本行不通。每次按住 W 键时,我都想将我的精灵移动 +4 像素。
差不多好了:
sprite.x += ( float ) ( Math.Cos( MathHelper.ToRadians( getRotation( ) ) ) * speedX );
sprite.y += ( float ) ( Math.Sin( MathHelper.ToRadians( getRotation( ) ) ) * speedY );
//Define what is forward when rotation is 0.
var forward = new Vector2(1f,0f);
//Create a rotation-matrix that can rotate the forward-vector
var rotater = Matrix.CreateRotationZ(MathHelper.ToRadians(getRotation()));
//rotate and normalize vector (normalizing makes the length = 1)
forward = Vector2.TransformNormal(forward, rotater);
//move in rotated forward direction times 4
Position += forward * 4f;
但我建议使用每秒像素值并乘以 deltatime:
Position += forward * pixelsPerSecond * (float)gameTime.ElapsedGameTime.TotalSeconds;
正如@BlackBear 指出的那样,您必须将旋转乘以您要移动的距离。
当您使用这类东西时,拥有一个封装基础知识的点(或向量)类(加法、缩放、旋转、角度确定等)并根据向量可视化运动会很有帮助。
例如,给定一个功能 Point2D 类:
// define movement vector as +4 units in 'Y' axis
// rotated by player facing
Point2D MoveVector = new Point2D(0, 4).Rotate(Player.FacingAngle);
// adjust player position by movement vector:
Player.Position.Add(MoveVector);
一个更好的想法可能是让玩家包含一个方向向量,只要需要将面对映射到 2D 坐标,就可以使用该方向向量。然后运动变成:
Player.Position.Add(Player.FacingVector * MoveSpeed);
这对于产生子弹之类的事情很方便,因为您可以将它们的初始面向矢量设置为玩家的面向矢量等等,从而节省整个链条的旋转操作。
而且您会获得额外的好处,即您的代码可以进行更多的自我记录:P
编辑 - 一堆代码:
这是我的 Point2D 实现的一部分:
public class Point2D
{
public double X;
public double Y;
public Point2D(double X = 0, double Y = 0)
{
this.X = X;
this.Y = Y;
}
// update this Point2D by adding other
public Point2D AddEquals(Point2D other)
{
X += other.X;
Y += other.Y;
return this;
}
// return a new Point2D that is the sum of this and other
public Point2D Add(Point2D other)
{
return new Point2D(X + other.X, Y + other.Y);
}
public Point2D Multiply(double scalar)
{
return new Point2D(X * scalar, Y * scalar);
}
// rotate by angle (in radians)
public Point2D Rotate(double angle)
{
double c = Math.cos(angle), s = Math.sin(angle);
double rx = X * s - Y * c;
double ry = Y * s + X * c;
return new Point2D(rx, ry);
}
public Point2D RotateDegrees(double angle)
{
return Rotate(angle * Math.PI / 180);
}
public double Distance(Point2D other)
{
double dx = other.X - X, dy = other.Y - Y;
return Math.Sqrt(dx * dx + dy * dy);
}
}
您可以充实其他操作。这些对于这段代码就足够了:
public class Player
{
public Point2D location;
// facing angle in degrees
public double facing;
public void TurnLeft(double degrees)
{
facing = (facing + 360 - degrees) % 360;
}
public void TurnRight(double degrees)
{
facing = (facing + degrees) % 360;
}
public void MoveForward(double distance)
{
// calculate movement vector
Point2D move = new Point2D(0, distance).RotateDegrees(facing);
// add to position
this.location.AddEquals(move);
}
}
命名在某些地方有点笨拙,但它应该给你一个想法。