Con l'aiuto della comunità Stack Overflow ho scritto un simulatore di fisica piuttosto semplice ma divertente.
Fai clic e trascina il mouse per lanciare una palla. Rimbalzerà intorno e alla fine si fermerà sul "pavimento".
La mia prossima grande caratteristica che voglio aggiungere è la collisione palla a palla. Il movimento della palla è suddiviso in vettore di velocità ascia e y. Ho gravità (piccola riduzione del vettore y ogni passo), ho attrito (piccola riduzione di entrambi i vettori ogni collisione con un muro). Le palle si muovono onestamente in modo sorprendentemente realistico.
Immagino che la mia domanda abbia due parti:
- Qual è il metodo migliore per rilevare la collisione palla a palla?
Ho solo un ciclo O (n ^ 2) che scorre su ogni palla e controlla ogni altra palla per vedere se il suo raggio si sovrappone? - Quali equazioni utilizzo per gestire le collisioni palla-palla? Fisica 101 In che
modo influiscono sui vettori x / y delle due sfere? Qual è la direzione risultante in cui si dirigono le due palle? Come posso applicarlo a ogni palla?
Gestire il rilevamento delle collisioni delle "pareti" e i risultanti cambiamenti del vettore sono stati facili ma vedo più complicazioni con le collisioni palla-palla. Con i muri dovevo semplicemente prendere il negativo del vettore x o y appropriato e andava nella direzione corretta. Con le palle non penso che sia così.
Alcuni rapidi chiarimenti: per semplicità sto bene con una collisione perfettamente elastica per ora, anche tutte le mie palle hanno la stessa massa in questo momento, ma potrei cambiarlo in futuro.
Modifica: risorse che ho trovato utili
Fisica della sfera 2d con vettori: collisioni bidimensionali senza trigonometria.pdf
Esempio di rilevamento della collisione con sfera 2d: aggiunta del rilevamento delle collisioni
Successo!
Il rilevamento e la risposta della collisione con la palla funzionano alla grande!
Codice rilevante:
Rilevazione di collisioni:
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]);
}
}
}
Questo controllerà le collisioni tra ogni palla ma salterà i controlli ridondanti (se devi controllare se la palla 1 si scontra con la palla 2, non dovrai controllare se la palla 2 si scontra con la palla 1. Inoltre, salta il controllo delle collisioni con se stessa ).
Quindi, nella mia classe di palla ho i miei metodi colliding () e 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));
}
Codice sorgente: fonte completa per il collettore palla a palla.
Se qualcuno ha qualche suggerimento su come migliorare questo simulatore di fisica di base fammelo sapere! Una cosa che devo ancora aggiungere è il momento angolare, quindi le palle rotoleranno in modo più realistico. Altri suggerimenti? Lascia un commento!
Vector2d impulse = mtd.multiply(i);
dovrebbe essere i * il vettore mtd normalizzato. Qualcosa del tipo:Vector2d impulse = mtd.normalize().multiply(i);