Что не так с моей функцией обновления положения планеты возле звезды?

Вначале код, кажется, работает, когда планета изгибается к звезде, но затем, когда он должен или втягиваться в звезду, или делать орбиту, он просто отталкивается в противоположном направлении. Что я делаю неправильно? Кажется, что изменение в поведении происходит, когда меняется знак расстояния.

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 — текущее положение планеты. время, прошедшее с момента последнего обновления. скорость и направление — начальная скорость и угол, под которым начинается планета. Эта сила никогда не меняется, так как мы находимся в космосе. гравитация — это гравитационная постоянная. starX и starY — это положение звезды, а расстояние — это расстояние между звездой и планетой. угол — это угол между звездой и планетой (у меня такое ощущение, что именно это и вызывает нежелательное поведение.)

-1

Решение

Ваша первая проблема — использовать atan (y / x) вместо atan2 (y, x), что предназначено для того, чтобы решить проблему. В частности, когда x становится маленьким, atan2 справится должным образом, в то время как atan не сможет справиться с y / x в тех же условиях. Я думаю, что это главная причина вашего взрыва, так как я воспринимаю ваш код на своих собственных условиях.

Сказав это, @Jim Lewis и @CodesInChaos также делают важные наблюдения. F = ma означает, что вы должны вывести ускорение из своих сил, а затем интегрировать ускорение, чтобы получить скорость (которая должна быть переменной состояния), и интегрировать скорость, чтобы получить положение. И если вы хотите, чтобы ваша программа была стабильной, когда планета превращается в звезду, вам понадобится более сложный метод интеграции. Ваш существующий метод известен как «метод Эйлера», и если вы посмотрите его в Википедии, вы получите представление о том, где вы стоите и куда вам следует идти.

Дополнительным уточнением было бы включение «умной тригонометрии». Заметьте, что, когда у вас есть три стороны прямоугольного треугольника, нет необходимости вычислять угол для вычисления синуса и косинуса. В этом случае ваши стороны — это расстояние, deltaX и deltaY. Таким образом, вы можете сделать cosAngle = deltaX / distance и sinAngle = deltaY / distance и использовать их для вычисления компонентов ускорения. Чтобы убедиться в этом, вы можете проверить cosAngle * cosAngle + sinAngle * sinAngle = 1. Кроме того, их знак точно подходит для использования в остальной части вычисления.

Я думаю, вы обнаружите, что если вы «сделаете Эйлера правильно», точно реализуете уравнения движения и используете atan2 или умный триг, вы обнаружите, что вам вообще не понадобится ваш хак «модификатор». Может получиться так, что если это для игры (ваш 1920 / 2,1080 / 2 заставляет меня поверить, что это так), и вы можете достаточно хорошо контролировать начальные условия и не перегружать систему слишком долго, вам может не понадобиться обновить от Эйлера.

1

Другие решения


По вопросам рекламы [email protected]