2D Physic Engine (Kreise mit Kollision) [NEUE FRAGE]

  • VB.NET

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von MindCode.

    2D Physic Engine (Kreise mit Kollision) [NEUE FRAGE]

    Hallo,

    ich bin mit meiner Kreiskollisionsabfrage weiter gekommen.
    Habe mich dann an den Mathe Unterricht erinnert und Vektoren benutzt für die
    Kollisionsreaktion.

    Allerdings hab ich immer noch einige Probleme und hoffe, dass ihr mir helfen könnt:

    1. - Die Kollisionsabfrage ist zu träge: Meine FPS sinkt je mehr Kreise ich habe
    und umso träger reagieren alle Kollisionen. Liegt wahrscheinlich daran, dass ich in einem
    Timer zwei For - Next Schleifen habe, aber ich wüsste jetzt keine andere Lösung :(

    2. - Die Kreise können nicht aufeinander liegen bleiben!
    2.2 - Wenn ein Kreis einen stehenden ganz vorsichtig berührt, springt der ruhende Kreis einfach zu schnell Weg!

    Sourcecode zum Download: 85.25.20.208/mindcode/CiCol.rar

    VB.NET-Quellcode

    1. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    2. Render.Refresh()
    3. For i = 0 To Ball_IndX
    4. If MoVinG(i) = 0 Or MoVinG(i) = 1 Then
    5. '// Moving Routines
    6. speedY(i) += gravity
    7. speedY(i) += ay(i)
    8. speedX(i) += ax(i)
    9. speedY(i) *= friction
    10. speedX(i) *= friction
    11. ball_loc_x(i) += speedX(i)
    12. ball_loc_y(i) += speedY(i)
    13. '// Collision with other Balls:
    14. bCenterX(i) = ball_loc_x(i) + Hsize
    15. bCenterY(i) = ball_loc_y(i) + Hsize
    16. If Ball_IndX > 0 Then
    17. For x = 0 To Ball_IndX
    18. a = bCenterX(i) - (ball_loc_x(x) + Hsize)
    19. b = bCenterY(i) - (ball_loc_y(x) + Hsize)
    20. If a = 0 Or b = 0 Then
    21. If b = 0 Then Abstand = Abs(a)
    22. If a = 0 Then Abstand = Abs(b)
    23. Else
    24. Abstand = Sqrt((Abs(a) ^ 2) + (Abs(b) ^ 2))
    25. End If
    26. Label11.Text = Abstand.ToString
    27. '// Collision Reaction (Vektors)
    28. If bGrav = 0 Then
    29. If Abs(Abstand) < BSize And Abstand <> 0 Then
    30. VeKY = (bCenterY(x) - bCenterY(i)) / 2
    31. VekX = (bCenterX(x) - bCenterX(i)) / 2
    32. speedX(i) -= (VekX * 0.1)
    33. speedY(i) -= (VeKY * 0.1)
    34. End If
    35. Else
    36. If Abs(Abstand) < 1000 And Abstand <> 0 Then
    37. VeKY = (bCenterY(x) - bCenterY(i)) / 2
    38. VekX = (bCenterX(x) - bCenterX(i)) / 2
    39. speedX(i) += ((VekX * 0.01))
    40. speedY(i) += ((VeKY * 0.01))
    41. End If
    42. End If
    43. Next
    44. End If
    45. '// Collision with Walls
    46. If ball_loc_y(i) > bottom_side Then
    47. ball_loc_y(i) = bottom_side
    48. speedY(i) *= -1
    49. ElseIf ball_loc_y(i) < 0 Then
    50. ball_loc_y(i) = 0
    51. speedY(i) *= -1
    52. End If
    53. If ball_loc_x(i) > right_side Then
    54. ball_loc_x(i) = right_side
    55. speedX(i) *= -1
    56. ElseIf ball_loc_x(i) < 0 Then
    57. ball_loc_x(i) = 0
    58. speedX(i) *= -1
    59. End If
    60. End If
    61. Next
    62. FPS = FPS + 1
    63. End Sub


    Könntet ihr mir da bitte helfen ?

    Liebe Grüße,
    Philipp

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MindCode“ ()

    Mach aus einem Kreis / einer Kugel eine eigene Klasse.
    Deren Objekte packst Du in eine List (Of MyCircle)
    In diese Klasse packst Du eine Funktion

    VB.NET-Quellcode

    1. Public Function Distance(ByVal MyCircle other)
    2. Return ABSTAND_ZWISCHEN_ME_UND_other
    3. End Function

    Dann musst Du nur jedes Objekt mit jedem anderen vergleichen und fertig.
    Der Code wird sehr übersichtlich und dann reden wir weiter.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Mach aus einem Kreis / einer Kugel eine eigene Klasse.
    Deren Objekte packst Du in eine List (Of MyCircle)
    In diese Klasse packst Du eine Funktion

    VB.NET-Quellcode

    1. Public Function Distance(ByVal MyCircle other)
    2. Return ABSTAND_ZWISCHEN_ME_UND_other
    3. End Function

    Dann musst Du nur jedes Objekt mit jedem anderen vergleichen und fertig.
    Der Code wird sehr übersichtlich und dann reden wir weiter.

    Mit Klassen hab ich es nicht so (noch nicht). Aber ich
    lese mich gerade in dieses Thema ein und werde es versuchen.
    Kannst du mir vielleicht noch paar weitere Infos zu deiner Idee
    geben damit ich, während ich mich mit Klassen beschäftige
    dann auch gleich praktisch mein Wissen anwenden kann?

    Verstehst? Eine kleine Zusammenfassung vom Ablauf her....
    (Vorher mit 64 FPS angefangen mit Backgroundworker mit 250 gestartet^^)
    Hier mein kleiner Test wo ich nur mal Testweise anstatt Timer 1 einen Backgroundworker genutzt habe:

    Bei einem Test mit 99 Bällen habe ich noch FPS von 80 erreicht beim ersten Test waren dies 7-8 fps.

    Ist bestimmt nicht die Beste lösung habe einfach den Code aus Timer ein in nen Backrgoundworker gepackt und nach jedem Durchgang(RunWorkerCompleted) Render.refresh und nochmals den Backrgoundworker angeworfen.

    Das bedeutet für dich: Mit mehren Threads arbeiten und vielleicht Code optimieren.


    MFG

    mcandy007 schrieb:

    Hier mein kleiner Test wo ich nur mal Testweise anstatt Timer 1 einen Backgroundworker genutzt habe:

    Bei einem Test mit 99 Bällen habe ich noch FPS von 80 erreicht beim ersten Test waren dies 7-8 fps.

    Ist bestimmt nicht die Beste lösung habe einfach den Code aus Timer ein in nen Backrgoundworker gepackt und nach jedem Durchgang(RunWorkerCompleted) Render.refresh und nochmals den Backrgoundworker angeworfen.

    Das bedeutet für dich: Mit mehren Threads arbeiten und vielleicht Code optimieren.


    MFG
    Wenn ich das so mache wie du beschrieben hast, dann sind die bewegungen ewigst schnell,
    gibt es dafür eine lösung? Und ziemlich oft friert alles einfach ein! Die Colorfunktion geht auch
    nicht mehr richtig, die bälle flackern dann bloß



    [EDIT: Habe das Problem gelößt indem ich im timer1 den backroundworker aufrufe.. meine fps bleibt zwar
    auf 64 c.a aber dafür kann ich mehrere bälle ohne lag einfügen jetzt

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „MindCode“ ()

    VB.NET-Quellcode

    1. Private lastTick As Integer = System.Environment.TickCount
    2. 'Beim bewegen der Bälle:
    3. position[X|Y] += (System.Environment.TickCount - lastTick) / geschwindigkeit * speed[X|Y]
    4. lastTick = System.Environment.TickCount


    bei geschwindigkeit einen beliebigen Wert einsetzen, umso größer der Wert, desto kleiner die Geschwindigkeit...
    Bei 1000 entspricht einer Bewegung von speed[X|Y] in einer Sekunde...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    Verbesserung des Ergebnisses der Kollision!

    Ich habe da jetzt was verändert.
    Und zwar habe ich jetzt diese Vektoraddition mal entfernt und dann
    die Physikalische Formeln für elastische stöße hergenommen...




    u1 und u2 sind ja die Geschwindigkeiten NACH dem Stoß.
    v1 und v2 sind die Geschwindigkeiten VOR dem Stoß.
    Als Masse habe ich jeweils einfach '1' genommen.

    Das ganze habe ich einmal für die X und einmal für die Y-Richtung
    berechnen lassen:

    VB.NET-Quellcode

    1. V1x = speedX(i)
    2. V1y = speedY(i)
    3. V2x = speedX(x)
    4. V2y = speedY(x)
    5. M1 = 1
    6. M2 = 1
    7. U1x = (M1 * V1x + M2 * (2 * V2x - V1x)) / (M1 + M2)
    8. U1y = (M1 * V1y + M2 * (2 * V2y - V1y)) / (M1 + M2)
    9. U2x = (M2 * V2x + M1 * (2 * V1x - V2x)) / (M2 + M1)
    10. U2y = (M2 * V2y + M1 * (2 * V1y - V2y)) / (M2 + M1)
    11. speedX(i) = U1x
    12. speedY(i) = U1y
    13. speedX(x) = U2x
    14. speedY(x) = U2y


    Jetzt habe ich aber folgendes Problem:
    Stößt eine Kugel eine andere NICHT Zentral an, sondern versetzt vom Mittelpunkt her
    dann rollt die eine Kugel einfach weiter in X richtung und nicht der Physik entsprechend,
    sagen wir mal Schräg nach oben, so wie man es erwarten würde!

    Warum?

    EDIT: Meine Vermutung ist: Ich brauche wohl dennoch Vektoren, weil es ein Zweidimensionaler Elastischer Stoß ist-
    Dummerweise leuchtet mir grad nicht ein wie ich das nun realisieren soll, sprich mir fehlt grad ein Ansatz, ich
    vergewaltige gerade schon wikipedia :D, könntet ihr mir da bitte helfen?

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „MindCode“ ()

    Habs geschafft. Für alle die es interessiert:

    VB.NET-Quellcode

    1. V1x = speedX(i)
    2. V1y = speedY(i)
    3. V2x = speedX(x)
    4. V2y = speedY(x)
    5. M1 = 1
    6. M2 = 1
    7. VeKY = (bCenterY(i) - bCenterY(x)) / 2
    8. VekX = (bCenterX(i) - bCenterX(x)) / 2
    9. LenG = Sqrt(VeKY * VeKY + VekX * VekX)
    10. VekX /= LenG
    11. VeKY /= LenG
    12. V1 = VekX * V1x + VeKY * V1y
    13. V2 = VekX * V2x + VeKY * V2y
    14. U1 = (M1 * V1 + M2 * V2 - M2 * (V1 - V2)) / (M1 + M2)
    15. U2 = (M1 * V1 + M2 * V2 - M1 * (V2 - V1)) / (M1 + M2)
    16. speedX(i) += (U1 - V1) * VekX
    17. speedY(i) += (U1 - V1) * VeKY
    18. speedX(x) += (U2 - V2) * VekX
    19. speedY(x) += (U2 - V2) * VeKY