С помощью сообщества Stack Overflow я написал довольно простой, но увлекательный симулятор физики.
Вы щелкаете мышью и запускаете шар. Он будет подпрыгивать и в конце концов остановится на «полу».
Моя следующая большая особенность, которую я хочу добавить, это столкновение мяча с мячом. Движение мяча разбито на топор и вектор скорости y. У меня есть сила тяжести (небольшое уменьшение вектора y на каждом шаге), у меня есть трение (небольшое уменьшение обоих векторов при каждом столкновении со стеной). Мячи честно перемещаются удивительно реалистичным способом.
Я думаю, мой вопрос состоит из двух частей:
- Каков наилучший метод обнаружения столкновения шара с мячом?
У меня просто есть петля O (n ^ 2), которая перебирает каждый шар и проверяет каждый другой шар, чтобы увидеть, перекрывается ли его радиус? - Какие уравнения я использую, чтобы справиться с столкновениями шара с шаром? Физика 101
Как это влияет на скорость вращения двух шаров по векторам x / y? В каком направлении движутся два мяча? Как я могу применить это к каждому шару?
Обработка обнаружения столкновений «стенок» и результирующих изменений вектора была легкой, но я вижу больше сложностей с столкновениями шарик-шар. Со стенами мне просто нужно было взять отрицательное значение соответствующего вектора x или y, и оно пошло бы в правильном направлении. С шарами я не думаю, что это так.
Несколько быстрых пояснений: для простоты я в порядке с совершенно упругим столкновением на данный момент, также все мои шары имеют одинаковую массу прямо сейчас, но я мог бы изменить это в будущем.
Изменить: ресурсы, которые я нашел полезными
2d Физика шаров с векторами: 2-мерные столкновения без тригонометрии.pdf
2d Пример обнаружения столкновений шаров: добавление обнаружения столкновений
Успех!
У меня есть обнаружение столкновения мяча и реакция работает отлично!
Соответствующий код:
Обнаружение столкновения:
for (int i = 0; i < ballCount; i++)
{
for (int j = i + 1; j < ballCount; j++)
{
if (balls[i].colliding(balls[j]))
{
balls[i].resolveCollision(balls[j]);
}
}
}
Это будет проверять наличие столкновений между каждым шаром, но пропустить лишние проверки (если вам нужно проверить, сталкивается ли шар 1 с шаром 2, вам не нужно проверять, сталкивается ли шар 2 с шаром 1. Кроме того, он пропускает проверку на столкновения с самим собой. ).
Затем в моем классе Ball у меня есть методы colliding () и resolCollision ():
public boolean colliding(Ball ball)
{
float xd = position.getX() - ball.position.getX();
float yd = position.getY() - ball.position.getY();
float sumRadius = getRadius() + ball.getRadius();
float sqrRadius = sumRadius * sumRadius;
float distSqr = (xd * xd) + (yd * yd);
if (distSqr <= sqrRadius)
{
return true;
}
return false;
}
public void resolveCollision(Ball ball)
{
// get the mtd
Vector2d delta = (position.subtract(ball.position));
float d = delta.getLength();
// minimum translation distance to push balls apart after intersecting
Vector2d mtd = delta.multiply(((getRadius() + ball.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / ball.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
ball.position = ball.position.subtract(mtd.multiply(im2 / (im1 + im2)));
// impact speed
Vector2d v = (this.velocity.subtract(ball.velocity));
float vn = v.dot(mtd.normalize());
// sphere intersecting but moving away from each other already
if (vn > 0.0f) return;
// collision impulse
float i = (-(1.0f + Constants.restitution) * vn) / (im1 + im2);
Vector2d impulse = mtd.normalize().multiply(i);
// change in momentum
this.velocity = this.velocity.add(impulse.multiply(im1));
ball.velocity = ball.velocity.subtract(impulse.multiply(im2));
}
Исходный код: полный исходный код для коллайдера.
Если у кого-то есть предложения по улучшению этого базового симулятора физики, дайте мне знать! Одна вещь, которую я еще должен добавить, это угловой момент, чтобы шары катились более реалистично. Любые другие предложения? Оставить комментарий!
Vector2d impulse = mtd.multiply(i);
должна быть * нормализованным вектором mtd. Что-то вроде:Vector2d impulse = mtd.normalize().multiply(i);