Z pomocą społeczności Stack Overflow napisałem całkiem prosty, ale zabawny symulator fizyki.
Kliknij i przeciągnij myszą, aby uruchomić piłkę. Odbije się i ostatecznie zatrzyma na „podłodze”.
Kolejną ważną funkcją, którą chcę dodać, jest zderzenie piłki z piłką. Ruch piłki jest podzielony na wektor ax i y prędkości. Mam grawitację (małe zmniejszenie wektora y na każdym kroku), mam tarcie (małe zmniejszenie obu wektorów przy każdym zderzeniu ze ścianą). Piłki szczerze się poruszają w zaskakująco realistyczny sposób.
Myślę, że moje pytanie składa się z dwóch części:
- Jaka jest najlepsza metoda wykrywania kolizji piłki z piłką?
Czy mam po prostu pętlę O (n ^ 2), która przechodzi przez każdą piłkę i sprawdza każdą inną piłkę, aby sprawdzić, czy jej promień się pokrywa? - Jakich równań używam do obsługi zderzeń piłki z piłką? Fizyka 101
Jak to wpływa na prędkość dwóch kulek wektorów x / y? W jakim kierunku zmierzają obie piłki? Jak zastosować to do każdej piłki?
Obsługa wykrywania kolizji „ścian” i wynikających z tego zmian wektora była łatwa, ale widzę więcej komplikacji w przypadku zderzeń piłki z piłką. W przypadku ścian musiałem po prostu wziąć ujemny odpowiedni wektor x lub y, po czym poszedłby we właściwym kierunku. Z piłkami nie sądzę, że tak jest.
Kilka szybkich wyjaśnień: dla uproszczenia jestem na razie z idealnie elastycznym zderzeniem, również wszystkie moje piłki mają teraz tę samą masę, ale mogę to zmienić w przyszłości.
Edycja: zasoby, które uważam za przydatne
Fizyka kuli 2d z wektorami: zderzenia dwuwymiarowe bez trygonometrii.pdf
Przykład 2d wykrywania kolizji kuli: Dodawanie detekcji kolizji
Sukces!
Wykrywanie kolizji z piłką i reakcja działają świetnie!
Odpowiedni kod:
Wykrywanie kolizji:
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]);
}
}
}
Spowoduje to sprawdzenie kolizji między każdą piłką, ale pominie zbędne kontrole (jeśli musisz sprawdzić, czy piłka 1 koliduje z piłką 2, nie musisz sprawdzać, czy piłka 2 koliduje z piłką 1. Pomija również sprawdzanie kolizji ze sobą) ).
Następnie w mojej klasie ball mam metody colliding () i 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));
}
Kod źródłowy: Pełne źródło zderzacza piłka-piłka.
Jeśli ktoś ma jakieś sugestie dotyczące ulepszenia tego podstawowego symulatora fizyki, daj mi znać! Jedną z rzeczy, które muszę jeszcze dodać, jest moment pędu, aby kule toczyły się bardziej realistycznie. Jakieś inne sugestie? Zostaw komentarz!
Vector2d impulse = mtd.multiply(i);
powinna być znormalizowanym wektorem mtd. Coś w stylu:Vector2d impulse = mtd.normalize().multiply(i);