Упругое нецентральное соударение шаров разной массы и размеров на JS
Пишу физику для 2d игры. И вот такая функция проверяет столкновения:
function distance(obj1, obj2){ //проверка на столкновение
let xDist=obj1.x-obj2.x; //расстояние по x
let yDist=obj1.y-obj2.y;
if(Math.sqrt(Math.pow(xDist,2)+Math.pow(yDist,2))<=(obj1.radius + obj2.radius)){
//пересчет скоростей при столкновении
//для первого объекта
obj1.speedX = -(2*obj2.massa*obj2.speedX+obj1.speedX*(obj1.massa-
obj2.massa))/(obj1.massa+obj2.massa);
obj1.speedY = -(2*obj2.massa*obj2.speedY+obj1.speedY*(obj1.massa-
obj2.massa))/(obj1.massa+obj2.massa);
//для второго
obj2.speedX = -(2*obj1.massa*obj1.speedX+obj2.speedX*(obj2.massa-
obj1.massa))/(obj2.massa+obj1.massa);
obj2.speedY = -(2*obj1.massa*obj1.speedY+obj2.speedY*(obj2.massa-
obj1.massa))/(obj2.massa+obj1.massa);
return 1; //если расстояние меньше, то они столкнулись
}
}
obj1.x- координата по x-у.
obj1.speedX- скорость по x-у.
obj1.massa- масса.
При таком просчете любые столкновения выглядят как будто бы соударение было центральным- одна окружность задевает вторую лишь слегка, и вторая должна отскочить в сторону, а она движется как будто бы вектор удара пришелся на центр массы. Вот можно попробовать(движение стрелками): https://codepen.io/hertzHe/pen/YzGeNJq
Как изменить вычисление векторов чтобы шары отскакивали физически правильно- при нецентральном соударении шаров разной массы и радиуса?
Ответы (1 шт):
Физика удара
Рассмотрим момент когда два шара коснулись друг друга. Введём систему координат в которой ось X совпадает с прямой соединяющей центры шаров. Ось Y перпендикулярна.
В этой системе координат вертикальные скорости в момент удара не изменятся. Горизонтальные скорости поменяются в соответствии физикой центрального удара, как если бы вертикальных скоростей не было вовсе.
Рассчёт
Проектировать скорости можно так. (x, y) - отрезок соединяющий центры шаров, причём нормированный. Тогда проекция скорости v на это отрезок - скалярное произведение vx = dot(v, (x, y)). Проекция скорости на перпендикуляр - vy = dot(v, (-y, x)).
После того как вы обработали удар, то есть пересчитали горизонтальные состовляющие скоростей (vx -> vx'), вам нужно собрать из проекций новый вектор скорости: v' = vx' * (x, y) + vy * (-y, x).
Ещё рассчёт
Небольшое дополнение: проектировать на перпендикулярную ось не обязательно. Эта математика хороша тем что работает и на плоскости и в пространстве (тогда вектор центров будет иметь вид (x, y, z)):
vx = dot(v, (x, y)) - проектируем скорость на прямую между центрами
vn = v - vx * (x, y) - нормальная состовляющая скорости в виде вектора
vx -> vx' - центральный удар на оси X (одномерный)
v' = vx' * (x, y) + vn - восстанавливаем полную скорость.
Одномерный центральный удар
Скорость центра масс системы до удара. По закону сохранения она сохранится и после удара:
vx = (obj1.massa * vx1 + obj2.massa * vx2) / (obj1.massa + obj2.massa)
Изменение скоростей первого и второго тел (штрихи - скорости после удара). Тут формулировка такая: если центр масс неподвижен до удара, то скорости должны измениться на противоположные:
vx1 - vx = -(vx1' - vx)
vx2 - vx = -(vx2' - vx)
Откуда получаем:
vx1' = 2 * vx - vx1
vx2' = 2 * vx - vx2