2D Collision Response

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

Fetze

Betreff: 2D Collision Response

BeitragMo, März 20, 2006 21:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi, ich mal wieder ^^

Habe jetzt 4 1/2 Stunden an einer Function für Collision Response gesessen und ich kriegs einfach nicht hin. Bitte dringend um Hilfe. Folgendes:
2 Raumschiffe kollidieren. Ich habe den Punkt der Kollision, die Schwerpunkte (=Drehpunkte) der Raumschiffe, ihre Massen, ihre Drehbewegungen in Grad/Frame sowie ihre Bewegungsvektoren, deren Betrag in Pixel/Frame angegeben wird. Hier erstmal eine Skizze dazu:

www.fetzenet.de/skizze.png

Daraus will ich nun, wie in der Skizze zu sehen ist, für beide Schiffe errechnen, welche ->zusätzliche<- DrehBewegung und Bewegung sie jeweils durch die Kollision erhalten, die ich zu deren Variablen addieren kann, um ihre neue Bewegung zu erhalten

Das Problem ist... tja, gar nicht mal so was konkretes. Ich hab einfach keine Ahnung, wie ich das ganze berechnen soll. Ich habs jetzt wie gesagt ne ganze Weile versucht, aber ich komme nicht wirklich weiter. Ich wäre sehr dankbar, falls mir jemand einfach ein paar kommentierte Codezeilen mit Pseudovariablen geben könnte, die ich bei mir einbauen kann.
 

Dreamora

BeitragMo, März 20, 2006 21:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Schau mal auf normalen Physikseiten nach dem Drehimpulssatz oder wenn du ein Physikbuch hast, kannst du natürlich auch da drin schauen.
Es ist in der Physik allgemein immer so, dass wenn es um Stossreaktionen geht, der Impulssatz (oder der Drehimpulssatz) zum tragen kommt.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

Fetze

BeitragMo, März 20, 2006 21:27
Antworten mit Zitat
Benutzer-Profile anzeigen
So weit war ich schon. Da ich im Physikunterricht bisher nichtmal Vektoren wirklich hatte und so nur das grundlegendste davon kann, bzw. auch von Impulsen oder dergleichen bisher nicht mehr als den Namen gehört habe, bin ich so nicht viel weiter gekommen. :/
 

Dreamora

BeitragMo, März 20, 2006 21:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Da bleibt dir nicht viel anderes, als dir das Wissen anzueignen, das hinter Vektoren und Impuls (oder besser erst einmal Bewegung und Kraft) steckt.

Wird nicht so schwer, wenn du wirklich an der Materie interessiert bist.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

Fetze

BeitragMo, März 20, 2006 21:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Nunja, da gäbe es noch die Möglichkeit, jemand, der diese Formeln bereitsaufgestellt hat, postet sie hier. Das ist ein Aufwand von geschätzt einer Minute. Wohingegen ich wahrscheinlich weitere 5 Stunden benötigen würde. Wie wäre es also, wenn ihr so nett seid, mir das zu ersparen und ein paar Formeln zu posten, und sei es nur, damit ic hverstehe, wie das funktioniert? Rolling Eyes Wink

Oder, eine weitere ALternative:
Jemand erklärt mir Schritt für Schritt, wie ich das ganze selber zusammen bekomme.

Klar, zur Not muss ich dann eben wieder zum Physikbuch greifen. Aber ich denke nach 4 1/2 Stunden Arbeit darf ich es doch wohl mal wagen, um Hilfe zu bitten.
 

Dreamora

BeitragMo, März 20, 2006 22:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Gewiss.
Deswegen gab ich dir ja den Hinweis mit dem Impulssatz Smile

Dir fertigen Code und dergleichen zu liefern bringt nichts, da du ihn dann bei bedarf nicht anpassen kannst und ich denke, das ist in einem Spiel wo physik an verschiedenen orten einfliesst, zwingend notwendig, da du sonst unter Umstäden die Physik so einbaust, dass sie sich gegenseitig stört oder garnicht funktioniert.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

Fetze

BeitragMo, März 20, 2006 22:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, in meinem Fall würde das schon was bringen. Bin wirklich kein Physik-Phobiker und ich denke, ich verstehe die Formeln, wenn ich sie sehe, d.h. anpassen sollte kein Problem sein. Stören kann sich da ebenfalls nichts, weil ich diese Physik-Spielerei genau ein Mal im gesamten Spiel benötige, nämlich für Schiff-Schiff-Kollision ^^

Edit:
Hier übrigens das letzte, was ich zustande gebracht hab. Den Drehmoment hab ich bisher bewusst weggelassen, aber auch so scheint hier irgendwas nicht zu funktionieren. :/

Code: [AUSKLAPPEN]

'Impulsübertragung:
Local fImpMult:Float = 0.1 * fTimeMult
Local iLoop:Int
For iLoop = 0 To fColX.length - 1
   Local fColDist1:Float
   Local fColAngle1:Float
   Local fColX1:Float
   Local fColY1:Float
   Local fImpX2:Float
   Local fImpY2:Float
   Local fTransDist1:Float
   Local fTransX1:Float
   Local fTransY1:Float
   
   Local fColDist2:Float
   Local fColAngle2:Float
   Local fColX2:Float
   Local fColY2:Float
   Local fImpX1:Float
   Local fImpY1:Float
   Local fTransDist2:Float
   Local fTransX2:Float
   Local fTransY2:Float
   
   fColDist1 = Distance(shipPar.fX, shipPar.fY, shipPar.fX + fColX[iLoop], shipPar.fY + fColY[iLoop])
   fColAngle1 = Angle(shipPar.fX, shipPar.fY, shipPar.fX + fColX[iLoop], shipPar.fY + fColY[iLoop])
   fColX1 = Sin(fColAngle1)
   fColY1 = -Cos(fColAngle1)
   fImpX2 = (shipPar2.fXSpeed * shipPar2.fRealMass) * fImpMult
   fImpY2 = (shipPar2.fYSpeed * shipPar2.fRealMass) * fImpMult
   fTransDist1 = ((fColX1 * fImpX2) + (fColY1 * fImpY2))
   fTransX1 = fColX1 * fTransDist1
   fTransY1 = fColY1 * fTransDist1
   
   fColDist2 = Distance(shipPar2.fX, shipPar2.fY, shipPar.fX + fColX[iLoop], shipPar.fY + fColY[iLoop])
   fColAngle2 = Angle(shipPar2.fX, shipPar2.fY, shipPar.fX + fColX[iLoop], shipPar.fY + fColY[iLoop])
   fColX2 = Sin(fColAngle2)
   fColY2 = -Cos(fColAngle2)
   fImpX1 = (shipPar.fXSpeed * shipPar.fRealMass) * fImpMult
   fImpY1 = (shipPar.fYSpeed * shipPar.fRealMass) * fImpMult
   fTransDist2 = ((fColX2 * fImpX1) + (fColY2 * fImpY1))
   fTransX2 = fColX2 * fTransDist2
   fTransY2 = fColY2 * fTransDist2
   
   shipPar.fXSpeed:+ (fTransX1 / shipPar.fRealMass)
   shipPar.fYSpeed:+ (fTransY1 / shipPar.fRealMass)
   shipPar2.fXSpeed:- fImpX2
   shipPar2.fYSpeed:- fImpY2
   
   shipPar2.fXSpeed:+ (fTransX2 / shipPar2.fRealMass)
   shipPar2.fYSpeed:+ (fTransY2 / shipPar2.fRealMass)
   shipPar.fXSpeed:- fImpX1
   shipPar.fYSpeed:- fImpY1
Next


Ich gehe jeden Kollisionspunkt durch und versuche an jedem Kollisionspunkt zu bestimmen, welcher Teil des Impulses direkt zum Schwerpunkt des entsprechenden Schiffes zeigt und sich so direkt darauf auswirkt. Diesen Teil teile ich anschließend wieder durch die Masse des Empfängerschiffes und addiere ihn zu dessen Geschwindigkeitsvektor. Irgendwie scheint sich die Geschwindigkeit da drinnen jedoch zu potenzieren, denn mir fliegen dadurch die Schiffe teilweise übers halbe Spielfeld weg - weil ich sie sachte angestupst hab.


Edit2:
Okay, einen Fehler hab ich gefunden. Hab von der Geschwindigkeit des Impulsdonators den gesamten Impuls abgezogen, ohne zuvor wieder durch die Masse zu dividieren... aber irgendwas funktioniert immernoch nicht.
Die Vektoren der Schiffe fangen bei Kollision an, zu "zucken", in verschiedene Richtungen, nahezu willkürlich scheinend. Dabei sollten sie - bei einem Frontalzusammenstoß zwei ähnlicher Schiffe - rein theoretisch langsam und relativ gleichmäßig abnehmen. Tun sie aber nicht.

Code: [AUSKLAPPEN]


'Impulsübertragung:
Local fImpMult:Float = 0.1 * fTimeMult
Local iLoop:Int
For iLoop = 0 To fColX.length - 1
   Local fColDist1:Float
   Local fColAngle1:Float
   Local fColX1:Float
   Local fColY1:Float
   Local fImpX2:Float
   Local fImpY2:Float
   Local fTransDist1:Float
   Local fTransX1:Float
   Local fTransY1:Float
   
   Local fColDist2:Float
   Local fColAngle2:Float
   Local fColX2:Float
   Local fColY2:Float
   Local fImpX1:Float
   Local fImpY1:Float
   Local fTransDist2:Float
   Local fTransX2:Float
   Local fTransY2:Float
   
   fColDist1 = Distance(shipPar.fX, shipPar.fY, shipPar.fX + fColX[iLoop], shipPar.fY + fColY[iLoop])
   fColAngle1 = Angle(shipPar.fX, shipPar.fY, shipPar.fX + fColX[iLoop], shipPar.fY + fColY[iLoop])
   fColX1 = Sin(fColAngle1)
   fColY1 = -Cos(fColAngle1)
   fImpX2 = (shipPar2.fXSpeed * shipPar2.fRealMass) * fImpMult
   fImpY2 = (shipPar2.fYSpeed * shipPar2.fRealMass) * fImpMult
   fTransDist1 = ((fColX1 * fImpX2) + (fColY1 * fImpY2))
   fTransX1 = fColX1 * fTransDist1
   fTransY1 = fColY1 * fTransDist1
   
   fColDist2 = Distance(shipPar2.fX, shipPar2.fY, shipPar.fX + fColX[iLoop], shipPar.fY + fColY[iLoop])
   fColAngle2 = Angle(shipPar2.fX, shipPar2.fY, shipPar.fX + fColX[iLoop], shipPar.fY + fColY[iLoop])
   fColX2 = Sin(fColAngle2)
   fColY2 = -Cos(fColAngle2)
   fImpX1 = (shipPar.fXSpeed * shipPar.fRealMass) * fImpMult
   fImpY1 = (shipPar.fYSpeed * shipPar.fRealMass) * fImpMult
   fTransDist2 = ((fColX2 * fImpX1) + (fColY2 * fImpY1))
   fTransX2 = fColX2 * fTransDist2
   fTransY2 = fColY2 * fTransDist2
   
   shipPar.fXSpeed:+ (fTransX1 / shipPar.fRealMass)
   shipPar.fYSpeed:+ (fTransY1 / shipPar.fRealMass)
   shipPar2.fXSpeed:- (fImpX2 / shipPar2.fRealMass)
   shipPar2.fYSpeed:- (fImpY2 / shipPar2.fRealMass)
   
   shipPar2.fXSpeed:+ (fTransX2 / shipPar2.fRealMass)
   shipPar2.fYSpeed:+ (fTransY2 / shipPar2.fRealMass)
   shipPar.fXSpeed:- (fImpX1 / shipPar.fRealMass)
   shipPar.fYSpeed:- (fImpY1 / shipPar.fRealMass)
Next

regaa

BeitragDi, März 21, 2006 1:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich denke bei so komplizierten Sachen ist es von Vorteil einen ausführfähiges rar auszuliefern damit derjenige, der sich mit der Materie beschäftigen will, sofort anfangen kann im Code nach Fehlern zu suchen und nicht erst eine halbe Stunde eine bmx zusammenstellen und die dazugehörigen Objekte/Grafiken muss um dir weiter zu helfen.
UltraMixer Professional 3 - Download
QB,HTML,CSS,JS,PHP,SQL,>>B2D,B3D,BP,BlitzMax,C,C++,Java,C#,VB6 , C#, VB.Net

Fetze

BeitragDi, März 21, 2006 18:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe mich gerade ne Stunde an die Programmierung eines Tesgeländes gesetzt und schließlich mit dem Fazit aufgegeben, dass das ganze zu komplex ist, um mal eben ein Testgelände zu schreiben. :/
Und den gesamten Sourcecode meines Spiels kann ich euch schlecht geben. Wäre nett, wenn jemand auch so mal über den Code schauen würde. Smile

Hier, aktuelle Version. Funktioniert selektiv, d.h. in bestimmten Aufprallswinkeln oder bei bestimmten Aufprallsvektoren oder wasweisich. Jedenfalls funktioniert es, wenn man frontal gegen ein Raumschiff fliegt, aber nicht, wenn man sich von hinten annähert. Dann wird man aufgesogen und hindurch katapultiert.
Ich habe mal eine Funktion geschrieben, die die Krafteinwirkung berechnet. Der obere Teil ohne Funktion ist der, der bei Kollision ausgeführt wird und der Fehler wird wohl in der Methode "Push" stecken.

Code: [AUSKLAPPEN]

'Impulsübertragung:
Local fImpMult:Float = 1.0 * fTimeMult 'fTimeMult gleicht FPS-Schwankungen aus.
Local iLoop:Int
For iLoop = 0 To fColX.length - 1
   Local fImpX1:Float
   Local fImpY1:Float
   Local fImpX2:Float
   Local fImpY2:Float
   
   fImpX1 = (shipPar.fXSpeed * shipPar.fRealMass) * fImpMult
   fImpY1 = (shipPar.fYSpeed * shipPar.fRealMass) * fImpMult
   fImpX2 = (shipPar2.fXSpeed * shipPar2.fRealMass) * fImpMult
   fImpY2 = (shipPar2.fYSpeed * shipPar2.fRealMass) * fImpMult
   
   shipPar.Push(fColX[iLoop], fColY[iLoop], fImpX2, fImpY2)
   shipPar2.Push(shipPar.fX - shipPar2.fX + fColX[iLoop], shipPar.fY - shipPar2.fY + fColY[iLoop], fImpX1, fImpY1)
   
   shipPar.Push(fColX[iLoop], fColY[iLoop], -fImpX1, -fImpY1)
   shipPar2.Push(shipPar.fX - shipPar2.fX + fColX[iLoop], shipPar.fY - shipPar2.fY + fColY[iLoop], -fImpX2, -fImpY2)
Next

'Schubst das Schiff vom angegebenen Punkt aus mit dem angegebenen Impuls
Method Push:Byte(fParX:Float, fParY:Float, fParXImp:Float, fParYImp:Float)
   Local fAngleTemp:Float 'Winkel von Schiffs-Schwerpunkt zu angegebenem Kraftpunkt (Dem Punkt, an dem die Kraft wirkt)
   Local fNormPPVecX:Float 'Normalisierter Vektor von Schiffs-Schwerpunkt zu angegebenen Kraftpunkt
   Local fNormPPVecY:Float
   Local fTransVec:Float 'Länge des Translationsvektors (Des (Impuls-)Vektors, der in die Bewegung des Schwerpunktes eingerechnet wird)
   Local fTransVecX:Float 'Translationsvektor (Impuls)
   Local fTransVecY:Float
   
   'Winkel von Schwerpunkt des Schiffes zu Kraftpunkt (dem Punkt, an dem die Kraft wirkt)
   'berechnen
   fAngleTemp = Angle(fX, fY, fX + fParX, fY + fParY)
   'Normalisierten Vektor (Vektor der Länge 1) dorthin errechnen
   fNormPPVecX = Sin(fAngleTemp)
   fNormPPVecY = -Cos(fAngleTemp)
   'Per Skalarprodukt den Impulsvektor auf den normalisierten (Muss normalisiert sein!)
   'Schwerpunkt-Kraftpunkt-Vektor projizieren und so die Länge des Translationsvektors
   'errechnen.
   fTransVec = ((fNormPPVecX * fParXImp) + (fNormPPVecY * fParYImp))
   'Diese Länge mit dem normalisierten Schwerpunkt-Kraftpunkt-Vektor multiplizieren, um
   'daraus den Translationsvektor zu erhalten
   fTransVecX = fTransVec * fNormPPVecX
   fTransVecY = fTransVec * fNormPPVecY
   
   'Translationsvektor in Geschwindigkeit einrechnen. Durch Masse teilen, da es sich hier um
   'einen Impuls handelt.
   fXSpeed:+ (fTransVecX / fRealMass)
   fYSpeed:+ (fTransVecY / fRealMass)
   
   Return True
End Method
 

Dreamora

BeitragDi, März 21, 2006 18:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hätte dir auf die schnelle eine prinzipielle Idee anzubieten:

Voraussetzung:
- Du kennst den Kollisionspunkt
- Du hast einen Massemittelpunkt

Nun kannst du über Vektorenprojektion bestimmen, ob das andere Schiff von links oder rechts dagegen gescheppert ist.
Dazu muss der Bewegungsvektor des aufprallenden Schiffes auf die unitäre Richtung Massemittelpunkt - Kollisionspunkt projiziert werden ( uni_direction = (vecKollisionspunkt - vecMassemittelpunkt)/Länge des Vektors ). Dies erfolgt durch die Formel projectedVec = Skalarprodukt(uni_direction,Bewegungsvektor) (Das Skalarprodukt zweier Vektoren A,B zb ist A.x*B.x + A.y*B.y + A.z*B.z )

Nun kannst du 2 Punkte bestimmen:
- A = Kollisionspunkt - Bewegungsvektor
- B = Kollisionspunkt - projectedVec

Nun kannst du den Winkel bestimmen zwischen A und B bestimmen aus sicht des Massemittelpunktes und weisst in welche Richtung sich dein Schiff drehen muss.
Wie stark sich das Schiff drehen wird, hängt von der Normale ab welcher projectedVec und den Punkt A verbindet. Die Normalen ist dabei: Bewegungsvektor - projectedVec.

Mittels der Länge der Normale und der Richtung kannst du nun dein Schiff drehen.

Hoffe, das hilft dir. Natürlich kannst du, wenn du Masse nutzt auch den Impulsvektor anstatt dem Bewegungsvektor nutzen.

Habe deinen Code leider nur überflogen, kann dir diesbezüglich daher leider keine Hilfestellung bieten.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

Fetze

BeitragDi, März 21, 2006 19:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn ich dich richtig verstanden habe, hast du mir genau das vorgeschlagen, was ich da versuche, allerdings mehr im Bezug auf Drehung.

Mir meinem Code funktioniert das auch bereits einwandfrei, mit einer Ausnahme: Kollidiere ich im falschen Winkel, heben sich die errechneten Translationsvektoren eines Schiffes auf oder zeigen in die Falsche Richtung, sodass das kleinere Schiff mehr oder weniger in das größere eingesaugt wird. Ein paar Frames später wird es dann mit überhöhter Geschwindigkeit hinauskatapultiert.

Momentan suche ich die Ursache dafür, habe aber bisher noch keinen Ansatz :/
Trotzdem danke Smile

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group