【问题标题】:What's wrong with my function to update position of planet near a star?我更新恒星附近行星位置的功能有什么问题?
【发布时间】:2015-07-04 07:06:46
【问题描述】:

最初,代码似乎在行星向恒星弯曲时起作用,但由于它应该被拉入恒星或进入轨道,它只是被推向相反的方向。我究竟做错了什么?当距离的符号发生变化时,行为的变化似乎发生了。

if(!alive){
    return;
}
xPos += t * velocity/10000 * cos(direction / 180 * 3.14);
yPos += t * velocity/10000 * sin(direction / 180 * 3.14);

double gravity = 1000;
double starX = 1920/2;
double starY = 1080/2;

double deltaX = xPos - starX;
double deltaY = yPos - starY;
double distance = sqrt(pow(deltaX, 2) + pow(deltaY, 2));
int modifier = 1;
if (xPos > starX){
    modifier = -1;
}
double angle = atan(deltaY / deltaX) * 180 / 3.14;
std::cout << angle << std::endl;

xPos += t * gravity / pow(distance,2) * modifier * cos(angle / 180 * 3.14);
yPos += t * gravity / pow(distance,2) * modifier * sin(angle / 180 * 3.14);

if (xPos > starX - 100 && xPos < starX + 100 && yPos > starY - 100 && yPos < starY + 100){
    alive = false;
}

xPos 和 yPos 是行星的当前位置。 t 是自上次更新以来的时间。速度和方向是行星开始时的初始速度和角度。自从我们在太空中以来,这种力量永远不会改变。重力是万有引力常数。 starX 和starY 是恒星的位置,distance 是恒星与行星之间的距离。 angle 是恒星和行星之间的角度(我有一种感觉,这就是导致不良行为的原因。)

【问题讨论】:

  • 距离符号如何变化? sqrt 将始终返回一个正数
  • 对,这就是为什么如果距离应该是负数,我会在其中添加那个修饰符。
  • 为什么应该是负数?如果不使用修饰符会怎样?
  • 如果不使用修饰符,如果行星在恒星的右侧,恒星会将行星推向相反的方向。
  • 任何给定时间的力都会导致速度变化,但您将这种变化直接应用于位置,这不是运动方程的工作方式。 x 和 y 方向的速度增量的符号由 sin/cos 调用确定,因此您不需要使用任何“修饰符”标志。

标签: c++ math physics game-physics orbital-mechanics


【解决方案1】:

您的第一个问题是使用 atan(y/x) 而不是 atan2(y, x) 来解决您遇到的麻烦。特别是当 x 变小时,atan2 将正确处理,而 atan 在相同条件下将无法处理 y/x。我认为这是导致您大吃一惊的主要原因,因为我根据自己的条件使用您的代码。

话虽如此,@Jim Lewis 和@CodesInChaos 也在进行重要的观察。 F=ma 意味着你应该从你的力中获得加速度,然后对加速度进行积分以获得速度(这必须是一个状态变量),然后对速度进行积分以获得位置。如果你想让你的程序在行星螺旋进入恒星时保持稳定,你将需要一种更复杂的积分方法。您现有的方法被称为“欧拉方法”,如果您在 Wikipedia 中查找它,您将了解您的立场和应该去的地方。

另一个改进是加入“智能三角法”。请注意,当您拥有直角三角形的三个边时,无需计算角度即可计算正弦和余弦。在这种情况下,您的双方是距离、deltaX 和 deltaY。因此,您可以执行 cosAngle = deltaX / distance 和 sinAngle = deltaY / distance,并使用它们来计算加速度的分量。要确认这一点,您可以检查 cosAngle*cosAngle + sinAngle*sinAngle = 1。这些符号也完全适合用于其余计算。

我想你会发现,如果你“正确地做 Euler”,忠实地实现运动方程并使用 atan2 或 smart trig,你会发现你根本不需要你的“修改器”hack。如果这是为了游戏(你的 1920/2,1080/2 让我相信它是),并且你可以很好地控制初始条件,而不是太长时间地踩系统,你可能不需要从欧拉升级。

【讨论】:

  • Protip:不要做任何类型的 atan,跳过角度的计算,只做 cosTheta = deltaX/distance 和 sinTheta = deltaY/distance 并使用它们代替你的 cos(anglePI/180) 和 sin(角度PI/180)。 cosTheta = deltaX/distance 就是余弦的定义。
  • 专业提示:您可以随时编辑自己的答案以改进它们。您的 protip 非常适合包含在您的答案主体中。
  • 谢谢@HristoIliev 我决定听从你的建议。我还学习了如何在文本中使用两个星号而不使用 italics
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-27
  • 1970-01-01
相关资源
最近更新 更多