Как сбросить два движущихся объекта - PullRequest
1 голос
/ 25 мая 2019

Я делаю игру ConSumo с аркадного автомата в Bully.По сути, есть вражеский борец, который движется по прямой линии и отскочит игрока в случае столкновения.Кажется, я не могу понять логику в углу, чтобы отскочить от игрока при столкновении с вражеским борцом.

Я попытался вычислить угол столкновения, используя арктан из (player.centerY - врага.centerY) /(player.centerX - player.centerY), а затем добавив 180 градусов, чтобы отразить угол.

double angle = Math.atan(((player.getCenterY() - enemies[i].getCenterY())/ (player.getCenterX() - enemies[i].getCenterX())));
angle = Math.toDegrees(angle);
angle += 180;
angle = Math.toRadians(angle);

player.addX(Math.cos(Angle) * strength);
plyaer.addY(-(Math.sin(angle) * strength));

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

1 Ответ

0 голосов
/ 25 мая 2019

Может быть, вы можете попробовать физический подход, учитывающий сохранение импульса и сохранение энергии.

По сути, игрок с массой mp имеет скорость [vp; 0] и противник с массой me, у игрока скорость [ve; 0].Нет компонентов, потому что они движутся только горизонтально.Теперь во время столкновения t = t_col предположим, что центр масс игрока имеет координаты [xp, yp], а центр масс врага имеет координаты [xe, ye] (вы всегда можете настроить их, чтобы убедиться, что эффект отскакивания больше, делая координаты у гораздо более разными, если хотите).

Сохранение импульса говорит нам, что скорости двух объектов, назовите их [Vp, Wp] и [Ve, We] сразу после столкновения, вычисляются следующим образом

[Vp; Wp] = [vp; 0] + (1/mp)*[I1; I2];

[Ve; We] = [ve; 0] - (1/me)*[I1; I2]; 

где, как это обычно бываетПредполагается, что удар является нормальным к поверхности объектов, вектор [I1; I2] можно принять как выровненный с вектором, соединяющим два центра: [xp - xe; yp - ye].Комбинируя эту информацию с сохранением энергии, можно вычислить величину указанного вектора и найти, что

k = (mp*me/(mp+me)) * (vp - ve)*(xp - xe) / ((xp - xe)^2 + (yp - ye)^2);

I1 = k*(xp - xe);

I2 = k*(yp - ye);

Таким образом, в основном, во время столкновения вы получаете в качестве входных данных:

  • позиция и скорость игрока: [xp; yp], [vp; 0]
  • позиция и скорость противника: [xe; ye], [ve; 0]
  • масса игрока mp и масса противника me

Затем вычислите

k = (mp*me/(mp+me)) * (vp - ve)*(xp - xe) / ((xp - xe)^2 + (yp - ye)^2);

I1 = k*(xp - xe);

I2 = k*(yp - ye);

Vp = vp + (1/mp)*I1;

Wp = (1/mp)*abs(I2);

Ve = ve - (1/me)*I1; 

We = (1/me)*abs(I2); 

Обратите внимание, что я использовал abs(I2), который является абсолютным значением I2.Это связано с тем, что для одного из двух объектов y-компонента скорости после столкновения будет положительной (поэтому никакой разницы нет), а для другого будет отрицательной.К отрицательному мы также можем добавить тот факт, что объект может отскочить от земли сразу после столкновения (таким образом, столкновение с объектом, а затем столкновение с землей).Таким образом, мы используем закон отражения, подобно тому, как свет отражается зеркалом.

После столкновения в момент времени t = t_col параболические траектории двух игроков (прежде чем они приземлятся обратно на землю) будут

xp(t) = xp + Vp * (t - t_col);

yp(t) = yp + Wp * (t - t_col) - (g/2) * (t - t_col)^2; 

xe(t) = xe + Ve * (t - t_col);

ye(t) = ye + We * (t - t_col) - (g/2) * (t - t_col)^2;

Если вам нужны углы:

cos(angle_p) = Vp / (Vp^2 + Wp^2);

sin(angle_p) = Wp / (Vp^2 + Wp^2);

cos(angle_e) = Ve / (Ve^2 + We^2);

sin(angle_e) = We / (Ve^2 + We^2);

, где angle_p - угол наклона игрока, а angle_e - угол врага.

...