2012-03-31 6 views
2

Ich schreibe ein wenig Physik-Simulation in C++, die grundsätzlich Kreise über den Bildschirm bewegt und wenn zwei Kreise kollidieren, sollten sie in der gleichen Weise abprallen wie Billardkugeln. Wenn die Kreise miteinander kollidieren, werden sie die meiste Zeit praktisch unendlich verlangsamen/sie scheinen aneinander zu haften und werden statisch. Manchmal prallt nur ein Ball bei der Kollision zurück und der andere behält seine Flugbahn bei. Dies ist nur eine einfache 2D-Simulation.Circular collision rebound funktioniert nicht richtig

Also hier ist, was ich für die Erkennung/Ricochet Logik:

bool Ball::BallCollision(Ball &b2) 
{ 
    if (sqrt(pow(b2.x - x, 2) + pow(b2.y - y, 2)) <= b2.radius + radius) // Test for collision 
    { 
     normal[0] = (x - (x + b2.x)/2)/radius; // Finds normal vector from point of collision to radius 
     normal[1] = (y - (y + b2.y)/2)/radius; 
     xvel = xvel - 2 * (xvel * normal[0]) * normal[0]; // Sets the velocity vector to the reflection vector 
     yvel = yvel - 2 * (yvel * normal[1]) * normal[1]; 

     ////x = xprev; // These just move the circle back a 'frame' so the collision 
     ////y = yprev; // detection doesn't detect collision more than once. 
        // Not sure if working? 
    } 
} 

ich nicht herausfinden kann, was mit meiner Funktion falsch ist. Danke für jede Hilfe im Voraus!

bearbeiten:

void Ball::Move() 
{ 
    xprev = x; 
    yprev = y; 
    x += xvel; 
    y += yvel; 
} 

void Ball::DrawCircle() 
{ 
    glColor3ub(100, 230, 150); 
    glBegin(GL_POLYGON); 
    for (int i = 0; i < 10; i++) 
    { 
     angle = i * (2*3.1415/10); 
     newx = x + r*cos(angle); 
     newy = y + r*sin(angle); 
     glVertex2f(newx, newy); 
    } 
    glEnd(); 
} 

Die Schleife:

das normal ist falsch
run_prev.clear(); // A vector, cleared every loop, that holds the Ball objects that collided 

    for (int i = 0; i < num_balls; i++) 
    { 
     b[i].Move(); 
    } 

    for (int i = 0; i < num_balls; i++) 
    { 
     b[i].WallCollision(); // Just wall collision detecting, that is working just fine 
    } 

    //The loop that checks for collisions... Am I executing this properly? 
    for (int i = 0; i < num_balls; i++) 
    { 
     for (int j = 0; j < num_balls; j++) 
     { 
      if (i == j) continue; 
      if (b[i].BallCollision(b[j]) == true) 
      { 
       run_prev.push_back(b[i]); 
      } 
     } 
    } 

    for (int i = 0; i < num_balls; i++) 
    { 
     b[i].DrawCircle(); 
    } 

    //xprev and yprev are the x and y values of the frame before for each circle 
    for (int i = 0; i < run_prev.size(); i++) 
    { 
     run_prev[i].x = run_prev[i].xprev; 
     run_prev[i].y = run_prev[i].yprev; 
    } 
+0

Sie sollten angeben, welche Typen Ihre Variablen sind, nur um zu wissen, ob wir Rundungsfehler oder andere Casting-Fehler ausschließen können. – vsz

+0

Ich verstehe nicht, warum Sie so normal berechnen. Sollen sie Einheitslänge haben? –

+0

Ich dachte, sie wären. Bitte korrigieren Sie mich, wo auch immer ich hingefallen bin. – Christian

Antwort

2
  1. Macht Kugeln kollidieren (Bewegungsvektor reflektieren) nur, wenn sie aufeinander sich bewegen. Verarbeiten Sie keine Kollision, wenn sie sich voneinander entfernen. Brechen Sie diese Regel, und sie werden zusammen geklebt werden.
  2. Wenn die Kollision bearbeitet wird, aktualisieren Sie beide Bälle gleichzeitig. Aktualisieren Sie nicht einen Ball nach dem anderen.
  3. Ihre Bewegungsvektoranpassung ist falsch. Bälle reflektieren nicht gegeneinander, weil sie sich mit unterschiedlichen Geschwindigkeiten bewegen können.

Richtige Bewegung Einstellung (unter der Annahme, Kugeln gleicher Masse) sollte so ähnlich aussehen:

pos1 and pos2 = positions; 
v1 and v2 are movement vector (speed); 
n is collision normal == normalize(pos1 - pos2); 
collisionSpeed = dot((v2-v1), n); 
collisionSpeed *= elasticy; (0.0..1.0); 
v1 = v1 - dot(v1, n); 
v2 = v2 - dot(v2, n); 
v1 -= scale(n, collisionSpeed * 0.5); 
v2 += scale(n, collisionSpeed * 0.5); 

die Formel zu verstehen, überprüfen Newtons Gesetz (Impulse insbesondere). Oder schau dir Chris Heckers Artikel über Spielphysik an.

+0

Danke. Wie testen Sie, ob sie sich aufeinander zu bewegen? – Christian

+0

@ vorbis5: Im obigen Beispiel das Vorzeichen von collisionSpeed ​​prüfen. – SigTerm

+0

Jeder half mir einen Haufen, also danke euch allen! – Christian

0

Ihr Weg zur Berechnung Jede Variable als Schwimmer

Die Funktionen deklariert wird. (x + b2.x)/2 muss nicht der Kollisionspunkt sein, wenn die Radien der Kugeln nicht gleich sind.

+0

Wie ich meine Simulation bisher eingerichtet habe, sind alle Radien gleich. – Christian

1

Es ist nicht klar, wie Sie diese Funktion aufrufen, aber ich denke, ich sehe das Problem.

Angenommen, Sie haben Ball ballA und Ball ballB, die im aktuellen Frame kollidieren, und dann führen Sie ballA.BallCollision(ballB).

Dadurch werden die Elementvariablen ballA aktualisiert und ein Frame zurück verschoben. Aber es aktualisiert nicht die Position oder Trajektorie von ballB.

Auch wenn Sie die Converse auch anrufen (ballB.BallCollision(ballA)), wird es die Kollision nicht erkennen, denn wenn Sie ballA.BallCollision(ballB) aufgerufen haben, bewegte es ballA zurück einen Rahmen.

+0

Sehr guter Einblick, ich werde meinen Code ein wenig bearbeiten und sehen, ob das mein Problem löst! – Christian

+0

Hmm, das Problem besteht immer noch. Wenn ein langsamer Kreis mit einem anderen kollidiert, bleiben beide zusammen und hören auf, sich zu bewegen, und das Zurückprallen scheint ein wenig aus oder so zu sein. Es ist komisch, ich habe mehr von meinem Code oben veröffentlicht und vielleicht kannst du ihn noch einmal ansehen. :) – Christian

1

Ich habe Ihren Code nicht im Detail betrachtet, aber es berücksichtigt nicht, dass diese Art von Kollision nur im Zentrum von Momentum Frames funktionieren kann. Nun, ich nehme an, deine Bälle sind gleich groß. Was Sie tun, ist den Durchschnitt der beiden Momente (oder Geschwindigkeiten, da sie die gleichen Massen haben) und subtrahieren diesen Durchschnitt von den Geschwindigkeiten. Führen Sie Ihre Berechnungen durch und addieren Sie den Durchschnittswert zurück. Here ist die Frage, die ich gestellt habe, die sich darauf beziehen kann.

+0

Super, ich werde das versuchen. – Christian

+0

Ok, das habe ich ausprobiert, und jetzt kleben und knallen die Kugeln noch zusammen, aber zumindest wenn sie kollidieren und kleben, werden sie nicht statisch. Ich denke, mein Hauptproblem ist hier das Festkleben der Bälle, wenn sie kollidieren. – Christian

+0

Haben Sie Code, der die Bälle so weit voneinander entfernt, dass sie sich nicht mehr schneiden? Und ich bin mir nicht ganz sicher, wie du deine Normalen berechnen sollst ... – slartibartfast