感谢 Stig-Rune Skansgård 的回复(如果你是丹麦语hi5),我修复了我的旧角度计算并让它在每种情况下都能正常工作。所以我想我会用适合我的解决方案来回答我自己的问题,这样未来访问者可以从中受益。这是一个非常大的 Ship 类的片段 + 一个计算角度的辅助方法:
public static float CalculateAngleFromVectors(Vector3 v1, Vector3 v2) {
float x = 0;
float X = v2.X - v1.X,
Z = v2.Z - v1.Z;
if (Z == 0) {
x = (X < 0 ? 90 : 270);
} else if (X == 0) {
x = (Z < 0 ? 180 : -180);
} else {
float temp = MathHelper.ToDegrees((float)Math.Atan(X / Z));
if (X < 0) {
x = (Z < 0 ? Math.Abs(temp) : 180 - Math.Abs(temp));
} else {
x = (Z < 0 ? 360 - Math.Abs(temp) : Math.Abs(temp) + 180);
}
}
return x;
}
此方法为您提供浮动角度(以度为单位)以旋转您的船(从标准 0 度起点)..
要使用它,只需在您的类中创建一些更新/动画方法,执行如下操作:
float desiredRotation = 0, currentRotation = 0, totalElapsed = 0, timePerFrame = 0.05f;
if (desiredRotation != 0) {
totalElapsed += elapsed;
if (totalElapsed > timePerFrame) {
if (isRotationComplete()) {
rotX += MathHelper.ToRadians(desiredRotation);
currentRotation = desiredRotation = 0;
} else if (desiredRotation > currentRotation) {
currentRotation += shipTurnSpeed;
} else if (desiredRotation < currentRotation) {
currentRotation -= shipTurnSpeed;
}
totalElapsed -= timePerFrame;
}
}
编辑:和完成检查:
private bool isRotationComplete() {
bool b = false;
if (desiredRotation > currentRotation && currentRotation + shipTurnSpeed > desiredRotation) {
b = true;
} else if (desiredRotation < currentRotation && currentRotation - shipTurnSpeed < desiredRotation) {
b = true;
}
return b;
}
本质上,它的作用是始终检查 DesiredRotation 是否大于 0.. 如果是,则意味着玩家已发出旋转命令(或 AI).. 在我的示例中,CurrentRotation 是 ofc 多少自上次给出旋转命令以来已旋转,并在旋转完成后设置为 0。你应该有一个旋转矩阵,它使用不同的变量来显示旋转。我的是这样的:
public float rotX { get; set; }
public float rotY { get; set; }
public Vector3 position { get; set; }
public Matrix Transform {
get {
return (Matrix.Identity *
Matrix.CreateScale(scale) *
Matrix.CreateRotationY(MathHelper.Pi) *
Rotation *
Matrix.CreateTranslation(position));
}
}
public float ShipCurRotation { get { return (rotX + MathHelper.ToRadians(currentRotation)); } }
public Matrix Rotation { get { return (Matrix.CreateRotationY(ShipCurRotation) * Matrix.CreateRotationX(rotY)); } }
rotX 变量在旋转完成时在我的动画中设置,也在 Init 处设置。这是我如何使用我的第一个代码片段为我生成的旋转角度:
public void MoveToPosition(Vector3 pos) {
desiredRotation = (CalculateAngleFromVectors(position, pos) - MathHelper.ToDegrees(rotX));
isMoving = true;
}
..这使得一个平滑的可定制的旋转、变换和移动设置..在一个XZ平面ofc..Y轴是UP并且总是0..
如果您有任何建议或更改或想法以使事情变得更好,请随时对此发表评论。我总是乐于改进。感谢您的回复,并希望这对很多新开发人员有所帮助,我花了很长时间来收集这些东西来自网络..
PS。旋转可以直接应用到 rotX 进行即时旋转,绕过动画和旋转速度。
WithRegards MatriXz