Python & Pygame: Ballkollision mit dem Inneren des Kreises

7

Ich mache ein Spiel, bei dem Bälle um die Innenseite eines viel größeren Kreises springen. Der größere Kreis bewegt sich nicht.

Hier ist der Code, den ich momentan für diese Kollisionen verwende:

%Vor%

Es basiert auf dem wunderbaren Tutorial von Peter Collingridge hier .

Die Kreis- und Kugelobjekte sind beide Klassen mit (x, y), Radius, Winkel und Geschwindigkeit.

Ich habe jedoch zwei Probleme mit dieser Methode:

  1. Der Ball springt von (was ich vermute) ist sein "Ankerpunkt", der in der oberen rechten Ecke des Kreises zu sein scheint.
  2. Wenn er mit den unteren 5% des Kreises kollidiert, springt er nicht hoch genug hoch und "sinkt" daher aus dem Bildschirm. Ich nehme an, dass dies daran liegt, dass der Sprung nicht hoch genug ist, um den Ball über seinen (nicht korrekt platzierten) "Ankerpunkt" zu bewegen?

Nachdem wir bereits mögliche Lösungen angeschaut haben, insbesondere "Fast circle collision detection" [Link gelöscht wegen Spam-Link-Limit], die zwar in Java die gleiche Methode verwenden, aber alle mit externen Kollisionen umgehen, während ich es bin schauend, einen Ball um das Innere eines Kreises springend.

Hier sind auch die Klassendefinitionen von Ball () und Circle ():

%Vor%

Vielen Dank im Voraus, Nathan

    
nchpmn 06.01.2011, 09:16
quelle

3 Antworten

12

Ich bin froh, dass dir mein Tutorial gefallen hat. Ich mag deine Variation, es sollte eigentlich einfacher sein.

Erstens, ich denke, dass Sie den Test für die Kollision ändern müssen:

%Vor%

Je größer die Ballgröße ist, desto kleiner kann der Abstand zwischen seinem Zentrum und dem Mittelpunkt des Kreises sein. Dadurch sollten die Bälle an der richtigen Stelle (innerhalb des Kreises) springen.

Dann denke ich, du musst nur die Zeichen für x und y tauschen und alles sollte funktionieren.

%Vor%

Um den Ball um die richtige Entfernung zu bewegen, können Sie die Überlappung berechnen:

%Vor%

Viel Glück

    
Peter Collingridge 07.01.2011, 20:28
quelle
12

Ohne Ihre Frage zu beantworten, möchte ich Ihre Implementierungsstrategie kommentieren und einen neuen Ansatz empfehlen. Sie stellen die Geschwindigkeit des Balls in Polarkoordinatenform dar, als ball.angle und ball.speed .

Ich denke, das wird Ihnen im Allgemeinen unangenehm sein. Zum Beispiel rufen Sie in Ihrem Kollisionscode atan2 auf, um den Vektor ( dx , dy ) in einen Winkel zu verwandeln, und dann rufen Sie sin und cos auf, um den Winkel wieder in einen Vektor zu verwandeln nochmal. (Sollten Sie jemals versuchen, Ihren Code auf drei Dimensionen zu verallgemeinern, finden Sie sich in einer Welt des Schmerzes wieder.) Wenn Sie also keine besonderen Anforderungen an Polarkoordinaten haben, empfehle ich Ihnen, das zu tun, was alle anderen tun, nämlich zu repräsentieren die Geschwindigkeit der Kugel in kartesischen Koordinaten als Vektor ( vx , vy ).

Ich empfehle auch, den physikalischen Ansatz von einem statischen ("ist Objekt A kollidiert derzeit mit Objekt B?") zu einem dynamischen ("wird Objekt A Kollision mit Objekt B während des nächsten Bewegungsschrittes? "). In einem statischen Physiksystem enden Sie oft mit Objekten, die sich am Ende eines Bewegungsschrittes schneiden, und dann müssen Sie herausfinden, wie sie sich am besten wieder trennen lassen, was schwer zu erreichen ist.

Wenn Sie beides tun, ist es einfach, den Ball ohne Trigonometrie zu werfen.

Schritt 1. Verwandeln Sie die Kreis- / Kreiskollision in eine Punkt- / Kreiskollision mit Minkowski-Zusatz :

Schritt 2. Betrachte ein Zeitsegment, in dem der Ball bei p = (px, py) beginnt und sich um v = (vx, vy) bewegt. Überschneidet es sich mit dem Kreis? Sie können dafür einen Standard-Liniensegment / -Kreis-Test verwenden, mit Ausnahme des Sinnes des Tests ist umgekehrt.

Schritt 3. Suchen Sie den Kollisionspunkt c = (cx, cy). Der Ball prallt vom Kreis auf die gleiche Weise ab, wie er von der Linie t an diesem Punkt tangential zum Kreis abprallt. Für einen Kreis, der am Ursprung zentriert ist, ist der Tangentenvektor gerade (-cy, cx) und ich bin mir sicher, dass Sie herausfinden können, wie Sie ihn für andere Kreise berechnen können.

In dieser Antwort erfahren Sie, wie Sie den neuen Pfad berechnen können der Ball basiert auf Reibungskoeffizienten und Restitution.

Schritt 4. Vergessen Sie nicht, dass der Ball noch etwas Abstand haben kann, um sich entlang des neuen Vektors w zu bewegen. Wenn der Zeitschritt groß genug ist oder die Geschwindigkeit hoch genug ist, kann er während desselben Zeitsegments erneut kollidieren.

    
Gareth Rees 07.01.2011 19:53
quelle
2

Die meisten Grafikpakete verwenden oben links als Start für Zeichnungscode. Wahrscheinlich wollen Sie 2 Koordinatensätze, die Sie kollidieren / bewegen / etc mit und die für das Zeichnen (x-Radius, y-Radius).

Auch, ohne zu viel darüber nachgedacht zu haben, sollte die Überprüfung für den Schnittpunkt distance + ball.size >= circle.size sein? Der Abstand der Kugeln vom Mittelpunkt plus Radius sollte kleiner sein als der Radius des Kreises, wenn ich das Setup richtig verstanden habe.

    
Per Fagrell 06.01.2011 09:30
quelle