Mit Hilfe der Stack Overflow-Community habe ich einen ziemlich einfachen, aber unterhaltsamen Physik-Simulator geschrieben.
Sie klicken und ziehen die Maus, um einen Ball zu starten. Es wird herumspringen und schließlich auf dem "Boden" anhalten.
Mein nächstes großes Feature, das ich hinzufügen möchte, ist die Kollision von Ball zu Ball. Die Bewegung des Balls wird in Axt- und Y-Geschwindigkeitsvektor aufgeteilt. Ich habe Schwerkraft (kleine Reduktion des y-Vektors bei jedem Schritt), ich habe Reibung (kleine Reduktion beider Vektoren bei jeder Kollision mit einer Wand). Die Bälle bewegen sich ehrlich und überraschend realistisch.
Ich denke meine Frage besteht aus zwei Teilen:
- Was ist die beste Methode, um eine Kollision von Ball zu Ball zu erkennen?
Habe ich nur eine O (n ^ 2) -Schleife, die über jeden Ball iteriert und jeden anderen Ball überprüft, um festzustellen, ob sich der Radius überlappt? - Welche Gleichungen verwende ich, um mit Kollisionen von Ball zu Ball umzugehen? Physik 101
Wie wirkt es sich auf die Geschwindigkeit der x / y-Vektoren der beiden Kugeln aus? In welche Richtung gehen die beiden Bälle? Wie wende ich das auf jeden Ball an?
Die Handhabung der Kollisionserkennung der "Wände" und der daraus resultierenden Vektoränderungen war einfach, aber ich sehe mehr Komplikationen bei Ball-Ball-Kollisionen. Bei Wänden musste ich einfach das Negativ des entsprechenden x- oder y-Vektors nehmen und es ging in die richtige Richtung. Bei Bällen glaube ich nicht, dass es so ist.
Einige schnelle Klarstellungen: Der Einfachheit halber bin ich mit einer perfekt elastischen Kollision im Moment in Ordnung, auch alle meine Bälle haben momentan die gleiche Masse, aber das könnte ich in Zukunft ändern.
Bearbeiten: Ressourcen, die ich nützlich gefunden habe
2d Ballphysik mit Vektoren: 2-dimensionale Kollisionen ohne Trigonometrie.pdf
Beispiel für die Erkennung von 2d Ballkollisionen: Hinzufügen einer Kollisionserkennung
Erfolg!
Ich habe die Ballkollisionserkennung und -reaktion großartig!
Relevanter Code:
Kollisionserkennung:
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]);
}
}
}
Dies prüft auf Kollisionen zwischen jedem Ball, überspringt jedoch redundante Prüfungen (wenn Sie prüfen müssen, ob Ball 1 mit Ball 2 kollidiert, müssen Sie nicht prüfen, ob Ball 2 mit Ball 1 kollidiert. Außerdem wird die Überprüfung auf Kollisionen mit sich selbst übersprungen ).
Dann habe ich in meiner Ballklasse meine Methoden colliding () und resolveCollision ():
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));
}
Quellcode: Vollständige Quelle für Ball-zu-Ball-Collider.
Wenn jemand Vorschläge zur Verbesserung dieses grundlegenden Physiksimulators hat, lass es mich wissen! Eine Sache, die ich noch hinzufügen muss, ist der Drehimpuls, damit die Kugeln realistischer rollen. Irgendwelche anderen Vorschläge? Hinterlasse einen Kommentar!
Vector2d impulse = mtd.multiply(i);
sollte i * der normalisierte mtd-Vektor sein. So etwas wie:Vector2d impulse = mtd.normalize().multiply(i);