С помощью сообщества Qaru я написал довольно простой, но увлекательный симулятор физики.
Вы щелкаете мышью и запускаете шар. Он будет подпрыгивать и в конце концов остановится на "полу".
Моя следующая большая особенность, которую я хочу добавить, это коллизия мяча с мячом. Движение мяча разбито на топор и вектор скорости y. У меня есть сила тяжести (небольшое уменьшение вектора y на каждом шаге), у меня есть трение (небольшое уменьшение обоих векторов при каждом столкновении со стеной). Мячи честно перемещаются удивительно реалистичным способом.
Я думаю, мой вопрос состоит из двух частей:
- Каков наилучший метод обнаружения столкновения шара с мячом?
У меня просто есть петля O (n ^ 2), которая перебирает каждый шар и проверяет каждый другой шар, чтобы увидеть, перекрывается ли его радиус? - Какие уравнения я использую, чтобы справиться с столкновениями шара с шаром? Физика 101
Как это влияет на скорость вращения двух шаров по векторам x/y? В каком направлении движутся два мяча? Как я могу применить это к каждому шару?
Обработка обнаружения столкновений "стенок" и результирующих изменений вектора была легкой, но я вижу больше сложностей с столкновениями шарик-шар. Со стенами мне просто нужно было взять отрицательное значение соответствующего вектора x или y, и оно пошло бы в правильном направлении. С шарами я не думаю, что это так.
Несколько быстрых пояснений: для простоты пока я в порядке с совершенно упругим коллизиям, сейчас все мои шары имеют одинаковую массу, но я могу изменить это в будущем.
Изменение: ресурсы, которые я нашел полезными
Физика двумерного шара с векторами: двумерные столкновения без тригонометрии .pdf
Пример обнаружения столкновения 2d Ball: добавление обнаружения столкновения
Успех!
У меня есть обнаружение столкновения мяча и реакция работает отлично!
Соответствующий код:
Обнаружение столкновения:
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));
}
Исходный код: полный исходный код для коллайдера.
Если у кого-то есть предложения по улучшению этого базового симулятора физики, дайте мне знать! Одна вещь, которую я должен добавить, - это момент импульса, чтобы шарики катились более реалистично. Любые другие предложения? Оставить комментарий!