C# 设置物体旋转到面坐标
C# Set Rotation of Object to Face Coordinates
我正在使用 C# 在自定义引擎中制作游戏。 (不是 Unity)
我有一个大网格和两个对象的 x/y 坐标。 Player 对象和 Destination 对象。以及玩家当前的旋转度数 (0-360)。
我已经变得过于依赖现有的游戏引擎,并且不知道如何找到我需要让玩家面对目标的旋转。
playerRotation;//0 to 360 degrees.
playerX double = 47.43;
playerY double = 43.36;
targetX double = 52.15;
targetY double = 38.67;
我目前的方法是尝试通过以下方式获取对象之间的距离:
float distanceX = Math.Abs(playerX - destinationX);
float distanceY = Math.Abs(playerY - destinationY);
这似乎工作正常。然后我需要旋转玩家面对目的地并让他们朝目的地移动,直到 distanceX/Y <= 0.
编辑:我一直在和 Atan2 打交道,试图找到答案。
Vector2 playerCoords = new Vector2(playerX, playerY);
Vector2 targetCoords = new Vector2(targetX, targetY);
double theta = Math.Atan2((targetCoords.yValue - playerCoords.yValue), (targetCoords.xValue - playerCoords.xValue));
theta = theta * (180 / Math.PI);//Convert theta to degrees.
double sigma = playerRotation;//Direction in degrees the player is currently facing.
double omega = sigma - theta;
OutputLog("omega: " + omega);
我的输出日志应该显示我的玩家需要面向目标的度数。但它给了我错误的结果。
玩家:(4782, 4172) 和
目标:(4749, 4157)
角度应该是286左右~。
但是 Theta = -155 和 omega = 229。
矢量数学很有用,而且没那么复杂。
第一个向量是你的玩家位置和目的地:
Vector2 playerPos = new Vector2(playerX, playerY);
Vector2 destinationPos = new Vector2(destinationX, destinationY);
现在你可以只减去两个向量,得到一个从一个位置指向另一个位置的向量。
Vector2 delta = destination - playerPos; // Note, it might be the other way around: playerPos - destination
那个增量向量有一个长度,那就是两点之间的距离。 Vector class 上通常有一个 Length 和一个 LengthSquared 属性。但是请注意,计算长度相当 CPU 密集,因为它使用平方根。如果您想将该距离与固定距离(如 200)进行比较,只需使用长度的平方并将其与更快的方式 (200 * 200) 进行比较。
您也可以使用该增量,让子弹从一个位置飞到另一个位置。你只需要规范化增量,有一种方法,你可以将它缩小到长度一。您现在可以使用该增量乘以每个物理循环的速度来更改子弹位置。
现在要获取角度,您可以使用:
双角 = Math.Atan2 (delta.Y, delta.X); // 注意这里y和x是颠倒的,应该是这样的。
请注意,这个角度的单位是弧度,而不是度数。弧度圆从 -PI 开始,到 PI 结束。因此,一个完整的圆是 2 * PI。把弧度换算成度数,可以看this question
编辑
我一直假设12点是0度,3点是90度,6点是180度,9点是270度。
但实际上在笛卡尔坐标系中情况有点不同。我也在下面的代码中做出了这个错误的假设。
但事实证明我错了。看这张照片
现在,如果您查看我的源代码,我所有的变量都被错误地命名了。但是,如果您查看它们的值,您会发现它们与图片相符。因此,Atan2 修正是它应该的样子。
// 使用来自 System.Numerics;
的 Vector2
internal static double RadianToDegree(double rad)
{
double thetaDegree = rad * (180.0 / Math.PI);
// Convert negative angles into positive ones
//
double thetaDegree2 = (thetaDegree + 360) % 360;
return thetaDegree2;
}
internal void Run()
{
// Player: (4782, 4172) and Target: (4749, 4157)
Vector2 player = new Vector2(4782, 4172);
Vector2 target = new Vector2(4749, 4157);
Vector2 delta = target - player;
double theta = Math.Atan2(delta.Y, delta.X);
double thetaDegree = RadianToDegree(theta);
// Given cartesian coordinate system
// positive y is up, negative is down
// positive x is right, negative is left
// Falsely assuming up is 0
// Falsely assuming right is 90
// Falsely assuming down is 180
// Falsely assuming left is 270
Vector2 v0 = new Vector2(0, 1);
Vector2 v45 = new Vector2(0.5f, 0.5f);
Vector2 v90 = new Vector2(0.5f, 0);
Vector2 v180 = new Vector2(0, -1);
Vector2 v270 = new Vector2(-1, 0);
double theta0 = Math.Atan2(v0.Y, v0.X);
double theta45 = Math.Atan2(v45.Y, v45.X);
double theta90 = Math.Atan2(v90.Y, v90.X);
double theta180 = Math.Atan2(v180.Y, v180.X);
double theta270 = Math.Atan2(v270.Y, v270.X);
double result0 = RadianToDegree(theta0);
double result45 = RadianToDegree(theta45);
double resultv90 = RadianToDegree(theta90);
double resultv180 = RadianToDegree(theta180);
double resultv270 = RadianToDegree(theta270);
// result 0 --> 90
// result 45 --> 45
// result 90 --> 0
// result 180 --> 270
// result 270 --> 180
}
我正在使用 C# 在自定义引擎中制作游戏。 (不是 Unity)
我有一个大网格和两个对象的 x/y 坐标。 Player 对象和 Destination 对象。以及玩家当前的旋转度数 (0-360)。
我已经变得过于依赖现有的游戏引擎,并且不知道如何找到我需要让玩家面对目标的旋转。
playerRotation;//0 to 360 degrees.
playerX double = 47.43;
playerY double = 43.36;
targetX double = 52.15;
targetY double = 38.67;
我目前的方法是尝试通过以下方式获取对象之间的距离:
float distanceX = Math.Abs(playerX - destinationX);
float distanceY = Math.Abs(playerY - destinationY);
这似乎工作正常。然后我需要旋转玩家面对目的地并让他们朝目的地移动,直到 distanceX/Y <= 0.
编辑:我一直在和 Atan2 打交道,试图找到答案。
Vector2 playerCoords = new Vector2(playerX, playerY);
Vector2 targetCoords = new Vector2(targetX, targetY);
double theta = Math.Atan2((targetCoords.yValue - playerCoords.yValue), (targetCoords.xValue - playerCoords.xValue));
theta = theta * (180 / Math.PI);//Convert theta to degrees.
double sigma = playerRotation;//Direction in degrees the player is currently facing.
double omega = sigma - theta;
OutputLog("omega: " + omega);
我的输出日志应该显示我的玩家需要面向目标的度数。但它给了我错误的结果。
玩家:(4782, 4172) 和 目标:(4749, 4157)
角度应该是286左右~。
但是 Theta = -155 和 omega = 229。
矢量数学很有用,而且没那么复杂。
第一个向量是你的玩家位置和目的地:
Vector2 playerPos = new Vector2(playerX, playerY);
Vector2 destinationPos = new Vector2(destinationX, destinationY);
现在你可以只减去两个向量,得到一个从一个位置指向另一个位置的向量。
Vector2 delta = destination - playerPos; // Note, it might be the other way around: playerPos - destination
那个增量向量有一个长度,那就是两点之间的距离。 Vector class 上通常有一个 Length 和一个 LengthSquared 属性。但是请注意,计算长度相当 CPU 密集,因为它使用平方根。如果您想将该距离与固定距离(如 200)进行比较,只需使用长度的平方并将其与更快的方式 (200 * 200) 进行比较。
您也可以使用该增量,让子弹从一个位置飞到另一个位置。你只需要规范化增量,有一种方法,你可以将它缩小到长度一。您现在可以使用该增量乘以每个物理循环的速度来更改子弹位置。
现在要获取角度,您可以使用: 双角 = Math.Atan2 (delta.Y, delta.X); // 注意这里y和x是颠倒的,应该是这样的。
请注意,这个角度的单位是弧度,而不是度数。弧度圆从 -PI 开始,到 PI 结束。因此,一个完整的圆是 2 * PI。把弧度换算成度数,可以看this question
编辑
我一直假设12点是0度,3点是90度,6点是180度,9点是270度。
但实际上在笛卡尔坐标系中情况有点不同。我也在下面的代码中做出了这个错误的假设。
但事实证明我错了。看这张照片
现在,如果您查看我的源代码,我所有的变量都被错误地命名了。但是,如果您查看它们的值,您会发现它们与图片相符。因此,Atan2 修正是它应该的样子。 // 使用来自 System.Numerics;
的 Vector2internal static double RadianToDegree(double rad)
{
double thetaDegree = rad * (180.0 / Math.PI);
// Convert negative angles into positive ones
//
double thetaDegree2 = (thetaDegree + 360) % 360;
return thetaDegree2;
}
internal void Run()
{
// Player: (4782, 4172) and Target: (4749, 4157)
Vector2 player = new Vector2(4782, 4172);
Vector2 target = new Vector2(4749, 4157);
Vector2 delta = target - player;
double theta = Math.Atan2(delta.Y, delta.X);
double thetaDegree = RadianToDegree(theta);
// Given cartesian coordinate system
// positive y is up, negative is down
// positive x is right, negative is left
// Falsely assuming up is 0
// Falsely assuming right is 90
// Falsely assuming down is 180
// Falsely assuming left is 270
Vector2 v0 = new Vector2(0, 1);
Vector2 v45 = new Vector2(0.5f, 0.5f);
Vector2 v90 = new Vector2(0.5f, 0);
Vector2 v180 = new Vector2(0, -1);
Vector2 v270 = new Vector2(-1, 0);
double theta0 = Math.Atan2(v0.Y, v0.X);
double theta45 = Math.Atan2(v45.Y, v45.X);
double theta90 = Math.Atan2(v90.Y, v90.X);
double theta180 = Math.Atan2(v180.Y, v180.X);
double theta270 = Math.Atan2(v270.Y, v270.X);
double result0 = RadianToDegree(theta0);
double result45 = RadianToDegree(theta45);
double resultv90 = RadianToDegree(theta90);
double resultv180 = RadianToDegree(theta180);
double resultv270 = RadianToDegree(theta270);
// result 0 --> 90
// result 45 --> 45
// result 90 --> 0
// result 180 --> 270
// result 270 --> 180
}