Проблема этого подхода в том, что координата Y может стать отрицательной.И как только это произойдет, если начальная скорость недостаточно высока, шар может застрять под поверхностью, как показывают результаты @RetiredNinja
(координата застревает при -0.049
в некоторой точке, что не является правильным поведением).
Ошибочные результаты (не в масштабе) из исходного кода, с измененными параметрами:
Мяч кажется "туннельным""через землю (некоторые значения опускаются ниже нуля).
Как решить эту проблему?Нам нужно правильно разрешить столкновение, убедившись, что шар отскакивает, а не пересекает границу поверхности.Для этого давайте рассмотрим поведение мяча во время временного шага, в котором происходит отскок.
Столкновение происходит, когда вертикальная скорость ивертикальное положение отрицательное.Чтобы найти время и скорость столкновения, используйте уравнения движения:
Получив скорость столкновения, мы можем просто обновить новую вертикальную скоростьна -spring * vc
(spring
должно иметь лучшее имя, например coef_rest
);дополнительным преимуществом является то, что нам больше не нужны вызовы pow
.
. Это может происходить несколько раз в течение временного шага, поэтому мы должны выполнить это в цикле.Еще одна вещь, на которую следует обратить внимание, это то, что с уменьшением вертикальной скорости скачки становятся бесконечно более частыми, поэтому нам нужна скорость отсечения, при которой мяч не будет подпрыгивать.
Код:
#include <stdio.h>
#include <math.h>
#ifndef M_PI
#define M_PI 3.141592654
#endif
int main()
{
const double g = 9.81; // gravity
const double dt = 0.025; // time step
const double maxtime = 5.0; // max time
const double spring = 0.95; // coefficient of restitution
const double cutoff = 1e-4; // cut-off velocity
double speed = 6;
double angle = 32;
angle = angle * M_PI / 180.0;
double init_vx = speed * cos(angle);
double init_vy = speed * sin(angle);
int springnumber = 0;
printf("0.0,0.0\n");
for (double ts = 0.0, vs = init_vy, time = dt; time <= maxtime;)
{
// positions *after* this time step
double px = time * init_vx;
double elapse = time - ts;
double py = 0.0, vy = 0.0;
if (vs >= cutoff)
{
py = (vs - 0.5 * g * elapse) * elapse;
vy = vs - g * elapse;
}
// check for bounce
if (vy < 0.0 && py < 0.0)
{
// collision time
double tc = 2.0 * vs / g;
// update speed after bounce and time of collision
springnumber++;
vs *= spring;
ts += tc;
continue;
}
// print
printf("%f,%f\n", px, py);
// timestep
time += dt;
}
return 0;
}
Результаты испытаний с теми же параметрами, что и раньше:
Шар больше не "туннелирует", что являетсяправильное поведение.