2015-03-19 2 views
5

Ich habe ein Programm, wo Kreise in einander bouncen können. I folgte den Anweisungen von hier für die Vektoren zu drehen und die Größen Skalierung basierend auf der Kollisionswinkel: http://www.vobarian.com/collisions/2dcollisions2.pdfIch kann nicht finden, was mit dieser Circle-Bounce-Berechnung in Python falsch ist

ich diesen Code in Python geschrieben (der 0-Index der angibt x-Koordinate):

norm_vect = [(object2.pos[0] - object1.pos[0]), (object2.pos[1] - object1.pos[1])] 
unit = sqrt((norm_vect[0]**2) + (norm_vect[1]**2)) 
unit_vect = [float(norm_vect[0])/unit, float(norm_vect[1]) /unit] 
tan_vect = [-unit_vect[1], unit_vect[0]] 
vel1 = object1.vel 
vel2 = object2.vel 
vel1_norm = vel1[0] * unit_vect[0] + vel1[1] * unit_vect[1] 
vel1_tan = vel1[0] * tan_vect[0] + vel1[1] * tan_vect[1] 
vel2_norm = vel2[0] * unit_vect[0] + vel2[1] * unit_vect[1] 
vel2_tan = vel2[0] * tan_vect[0] + vel2[1] * tan_vect[1] 
new_vel1_norm = (vel1_norm * (object1.mass - object2.mass) + 2 * object2.mass * vel2_norm)/(object1.mass + object2.mass) 
new_vel2_norm = (vel2_norm * (object2.mass - object1.mass) + 2 * object1.mass * vel1_norm)/(object1.mass + object2.mass) 
new_norm_vect1 = [new_vel1_norm * float(unit_vect[0]), new_vel1_norm * float(unit_vect[1])] 
new_norm_vect2 = [new_vel2_norm * float(unit_vect[0]), new_vel2_norm * float(unit_vect[1])] 
new_tan_vect1 = [new_vel1_norm * float(tan_vect[0]), new_vel1_norm * float(tan_vect[1])] 
new_tan_vect2 = [new_vel2_norm * float(tan_vect[0]), new_vel2_norm * float(tan_vect[1])] 

# Now update the object's velocity 
object1.vel = [new_norm_vect1[0] + new_tan_vect1[0], + new_norm_vect1[1] + new_tan_vect1[1]] 
object2.vel = [new_norm_vect2[0] + new_tan_vect2[0], + new_norm_vect2[1] + new_tan_vect2[1]] 

Das Problem ist, dass es manchmal funktioniert, aber nicht zu anderen Zeiten. Kann mir jemand sagen warum? Es sieht so aus, als ob die Bälle im rechten Winkel kollidieren, dann tauschen ihre Ausgangsbahnen oder etwas anderes. Ich schrieb dies in Codeskulptur-Browser: http://www.codeskulptor.org/#user39_8q0Xdp3Y4s_2.py

Kann jemand darauf hinweisen, wo ich falsch gelaufen bin?

EDIT: Könnte es sein, dass ich die Kollision verarbeite? Hier sind die Schritte:

1) Draw the balls on the screen 
    2) Create set of unique pairs of collidable objects 
    3) For each ball, move the ball's position 1 frame forward according to the velocity: 
     ->1) Check to see if the ball is hitting a wall 
     ->2) For each pairset, if the ball in question is a member of the pair: 
      -->1) If distance between centers is less than sum of radii: 
        -->1) Calculate rebound trajectories 
        ---2) Find N such that position + rebound trajectory *N is out of collision zone 
+1

Was ist Objekt2.2 auf Ihrer letzten Zeile dort? –

+0

ein Tippfehler :) Ich habe den tatsächlichen Code ein wenig anders, um mit meinen Klassen zu interagieren, so musste ich hier einige neu schreiben. Verpasste diesen einen! – Apc0243

+0

Wenn Sie nur das Problem lösen wollen und es nicht von Grund auf lösen wollen, dann können Sie stattdessen einfach eine Physik-Engine verwenden. –

Antwort

2

Die Online-Simulation ist wirklich cool! Ich habe Ihren vollständigen Code nicht im Detail studiert, sondern nur den Ausschnitt, den Sie in Ihrer Frage gepostet haben. Aus einem kurzen Blick berechnen Sie korrekt die tangentialen und normalen Einheitsvektoren, die alten Normal- und Tangentialgeschwindigkeiten und die neue Normalgeschwindigkeit. Aber danach scheinst du dich ein wenig zu verlaufen. Wie in dem Dokument über die Kollisionen erläutert, ändern sich die Tangentialgeschwindigkeiten während der Kollision nicht, so dass es nicht notwendig ist, new_tan_vect1/2 zu berechnen. Ich verstehe auch nicht, warum Sie new_norm_vect1 berechnen, der normale Vektor ändert sich nicht während der Kollision.

Einige andere kleine Bemerkungen:

  • warum verwenden Sie float() ganzen Code? Dies wird normalerweise nicht benötigt. Wenn der Grund dafür ist, korrekte Ergebnisse für die Division zu erhalten, sollten Sie am Anfang Ihres Codes wirklich eine from __future__ import division hinzufügen, da Sie Python2 zu verwenden scheinen. Weitere Informationen finden Sie unter this old question.

  • Was Sie norm_vect nennen, ist eigentlich der un-normalisierte Normalvektor, und was Sie unit_vect nennen, ist der normalisierte Normaleinheitsvektor. Ich würde einfach beide norm_vect nennen, um den Unterschied zwischen normal und tangential deutlicher zu machen. Ein Einheitsvektor ist ein Vektor mit der Länge 1, daher ist die Verwendung für den normalen Vektor ein bisschen irreführend.

  • Wenn Sie planen, mehr dieser Art von Simulationen zu tun, sollten Sie überlegen, über numpy zu lernen. Dies ermöglicht Ihnen, vektorisierte Berechnungen zu schreiben, anstatt alle Gleichungen für x und y von Hand zu schreiben. Z.B. norm_vect = pos2 - pos1; norm_vect /= np.linalg.norm(norm_vect) oder object1.vel = norm_vect * new_vel1_norm + tang_vect * vel1_tang.

Ich würde Ihre Schnipsel schreiben mehr oder weniger sollte so (ungetestet Code):

from __future__ import division # move this to the top of your program 

# calculate normal and tangential unit vectors 
norm_vect = [(object2.pos[0] - object1.pos[0]), 
      (object2.pos[1] - object1.pos[1])] # stil un-normalized! 
norm_length = sqrt((norm_vect[0]**2) + (norm_vect[1]**2)) 
norm_vect = [norm_vect[0]/norm_length, 
      norm_vect[1]/norm_length] # do normalization 
tang_vect = [-norm_vect[1], norm_vect[0]] # rotate norm_vect by 90 degrees 

# normal and tangential velocities before collision 
vel1 = object1.vel 
vel2 = object2.vel 
vel1_norm = vel1[0] * norm_vect[0] + vel1[1] * norm_vect[1] 
vel1_tang = vel1[0] * tang_vect[0] + vel1[1] * tang_vect[1] 
vel2_norm = vel2[0] * norm_vect[0] + vel2[1] * norm_vect[1] 
vel2_tang = vel2[0] * tang_vect[0] + vel2[1] * tang_vect[1] 

# calculate velocities after collision 
new_vel1_norm = (vel1_norm * (object1.mass - object2.mass) 
    + 2 * object2.mass * vel2_norm)/(object1.mass + object2.mass) 
new_vel2_norm = (vel2_norm * (object2.mass - object1.mass) 
    + 2 * object1.mass * vel1_norm)/(object1.mass + object2.mass) 
# no need to calculate new_vel_tang, since it does not change 

# Now update the object's velocity 
object1.vel = [norm_vect[0] * new_vel1_norm + tang_vect[0] * vel1_tang, 
       norm_vect[1] * new_vel1_norm + tang_vect[1] * vel1_tang] 
object2.vel = [norm_vect[0] * new_vel2_norm + tang_vect[0] * vel2_tang, 
       norm_vect[1] * new_vel2_norm + tang_vect[1] * vel2_tang] 

ich einige der Variablen umbenannt, um es klar.

+0

Nun, ich habe das Gefühl, dass ich etwas in Python vermassele, weil sich die Geschwindigkeiten ändern, aber aus irgendeinem Grund wird der globale Klassenzustand nicht geändert. Siehe hier: http://www.codeskulptor.org/#user39_8q0Xdp3Y4s_3.py Könnte es sein, dass ich nicht von '__future__' importieren kann, weil Codeskulptur eine extrem eingeschränkte Implementierung von Python ist, nur damit die Leute die Grundlagen der Interaktion lernen können (SimpleGUI-Modul von den Professoren der Coursera Class zusammen mit Codeskulptor erstellt) – Apc0243

+0

http://www.codeskulptor.org/#user39_8q0Xdp3Y4s_4.py <- das ist sauberer, aber das Problem ist immer noch da und ich habe keine Ahnung warum. Ich denke es liegt daran, dass meine collision() Funktion von einer Klassenmethode aufgerufen wird. Ich bin nicht sicher, wie man die paarweise Kollisionsprüfung innerhalb der Klasse implementiert, weshalb ich es herauszog – Apc0243

+1

Mit Blick auf die Geschwindigkeiten, die Sie in der Kollisionsfunktion drucken, schien es, dass, wenn ein leichter Ball mit einem schweren Ball kollidierte die Geschwindigkeit kippte so wie sie sollte, aber dann direkt danach spiegelte sie sich wieder in die entgegengesetzte Richtung, so dass tatsächlich nichts passierte. Der Fehler war in Ihrer 'match_objects' Funktion, Sie addieren jedes Paar zweimal, einmal vorwärts und einmal rückwärts. Jede Kollision wird dann zweimal von Objekt 1 und für Objekt 2 erkannt, diese beiden löschen sich gegenseitig aus. Das scheint zu funktionieren (Bälle stecken manchmal fest): http://www.codeskultist.org/#user39_sV5TmqJSlAYGeOG.py –

Verwandte Themen