We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › 2D collision of circles, works but buggy
Page Index Toggle Pages: 1
2D collision of circles, works but buggy (Read 1057 times)
2D collision of circles, works but buggy
Feb 6th, 2010, 6:16am
 
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()Wink, 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);
}
Re: 2D collision of circles, works but buggy
Reply #1 - Feb 6th, 2010, 6:17am
 
continuation of circle.pde
Code:

void bewegen()
{
//geschwindigkeit.add(beschleunigung);
ort.add(geschwindigkeit);

ort.x = constrain(ort.x, 0 + durchmesser / 2, width - durchmesser / 2);
ort.y = constrain(ort.y, 0 + durchmesser / 2, height - durchmesser / 2);
}

void abprallen()
{
if(ort.x == durchmesser / 2 || ort.x == width - durchmesser / 2)
{
geschwindigkeit.x = -geschwindigkeit.x * reibung;
geschwindigkeit.y = geschwindigkeit.y * reibung;
}
if(ort.y == durchmesser / 2 || ort.y == height - durchmesser / 2)
{
geschwindigkeit.y = -geschwindigkeit.y * reibung;
geschwindigkeit.x = geschwindigkeit.x * reibung;
}
}
}

Re: 2D collision of circles, works but buggy
Reply #2 - Feb 6th, 2010, 6:22am
 
How could I correct this bug? It looks pretty shitty when the circles clump together: they start flying around.
Is there a better way to realize collision - with vectors?
I’ve got a maximum of 99 circles because I don’t know how to initialize the arrays needed for the class. If I use Code:
float[] var = new float[kreise.length] 

a OutOfBoundException is returned. Every instance is constructed only once, I think.

Thanks in advance.

PS. If you want to, I upload this sketch to openprocesing.org.
Re: 2D collision of circles, works but buggy
Reply #3 - Feb 7th, 2010, 11:39pm
 
When you detect a collision, the two balls could be overlapping.
You could 'reset' the balls' position to slightly apart after they collide to keep them from spiraling out of control.

If you like, I can post a sketch I have worked on. It doesn't use Vectors, but behaves similarly to your program.
Re: 2D collision of circles, works but buggy
Reply #4 - Feb 8th, 2010, 1:47am
 
There's a comprehensive example of cirlce collision using coordinate rotation (and taking mass into account) in the learning section.

This is also something of a FAQ - the usual problem is that if two circles are travelling at speed they overlap by a large amount when the collision is detected.  If you're implementing friction, or other factors that affect the circle's speed, when the circles 'bounce' (i.e. you reverse the vector) they may not escape the overlap in that frame meaning a bounce will be registered in the next frame, often leading them to get 'stuck' together.  The answer is to cheat, as NoahBuddy said: as well as reversing the vector you move the circles so they are no longer overlapping, then on the next frame they're free to fly off in the appropriate direction...
Page Index Toggle Pages: 1