The last three days I spent on a sketch of colliding circles. It was pretty hard because everything about trigonometry has fallen in oblivion within several years after my graduation, but finally I made it work. Unfortunately, the circles tend to clump together, especially when I turn on gravity. I believe a flat angle causes this problem, too - but I’m not sure.
Here’s the code:
main.pde Code:
boolean beschleunigungsschalter = false;
String[] informationen = new String[3];
float reibung = 1;
float durchmesser = 50;
PVector[] ort = new PVector[3];
PVector[] geschwindigkeit = new PVector[3];
PVector beschleunigung = new PVector(0, .981);
PVector start;
int zahl;
Kreis[] kreis = new Kreis[0];
void setup() {
size(800, 500, JAVA2D);
frameRate(30);
smooth();
textFont(createFont("Monospaced", 11));
}
void draw() {
background(227, 184, 44);
int j = 0;
if(beschleunigungsschalter) { informationen[2] = "beschleunigung an; x: " + beschleunigung.x + " y: " + beschleunigung.y; j++; } else { informationen[2] = "beschleunigung aus"; }
for(int i = 0; i < informationen.length; i++)
{
if(informationen[i] != null) text(informationen[i], 10, i * 13 + 20);
}
if(mousePressed)
{
stroke(0);
strokeWeight(1);
line(start.x, start.y, mouseX, mouseY);
}
for(int lauf = 0; lauf < kreis.length; lauf++)
{
pushMatrix();
kreis[lauf].bewegen();
kreis[lauf].abprallen();
kreis[lauf].anzeigen();
kreis[lauf].kollisionerkennen();
if(beschleunigungsschalter) kreis[lauf].beschleunigen();
popMatrix();
}
}
void mousePressed()
{
start = new PVector(mouseX, mouseY);
}
void mouseReleased()
{
PVector ende = new PVector(mouseX, mouseY);
PVector richtung = PVector.sub(ende,start);
float staerke = richtung.mag();
kreis = (Kreis[]) append(kreis, new Kreis(kreis.length, durchmesser, start, richtung, beschleunigung, reibung));
//append(kreis, new Kreis(lauf, durchmesser, ort[lauf], geschwindigkeit[lauf], beschleunigung));
}
void keyPressed()
{
if(key == 'b') beschleunigungsschalter = !beschleunigungsschalter;
}
If you click and drag the mouse a vector for direction and speed of a new circle will be recorded after releasing the button. This circle is moved (kreis[lauf].bewegen()
, reflected at window borders, actually shown and bounced off other circles. If you pressed 'b' gravity is turned on, and the circles will fall down.
circle.pde Code:
class Kreis
{
PVector ort, geschwindigkeit, beschleunigung, wind;
//Kollisionsvariablen
PVector[] abstand = new PVector[99];
PVector[] tangentialvektor = new PVector[99];
PVector[] uebertragungsvektor = new PVector[99];
float[] abstandswert = new float[99];
float[] tangentialwert = new float[99];
float durchmesser, masse, reibung;
int nummer;
Kreis()
{
}
Kreis(int _nummer, float _durchmesser, PVector _ort, PVector _geschwindigkeit, PVector _beschleunigung, float _reibung)
{
nummer = _nummer;
durchmesser = _durchmesser;
ort = _ort;
geschwindigkeit = _geschwindigkeit;
masse = durchmesser * .05;
wind = new PVector(0, 0);
beschleunigung = _beschleunigung;
reibung = _reibung;
}
void kollisionerkennen()
{
for(int i = 0; i < kreis.length; i++)
{
if(i != nummer)
{
abstand[i] = PVector.sub(kreis[i].ort, ort);
abstandswert[i] = abstand[i].mag();
if(abstandswert[i] < durchmesser / 2 + kreis[i].durchmesser / 2)
{
//println("Kollision zwischen den Kreisen " + nummer + " & " + i + " erkannt.");
abstand[nummer] = PVector.sub(ort, kreis[i].ort);
//println("# " + nummer + " abstand: " + abstand[nummer]);
//println("# " + i + " abstand: " + abstand[i]);
kollidieren_test(abstand, nummer, i); //Bedingung nach Testphase wieder entfernen!
}
}
}
}
void kollidieren_test(PVector[] abstand, int ersterkreis, int zweiterkreis)
{
int[] h = new int[2];
float[] waxz = new float[2];
float[] waxv = new float[2];
float[] wtv = new float[2];
float[] waxt = new float[2];
float[] lv = new float[2];
float[] lt = new float[2];
float[] xt = new float[2];
float[] yt = new float[2];
float[] xu = new float[2];
float[] yu = new float[2];
float[] xr = new float[2];
float[] yr = new float[2];
h[0] = ersterkreis;
h[1] = zweiterkreis;
for(int i = 0; i < 2; i++)
{
waxz[i] = atan2(abstand[h[i]].y, abstand[h[i]].x); //Winkel zwischen x-Achse und Zentralvektor
waxv[i] = atan2(kreis[h[i]].geschwindigkeit.y, kreis[h[i]].geschwindigkeit.x); //Winkel zwischen x-Achse und Geschwindigkeitsvektor
wtv[i] = waxz[i] - radians(90) - waxv[i]; //Winkel zwischen Tangential- und Geschwindigkeitsvektor
waxt[i] = waxz[i] - radians(90); //Winkel zwischen x-Achse und Tangentialvektor
lv[i] = kreis[h[i]].geschwindigkeit.mag(); //Länge des Geschwindigkeitsvektors
lt[i] = cos(wtv[i]) * lv[i]; //Länge des Tangentialvektors
xt[i] = cos(waxt[i]) * lt[i]; //x-Wert des Tangentialvektors
yt[i] = tan(waxt[i]) * xt[i]; //y-Wert des Tangentialvektors
xu[i] = kreis[h[i]].geschwindigkeit.x - xt[i]; //x-Wert des zu übertragenen Vektors
yu[i] = kreis[h[i]].geschwindigkeit.y - yt[i]; //y-Wert des zu übertragenen Vektors
xr[i] = xt[i] + xu[1 - i]; //x-Wert des resultierenden Geschwindigkeitsvektors
yr[i] = yt[i] + yu[1 - i]; //y-Wert des resultierenden Geschwindigkeitsvektors
kreis[h[i]].geschwindigkeit.x = xr[i]; //Anwendung des x-Werts des resultierenden Geschwindigkeitsvektors
kreis[h[i]].geschwindigkeit.y = yr[i]; //Anwendung des y-Werts des resultierenden Geschwindigkeitsvektors
}
}
void anzeigen()
{
noFill();
stroke(42, 74, 113);
strokeWeight(2);
translate(ort.x, ort.y);
ellipse(0, 0, durchmesser, durchmesser);
}