-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 は星と惑星の間の距離です。angle は、星と惑星の間の角度です (これが望ましくない動作を引き起こしていると感じています)。

4

1 に答える 1

1

最初の問題は、atan2(y, x) の代わりに atan(y/x) を使用することです。これは、あなたが抱えている問題の種類を意味します。具体的には、x が小さくなると、atan2 は適切に処理されますが、atan は同じ条件下で y/x を処理できなくなります。私はあなたのコードを独自の条件で取っているので、これがあなたが抱えている爆発の主な理由だと思います。

そうは言っても、@Jim Lewis と @CodesInChaos も重要な観察を行っています。F=ma は、力から加速度を導き出し、加速度を積分して速度 (状態変数である必要があります) を取得し、速度を積分して位置を取得する必要があることを意味します。また、惑星が星に渦巻くときにプログラムを安定させたい場合は、より洗練された統合方法が必要になります。あなたの既存の方法は「オイラー法」として知られており、ウィキペディアで調べると、現在の立場と進むべき道がわかります。

追加の改良は、「スマート三角法」を組み込むことです。直角三角形の 3 つの辺がある場合、正弦と余弦を計算するために角度を計算する必要がないことに注意してください。この場合の側面は、距離、deltaX、および deltaY です。したがって、cosAngle = deltaX / distance および sinAngle = deltaY / distance を実行し、それらを使用して加速度のコンポーネントを計算できます。これを確認するには、cosAngle*cosAngle + sinAngle*sinAngle = 1 を確認します。また、これらの符号は、残りの計算で使用するのに正確です。

「オイラーを適切に実行」し、運動方程式を忠実に実装し、atan2 またはスマート トリガーを使用すると、「修飾子」ハックがまったく必要ないことがわかると思います。これがゲーム用であり (あなたの 1920/2,1080/2 がそうであると私に信じ込ませます)、初期条件を十分に制御でき、システムを過度にステップさせない場合は、そうする必要がないかもしれません。オイラーからのアップグレード。

于 2015-07-04T09:40:15.383 に答える