-1

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

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 是恒星与行星之间的距离。角度是恒星和行星之间的角度(我感觉这是导致不良行为的原因。)

4

1 回答 1

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 让我相信它是),并且你可以很好地控制初始条件,而不是太长时间地踩系统,你可能不需要从欧拉升级。

于 2015-07-04T09:40:15.383 回答