Kreis in Pygame unterteilen

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
k-net
User
Beiträge: 22
Registriert: Donnerstag 22. Oktober 2020, 16:43

Samstag 19. Juni 2021, 12:52

Hallo,

ich habe in Pygame mit

Code: Alles auswählen

pygame.draw.circle(screen, white, (250, 250), 250, 1)
einen Kreis gezeichnet.
Ich möchte nun Linien durch diesen Kreis zeichnen. Und zwar acht Linien, die den Kreis in 16 gleichgroße Teile teilen.
Einige Linien, wie diese hier

Code: Alles auswählen

pygame.draw.aaline(screen, yellow, [0, 0], [500, 500])
(Das Fenster ist 500x500 groß) sind ja denkbar einfach. Aber ich kann mich natürlich nicht auf Dauer an den Abmessungen des Fensters orientieren, denn dann werden die Teile nicht gleich groß.

Kann mir jemand einen Tipp geben, wie ich das hinbekomme? Ich stelle mir vor, dass er die Werte für die Koordinaten der Linien aus einer Winkelangabe nimmt. Oder gibt es andere Wege diese zu berechnen. Ich habe schon gesucht und mit dem math modul und pi rumexperimentiert, komme aber nicht weiter.

Wäre toll, wenn jemand da eine Idee hätte.

Danke!
__deets__
User
Beiträge: 10294
Registriert: Mittwoch 14. Oktober 2015, 14:29

Samstag 19. Juni 2021, 13:27

Der Startpunkt ist immer das Zentrum. Und die x und y Koordinate ist cos(Winkel) * Radius und sin(Winkel) * Radius. Und der Winkel ist i * PI * 2 / 8, wobei i von 0 - 7 läuft.
k-net
User
Beiträge: 22
Registriert: Donnerstag 22. Oktober 2020, 16:43

Sonntag 20. Juni 2021, 19:09

Danke, das hat schonmal sehr geholfen.

Ich führe das in folgender Funktion aus:

Code: Alles auswählen

def lines():
    zahlenliste = range(0, 7)
    r = 250
    circle = pygame.draw.circle(screen, white, (250, 250), r, 1)
    for i in zahlenliste:
        w = i * math.pi * 2 / 4
        line_01 = pygame.draw.aaline(screen, yellow, [250, 250], [math.cos(w)*r, math.sin(w)*r])

Es ist aber nur ein Viertel des Kreises mit Linien befüllt. Wenn ich die Formel zu "w" wie von dir beschrieben übernehme, sind es zu viele Linien in dem Viertel, daher habe ich aus der 8 eine 4 gemacht. Aber irgendwas scheine ich zudem noch falsch zu machen... :?
Sirius3
User
Beiträge: 14998
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 20. Juni 2021, 19:23

Du läßt nur sieben statt acht Linien zeichnen. Und die Endpositionen sind liegen auf einem Kreis der um 0/0 zentriert ist, und nicht um 250/250. Mit den Rückgabewerten von aaline und circle machst Du nichts.
__deets__
User
Beiträge: 10294
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sonntag 20. Juni 2021, 19:41

Also meine Formel war schon korrekt. Wenn da was bei dir nicht gepasst hat, war es etwas anderes.

Code: Alles auswählen

>>> import math as m
>>> [i * m.pi * 2 / 8 for i in range(8)]
[0.0, 0.7853981633974483, 1.5707963267948966, 2.356194490192345, 3.141592653589793, 3.9269908169872414, 4.71238898038469, 5.497787143782138]
>>> rads = [i * m.pi * 2 / 8for i in range(8)]
>>> [m.degrees(r) for r in rads]
[0.0, 45.0, 90.0, 135.0, 180.0, 225.0, 270.0, 315.0]
Du musst aber auch den Startpunkt auf die errechnete Kreiskoordinate addieren. Denn das geht ja nur um den Nullpunkt.
k-net
User
Beiträge: 22
Registriert: Donnerstag 22. Oktober 2020, 16:43

Montag 21. Juni 2021, 16:57

Tut mir leid, was du da gemacht hast, verstehe ich nicht :|
__deets__
User
Beiträge: 10294
Registriert: Mittwoch 14. Oktober 2015, 14:29

Montag 21. Juni 2021, 17:56

Es zeigt einfach nur, das meine Formel korrekt war. Wenn du es nicht verstehst ist das nicht schlimm, dann musst du es eben glauben. Wobei das ja nur zwei for schleifen sind. Was daran ist so ungewöhnlich?

Wenn dein Ding also nicht richtig dargestellt wird, liegt es an etwas andrem.
k-net
User
Beiträge: 22
Registriert: Donnerstag 22. Oktober 2020, 16:43

Montag 21. Juni 2021, 18:10

Ich glaube dir das ganz sicher dass die Formel richtig ist, mein mathematisches Verständnis hinkt aber noch hinterher.
Nach diversen Tutorials über Kreisgleichungen und Umrechnung von Bogenmaß zu Winkelangaben etc... bin ich nur ein bisschen schlauer... nur ein bisschen.

Was genau meinst du mit
Denn das geht ja nur um den Nullpunkt.
?
__deets__
User
Beiträge: 10294
Registriert: Mittwoch 14. Oktober 2015, 14:29

Montag 21. Juni 2021, 18:37

Die Formel berechnet die Koordinaten um den Nullpunkt. Du malst deinen Kreis aber irgendwo. Also musst du den errechneten Punkt auf den Kreismittelpunkt addieren. Mal dir die Sache mal auf Kästchenpapier auf. Dann kommt das Verständnis einfacher.
k-net
User
Beiträge: 22
Registriert: Donnerstag 22. Oktober 2020, 16:43

Montag 21. Juni 2021, 21:42

Ah, okay... geschnallt.

aktuell sieht es so aus:

Code: Alles auswählen

line_01 = pygame.draw.aaline(screen, yellow, [250, 250], [math.cos(math.radians(0)) * r + 250, math.sin(math.radians(0)) * r + 250])
line_02 = pygame.draw.aaline(screen, yellow, [250, 250], [math.cos(math.radians(22.5)) * r + 250, math.sin(math.radians(22.5)) * r + 250])
usw... für jede Linie einzeln eben.

Es funktioniert. Ich werde das aber noch ändern. Ich musste mir das erstmal so herleiten, damit ich verstehe, was passiert und wie es funktioniert. Aus den einzelnen Linien mache ich aber noch eine Schleife und werde deine Formel wieder einbringen. Aber schonmal vielen Dank für die Hilfe!
__deets__
User
Beiträge: 10294
Registriert: Mittwoch 14. Oktober 2015, 14:29

Montag 21. Juni 2021, 22:22

Du musst wie Sirius3 schon sagte die Ergebnisse von aaline nicht an einen Namen binden. Und du solltest auch den Kreismittelpunkt nicht fest verdrahten. Sondern mit Variablen gestalten.
rogerb
User
Beiträge: 528
Registriert: Dienstag 26. November 2019, 23:24

Montag 21. Juni 2021, 22:42

@k-net,

kleiner Tipp, bzw. Herausforderung: Wenn du die Linien durch den Mittelpunkt kreuzen lässt, brauchst du sie nur vier mal zu zeichnen.

Code: Alles auswählen

# Nur ein Ausschnitt, kein fertiges Programm, angle, radius, center_x, center_y müssen natürlich vorher definiert sein
x_distance = math.cos(math.radians(angle)) * radius
y_distance = math.sin(math.radians(angle)) * radius
pygame.draw.aaline(screen, yellow, [center_x - x_distance, center_y - y_distance], [center_x + x_distance, center_y + y_distance])
k-net
User
Beiträge: 22
Registriert: Donnerstag 22. Oktober 2020, 16:43

Donnerstag 24. Juni 2021, 17:19

Hallo,

ich habe erneut ein kleines Rechenproblem.

Auf meinem Rad habe ich nun mehrere Kugeln, die sich die Speichen hin und her entlang bewegen.

Bild

Kugel 1 (links unten):

Code: Alles auswählen

    def draw_ball_01(self):
        ball_01 = pygame.draw.circle(screen, self.color, (self.ball_01_x, self.ball_01_y), self.radius, self.width)
        self.ball_01_x += self.speed
        if self.ball_01_x <= math.cos(math.radians(180)) * self.r + self.r:
            self.speed = 3
        elif self.ball_01_x >= math.cos(math.radians(0)) * self.r + self.r:
            self.speed = -3
Kugel 2 (darüber)

Code: Alles auswählen

    def draw_ball_02(self):
        ball_02 = pygame.draw.circle(screen, self.color, (self.ball_02_x, self.ball_02_y), self.radius, self.width)
        self.ball_02_x += self.speed 
        self.ball_02_y += self.speed
        if self.ball_02_x <= math.cos(math.radians(202.5)) * self.r + self.r:
            self.speed = 3
        elif self.ball_02_y >= math.sin(math.radians(22.5)) * self.r + self.r:
            self.speed = -3
Kugel 3 (über 2)

Code: Alles auswählen

    def draw_ball_03(self):
        ball_03 = pygame.draw.circle(screen, self.color, (self.ball_03_x, self.ball_03_y), self.radius, self.width)
        self.ball_03_x += self.speed / 1.414
        self.ball_03_y += self.speed / 1.414
        if self.ball_03_y <= math.sin(math.radians(225)) * self.r + self.r:
            self.speed = 3
        elif self.ball_03_x >= math.cos(math.radians(45)) * self.r + self.r:
            self.speed = -3
usw...

Das hin und her bewegen zwischen den Punkten und auf der Linie klappt gut. Kugel 1 und 3 und natürlich 5 laufen synchron und passieren gleichzeitig den Mittelpunkt. bei Kugel drei habe ich mich an dem Verhältnis einer Diagonalen zu den Seitenlängen eines Quadrates orientiert.

Aber Teufel auch für Kugel 2 und 4 bekomme ich das nicht hin :x
Kann mir bitte jemand da weiterhelfen?

Danke!
__deets__
User
Beiträge: 10294
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 24. Juni 2021, 17:48

Mir ist unklar was diese Kugeln tun sollen. Kannst du das mal beschreiben?

Was aber klar ist: du musst dringend Klassen, Argumente und Variablen benutzen. Statt mehrfach den nahezu gleichen Code zu kopieren. Das ist fehlerträchtig und kompliziert.
Sirius3
User
Beiträge: 14998
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 24. Juni 2021, 18:03

Statt für jeden Ball eine eigene Funktion zu schreiben, benutzt man eine passende Datenstruktur.
Wenn alle Bälle immer den gleichen Abstand zum Mittelpunkt haben sollen, ist das noch einfacher:

Code: Alles auswählen

    def draw_balls(self):
        for i in range(8):
            angle = i * math.pi / 4
            x = math.cos(angle) * self.ball_position + self.r
            y = math.sin(angle) * self.ball_position + self.r
            pygame.draw.circle(screen, self.color, (x, y), self.radius, self.width)
        self.ball_position -= 1
Antworten