За допомогою спільноти Stack Overflow я написав досить базовий, але веселий фізичний симулятор.
Ви натискаєте та перетягуєте мишу, щоб запустити кульку. Він відскочить і врешті-решт зупиниться на «підлозі».
Наступна моя велика особливість, яку я хочу додати, - це зіткнення м'яча на кулю. Рух кулі розбивається на вектор оси та y швидкості. У мене гравітація (невелике зменшення y вектора на кожен крок), у мене тертя (невелике зменшення обох векторів при кожному зіткненні зі стінкою). Кулі чесно рухаються навколо напрочуд реалістичним способом.
Я думаю, моє запитання має дві частини:
- Який найкращий спосіб виявити зіткнення кульки в кулю?
Чи просто у мене є петля O (n ^ 2), яка переходить над кожною кулькою і перевіряє кожну іншу кулю, щоб побачити, чи перекривається її радіус? - Які рівняння я використовую для обробки кулі до зіткнення кулі? Фізика 101
Як це впливає на швидкість руху двох кульок х / у? У якому отриманому напрямку обидва кулі відхиляються? Як застосувати це до кожного кульки?
Впоратися з виявленням зіткнень "стінок" та отриманими в результаті цього векторними змінами було легко, але я бачу більше ускладнень при зіткненнях з кулькою. Зі стінами я просто повинен був взяти мінус відповідного вектора x або y, і він пішов би в правильному напрямку. З кульками я не думаю, що це так.
Деякі швидкі роз'яснення: для простоти я все в порядку з ідеально еластичним зіткненням, також всі мої кулі мають тепер однакову масу, але я можу змінити це в майбутньому.
Редагувати: Ресурси, які я вважаю корисними
Фізика 2d кульки з векторами: 2-мірними зіткненнями без Trigonometry.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. Також він пропускає перевірку на зіткнення з самим собою ).
Потім у моєму бальному класі я використовую свої методи зіткнення () та вирішення колізій ():
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);
повинен бути i * нормалізованим вектором mtd. Щось на кшталт:Vector2d impulse = mtd.normalize().multiply(i);