modified
This commit is contained in:
1 parent
e1c3d4dace
commit
6993048908
3 files changed
+143
-96
No files matched your search
+118
-60
@@ -3,40 +3,52 @@ import asyncio
|
||||
import turtle
|
||||
import math
|
||||
|
||||
# =====================================
|
||||
# BILDSCHIRM
|
||||
# =====================================
|
||||
# ==========================================
|
||||
# 1. BILDSCHIRM UND GLOBALE VARIABLEN
|
||||
# ==========================================
|
||||
|
||||
# Wir erstellen das Turtle-Fenster.
|
||||
screen = turtle.Screen()
|
||||
screen.setup(900, 650)
|
||||
screen.bgcolor("black")
|
||||
screen.setup(900, 650) # Fenstergröße
|
||||
screen.bgcolor("black") # Schwarzer Hintergrund
|
||||
screen.title("Rennbahn - Reeborg & Sophia")
|
||||
|
||||
# tracer(0) deaktiviert die automatische Bildschirmaktualisierung.
|
||||
# Wir aktualisieren den Bildschirm später selbst mit screen.update().
|
||||
screen.tracer(0)
|
||||
|
||||
# Die aktuelle Ampelphase wird in einer globalen Variable gespeichert.
|
||||
# OL_UR bedeutet: oben links und unten rechts haben Grün.
|
||||
# OR_UL bedeutet: oben rechts und unten links haben Grün.
|
||||
ampel_phase = "OL_UR"
|
||||
|
||||
# Sperre für die Kreuzung
|
||||
# Ein Lock verhindert, dass beide Autos gleichzeitig
|
||||
# die Kreuzung überqueren.
|
||||
kreuzung = asyncio.Lock()
|
||||
|
||||
|
||||
# =====================================
|
||||
# EINE ACHTERBAHN MIT ZWEI SPUREN
|
||||
# =====================================
|
||||
# ==========================================
|
||||
# 2. STRECKE ZEICHNEN
|
||||
# ==========================================
|
||||
|
||||
def position(t, spur):
|
||||
|
||||
# Grundform der Achterbahn
|
||||
# Mathematische Berechnung der Achterbahn (Unendlichkeitszeichen).
|
||||
x = 250 * math.sin(t)
|
||||
y = 145 * math.sin(2 * t)
|
||||
|
||||
# Senkrechter Versatz für die zwei Fahrspuren
|
||||
# Berechnung der Fahrtrichtung an der aktuellen Position.
|
||||
dx = 250 * math.cos(t)
|
||||
dy = 290 * math.cos(2 * t)
|
||||
|
||||
# Länge des Richtungsvektors berechnen.
|
||||
laenge = math.sqrt(dx**2 + dy**2)
|
||||
|
||||
# Die beiden Fahrspuren werden leicht versetzt.
|
||||
# spur = 1 oder -1 unterscheidet die beiden Fahrspuren.
|
||||
abstand = 10 * spur * math.sin(t)**2
|
||||
|
||||
# Versatz senkrecht zur Fahrtrichtung berechnen.
|
||||
x += abstand * (-dy / laenge)
|
||||
y += abstand * (dx / laenge)
|
||||
|
||||
@@ -45,20 +57,24 @@ def position(t, spur):
|
||||
|
||||
def zeichne_strecke():
|
||||
|
||||
# Eine zusätzliche Turtle zeichnet die Rennbahn.
|
||||
strecke = turtle.Turtle()
|
||||
strecke.hideturtle()
|
||||
strecke.speed(0)
|
||||
strecke.color("#777777")
|
||||
strecke.pensize(3)
|
||||
|
||||
# Beide Spuren derselben Achterbahn
|
||||
# Wir zeichnen die beiden Fahrspuren der Achterbahn.
|
||||
for spur in [-1, 1]:
|
||||
|
||||
strecke.penup()
|
||||
|
||||
# Die Strecke wird aus 1001 kleinen Punkten aufgebaut.
|
||||
for i in range(1001):
|
||||
|
||||
t = i * 2 * math.pi / 1000
|
||||
|
||||
# Berechnet die Koordinaten für den aktuellen Punkt.
|
||||
x, y = position(t, spur)
|
||||
|
||||
if i == 0:
|
||||
@@ -72,9 +88,9 @@ def zeichne_strecke():
|
||||
screen.update()
|
||||
|
||||
|
||||
# =====================================
|
||||
# AMPEL-ANZEIGE
|
||||
# =====================================
|
||||
# ==========================================
|
||||
# 3. AMPEL ANZEIGEN
|
||||
# ==========================================
|
||||
|
||||
anzeige = turtle.Turtle()
|
||||
anzeige.hideturtle()
|
||||
@@ -85,8 +101,10 @@ anzeige.goto(0, 260)
|
||||
|
||||
def zeige_ampel():
|
||||
|
||||
# Alte Ampelanzeige löschen.
|
||||
anzeige.clear()
|
||||
|
||||
# Aktuelle Ampelphase auf dem Bildschirm anzeigen.
|
||||
anzeige.write(
|
||||
"AMPEL: " + ampel_phase,
|
||||
align="center",
|
||||
@@ -96,113 +114,139 @@ def zeige_ampel():
|
||||
screen.update()
|
||||
|
||||
|
||||
# =====================================
|
||||
# AMPEL
|
||||
# =====================================
|
||||
# ==========================================
|
||||
# 4. AMPEL-COROUTINE
|
||||
# ==========================================
|
||||
|
||||
async def ampel():
|
||||
|
||||
global ampel_phase
|
||||
|
||||
# Die Ampel läuft dauerhaft.
|
||||
while True:
|
||||
|
||||
# Die Ampel wartet 5 Sekunden.
|
||||
# asyncio.sleep blockiert nicht die Event Loop.
|
||||
await asyncio.sleep(5)
|
||||
|
||||
# Die Ampel wartet, bis die Kreuzung frei ist.
|
||||
async with kreuzung:
|
||||
|
||||
# Zwischen den beiden Ampelphasen wechseln.
|
||||
if ampel_phase == "OL_UR":
|
||||
ampel_phase = "OR_UL"
|
||||
else:
|
||||
ampel_phase = "OL_UR"
|
||||
|
||||
print("🚦 Ampel schaltet auf:", ampel_phase)
|
||||
# Änderung in der Konsole protokollieren.
|
||||
print("Ampel schaltet auf:", ampel_phase)
|
||||
|
||||
# Neue Ampelphase grafisch anzeigen.
|
||||
zeige_ampel()
|
||||
|
||||
|
||||
# =====================================
|
||||
# AUTO BEWEGEN
|
||||
# =====================================
|
||||
# ==========================================
|
||||
# 5. AUTOS BEWEGEN
|
||||
# ==========================================
|
||||
|
||||
async def fahren(auto, start, ende, spur):
|
||||
|
||||
# Wir teilen die Bewegung in viele kleine Schritte.
|
||||
# Dadurch wird die Event Loop nicht blockiert.
|
||||
schritte = max(1, int(abs(ende - start) * 60))
|
||||
|
||||
for i in range(1, schritte + 1):
|
||||
|
||||
# Berechnung des nächsten Punktes auf der Strecke.
|
||||
t = start + (ende - start) * i / schritte
|
||||
|
||||
x, y = position(t, spur)
|
||||
|
||||
# Aktuelle Position des Autos speichern.
|
||||
alte_x, alte_y = auto.position()
|
||||
|
||||
# Fahrtrichtung aus den alten und neuen Koordinaten berechnen.
|
||||
winkel = math.degrees(
|
||||
math.atan2(y - alte_y, x - alte_x)
|
||||
)
|
||||
|
||||
# Turtle in Fahrtrichtung drehen.
|
||||
auto.setheading(winkel)
|
||||
|
||||
# Auto zum nächsten Punkt bewegen.
|
||||
auto.goto(x, y)
|
||||
|
||||
# Bildschirm aktualisieren.
|
||||
screen.update()
|
||||
|
||||
# Kurze Pause zwischen den Bewegungsschritten.
|
||||
await asyncio.sleep(0.02)
|
||||
|
||||
|
||||
# =====================================
|
||||
# KREUZUNG ÜBERQUEREN
|
||||
# =====================================
|
||||
# ==========================================
|
||||
# 6. KREUZUNG UND AMPEL ABFRAGEN
|
||||
# ==========================================
|
||||
|
||||
async def kreuzung_ueberqueren(
|
||||
auto, name, spur, t, gruen
|
||||
):
|
||||
async def kreuzung_ueberqueren(auto, name, spur, t, gruen):
|
||||
|
||||
# Bis kurz vor die Kreuzung fahren
|
||||
# Das Auto fährt zunächst bis kurz vor die Kreuzung.
|
||||
einstieg = t - 0.12
|
||||
|
||||
await fahren(auto, t - 0.5, einstieg, spur)
|
||||
|
||||
# Warten, bis die Ampel grün ist
|
||||
# Solange die Ampel rot ist, wartet das Auto.
|
||||
while True:
|
||||
|
||||
# Prüfen, ob die Ampel für dieses Auto grün ist.
|
||||
if ampel_phase == gruen:
|
||||
|
||||
# Kreuzung reservieren.
|
||||
await kreuzung.acquire()
|
||||
|
||||
# Nach dem Reservieren erneut prüfen,
|
||||
# ob die Ampel noch immer grün ist.
|
||||
if ampel_phase == gruen:
|
||||
break
|
||||
|
||||
# Falls nicht mehr grün, Lock wieder freigeben.
|
||||
kreuzung.release()
|
||||
|
||||
# Log-Meldung ausgeben.
|
||||
print(name, "wartet auf Grün...")
|
||||
|
||||
# Eine Sekunde warten und erneut prüfen.
|
||||
await asyncio.sleep(1)
|
||||
|
||||
print(name, "hat Grün und überquert die Kreuzung!")
|
||||
|
||||
try:
|
||||
|
||||
# Kreuzung in kleinen Schritten überqueren
|
||||
# Das Auto überquert die Kreuzung in kleinen Schritten.
|
||||
await fahren(auto, einstieg, t + 0.12, spur)
|
||||
|
||||
finally:
|
||||
|
||||
# Kreuzung nach der Überquerung wieder freigeben.
|
||||
kreuzung.release()
|
||||
|
||||
|
||||
# =====================================
|
||||
# REEBORG - BLAUES AUTO
|
||||
# =====================================
|
||||
# ==========================================
|
||||
# 7. REEBORG - BLAUES AUTO
|
||||
# ==========================================
|
||||
|
||||
async def reeborg():
|
||||
|
||||
# Neues Turtle-Objekt für Reeborg erstellen.
|
||||
auto = turtle.Turtle()
|
||||
auto.shape("turtle")
|
||||
auto.color("#008cff")
|
||||
auto.pensize(4)
|
||||
auto.speed(0)
|
||||
|
||||
# Reeborg bekommt seine Fahrspur.
|
||||
spur = 1
|
||||
|
||||
# Start oben links
|
||||
# Startposition oben links.
|
||||
t = -3 * math.pi / 4
|
||||
|
||||
x, y = position(t, spur)
|
||||
@@ -210,45 +254,50 @@ async def reeborg():
|
||||
auto.penup()
|
||||
auto.goto(x, y)
|
||||
|
||||
print("🔵 Reeborg startet!")
|
||||
print("Reeborg startet!")
|
||||
|
||||
# Das Auto fährt dauerhaft im Kreis.
|
||||
while True:
|
||||
|
||||
# Erste Kreuzung: OL -> UR
|
||||
# Erste Kreuzung: Reeborg benötigt OL_UR-Grün.
|
||||
await kreuzung_ueberqueren(
|
||||
auto, "🔵 Reeborg", spur, 0, "OL_UR"
|
||||
auto, "Reeborg", spur, 0, "OL_UR"
|
||||
)
|
||||
|
||||
# Rechte Kehre
|
||||
# Danach fährt Reeborg durch die rechte Kehre.
|
||||
await fahren(auto, 0.12, math.pi - 0.12, spur)
|
||||
|
||||
# Zweite Kreuzung: OR -> UL
|
||||
# Zweite Kreuzung: Hier benötigt Reeborg OR_UL-Grün.
|
||||
await kreuzung_ueberqueren(
|
||||
auto, "🔵 Reeborg", spur, math.pi, "OR_UL"
|
||||
auto, "Reeborg", spur, math.pi, "OR_UL"
|
||||
)
|
||||
|
||||
# Linke Kehre
|
||||
# Anschließend fährt Reeborg durch die linke Kehre.
|
||||
await fahren(
|
||||
auto, math.pi + 0.12,
|
||||
2 * math.pi - 0.12, spur
|
||||
auto,
|
||||
math.pi + 0.12,
|
||||
2 * math.pi - 0.12,
|
||||
spur
|
||||
)
|
||||
|
||||
|
||||
# =====================================
|
||||
# SOPHIA - ROTES AUTO
|
||||
# =====================================
|
||||
# ==========================================
|
||||
# 8. SOPHIA - ROTES AUTO
|
||||
# ==========================================
|
||||
|
||||
async def sophia():
|
||||
|
||||
# Neues Turtle-Objekt für Sophia erstellen.
|
||||
auto = turtle.Turtle()
|
||||
auto.shape("turtle")
|
||||
auto.color("#ff3030")
|
||||
auto.pensize(4)
|
||||
auto.speed(0)
|
||||
|
||||
# Sophia bekommt die andere Fahrspur.
|
||||
spur = -1
|
||||
|
||||
# Start unten links
|
||||
# Startposition unten links.
|
||||
t = -math.pi / 4
|
||||
|
||||
x, y = position(t, spur)
|
||||
@@ -256,39 +305,47 @@ async def sophia():
|
||||
auto.penup()
|
||||
auto.goto(x, y)
|
||||
|
||||
print("🔴 Sophia startet!")
|
||||
print("Sophia startet!")
|
||||
|
||||
# Auch Sophia fährt dauerhaft.
|
||||
while True:
|
||||
|
||||
# Erste Kreuzung: UL -> OR
|
||||
# Erste Kreuzung: Sophia benötigt OR_UL-Grün.
|
||||
await kreuzung_ueberqueren(
|
||||
auto, "🔴 Sophia", spur, 0, "OR_UL"
|
||||
auto, "Sophia", spur, 0, "OR_UL"
|
||||
)
|
||||
|
||||
# Rechte Kehre
|
||||
# Danach fährt Sophia durch die rechte Kehre.
|
||||
await fahren(auto, 0.12, math.pi - 0.12, spur)
|
||||
|
||||
# Zweite Kreuzung: UR -> OL
|
||||
# Zweite Kreuzung: Sophia benötigt OL_UR-Grün.
|
||||
await kreuzung_ueberqueren(
|
||||
auto, "🔴 Sophia", spur, math.pi, "OL_UR"
|
||||
auto, "Sophia", spur, math.pi, "OL_UR"
|
||||
)
|
||||
|
||||
# Linke Kehre
|
||||
# Anschließend fährt Sophia durch die linke Kehre.
|
||||
await fahren(
|
||||
auto, math.pi + 0.12,
|
||||
2 * math.pi - 0.12, spur
|
||||
auto,
|
||||
math.pi + 0.12,
|
||||
2 * math.pi - 0.12,
|
||||
spur
|
||||
)
|
||||
|
||||
|
||||
# =====================================
|
||||
# HAUPTPROGRAMM
|
||||
# =====================================
|
||||
# ==========================================
|
||||
# 9. HAUPTPROGRAMM
|
||||
# ==========================================
|
||||
|
||||
async def main():
|
||||
|
||||
# Zuerst die Rennbahn zeichnen.
|
||||
zeichne_strecke()
|
||||
|
||||
# Ampelanzeige initialisieren.
|
||||
zeige_ampel()
|
||||
|
||||
# Alle drei Coroutinen nebenläufig starten.
|
||||
# Das Programm wartet, bis alle Coroutinen beendet sind.
|
||||
await asyncio.gather(
|
||||
ampel(),
|
||||
reeborg(),
|
||||
@@ -296,4 +353,5 @@ async def main():
|
||||
)
|
||||
|
||||
|
||||
# Startet die Event Loop und damit das Programm.
|
||||
asyncio.run(main())
|
||||
+12
-18
@@ -1,18 +1,12 @@
|
||||
2026-11-12 13:12:02,794 [INFO] Rennbahn-Simulation gestartet.
|
||||
2026-11-12 13:12:02,810 [INFO] Reeborgs Blauer Flitzer nähert sich der Kreuzung.
|
||||
2026-11-12 13:12:02,841 [INFO] Sophias Rotes Auto nähert sich der Kreuzung.
|
||||
2026-11-12 13:12:04,087 [INFO] Reeborgs Blauer Flitzer hat Grün und überquert die Kreuzung.
|
||||
2026-11-12 13:12:04,103 [INFO] Sophias Rotes Auto steht an der Ampel (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:12:04,793 [INFO] Reeborgs Blauer Flitzer fährt in die Schleife.
|
||||
2026-11-12 13:12:05,135 [INFO] Sophias Rotes Auto steht an der Ampel (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:12:06,152 [INFO] Sophias Rotes Auto steht an der Ampel (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:12:07,181 [INFO] Sophias Rotes Auto steht an der Ampel (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:12:08,197 [INFO] Sophias Rotes Auto hat Grün und überquert die Kreuzung.
|
||||
2026-11-12 13:12:09,145 [INFO] Sophias Rotes Auto fährt in die Schleife.
|
||||
2026-11-12 13:12:09,364 [INFO] Reeborgs Blauer Flitzer fährt wieder zur Kreuzung.
|
||||
2026-11-12 13:12:10,988 [INFO] Reeborgs Blauer Flitzer hat wieder Grün und passiert die Kreuzung erneut.
|
||||
2026-11-12 13:12:11,943 [INFO] Reeborgs Blauer Flitzer fährt in die zweite Schleife.
|
||||
2026-11-12 13:12:13,732 [INFO] Sophias Rotes Auto fährt wieder zur Kreuzung.
|
||||
2026-11-12 13:12:15,370 [INFO] Sophias Rotes Auto hat wieder Grün und passiert die Kreuzung erneut.
|
||||
2026-11-12 13:12:16,320 [INFO] Sophias Rotes Auto fährt in die zweite Schleife.
|
||||
2026-11-12 13:12:16,536 [INFO] Reeborgs Blauer Flitzer nähert sich der Kreuzung.
|
||||
2026-11-12 13:32:51,294 [INFO] Rennbahn-Simulation gestartet.
|
||||
2026-11-12 13:32:51,309 [INFO] Reeborgs Blauer Flitzer nähert sich der Kreuzung.
|
||||
2026-11-12 13:32:51,340 [INFO] Sophias Rotes Auto nähert sich der Kreuzung.
|
||||
2026-11-12 13:32:52,526 [INFO] Reeborgs Blauer Flitzer hat Grün und überquert die Kreuzung.
|
||||
2026-11-12 13:32:52,558 [INFO] Sophias Rotes Auto steht an der Ampel (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:32:53,228 [INFO] Reeborgs Blauer Flitzer fährt in die Schleife.
|
||||
2026-11-12 13:32:53,572 [INFO] Sophias Rotes Auto steht an der Ampel (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:32:54,588 [INFO] Sophias Rotes Auto steht an der Ampel (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:32:55,600 [INFO] Sophias Rotes Auto steht an der Ampel (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:32:56,611 [INFO] Sophias Rotes Auto hat Grün und überquert die Kreuzung.
|
||||
2026-11-12 13:32:57,560 [INFO] Sophias Rotes Auto fährt in die Schleife.
|
||||
2026-11-12 13:32:57,778 [INFO] Reeborgs Blauer Flitzer fährt wieder zur Kreuzung.
|
||||
+13
-18
@@ -1,18 +1,13 @@
|
||||
2026-11-12 13:14:26,321 [INFO] Simulation gestartet.
|
||||
2026-11-12 13:14:26,336 [INFO] Reeborgs Blauer Flitzer nähert sich der Kreuzung.
|
||||
2026-11-12 13:14:26,368 [INFO] Sophias Rotes Auto nähert sich der Kreuzung.
|
||||
2026-11-12 13:14:27,550 [INFO] Reeborgs Blauer Flitzer hat Grün und überquert die Kreuzung.
|
||||
2026-11-12 13:14:27,580 [INFO] Sophias Rotes Auto steht an der Kreuzung (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:14:28,266 [INFO] Reeborgs Blauer Flitzer fährt durch die Kehre.
|
||||
2026-11-12 13:14:28,609 [INFO] Sophias Rotes Auto steht an der Kreuzung (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:14:29,623 [INFO] Sophias Rotes Auto steht an der Kreuzung (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:14:30,639 [INFO] Sophias Rotes Auto steht an der Kreuzung (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:14:31,651 [INFO] Sophias Rotes Auto hat Grün und überquert die Kreuzung.
|
||||
2026-11-12 13:14:32,617 [INFO] Sophias Rotes Auto fährt durch die Kehre.
|
||||
2026-11-12 13:14:32,834 [INFO] Reeborgs Blauer Flitzer fährt zur zweiten Kreuzung.
|
||||
2026-11-12 13:14:34,492 [INFO] Reeborgs Blauer Flitzer hat wieder Grün und passiert die zweite Kreuzung.
|
||||
2026-11-12 13:14:35,483 [INFO] Reeborgs Blauer Flitzer fährt durch die zweite Kehre.
|
||||
2026-11-12 13:14:37,296 [INFO] Sophias Rotes Auto fährt zur zweiten Kreuzung.
|
||||
2026-11-12 13:14:38,915 [INFO] Sophias Rotes Auto hat wieder Grün und passiert die zweite Kreuzung.
|
||||
2026-11-12 13:14:39,944 [INFO] Sophias Rotes Auto fährt durch die zweite Kehre.
|
||||
2026-11-12 13:14:40,159 [INFO] Reeborgs Blauer Flitzer nähert sich der Kreuzung.
|
||||
2026-11-12 13:32:19,198 [INFO] Simulation gestartet.
|
||||
2026-11-12 13:32:19,213 [INFO] Reeborgs Blauer Flitzer nähert sich der Kreuzung.
|
||||
2026-11-12 13:32:19,244 [INFO] Sophias Rotes Auto nähert sich der Kreuzung.
|
||||
2026-11-12 13:32:20,420 [INFO] Reeborgs Blauer Flitzer hat Grün und überquert die Kreuzung.
|
||||
2026-11-12 13:32:20,435 [INFO] Sophias Rotes Auto steht an der Kreuzung (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:32:21,119 [INFO] Reeborgs Blauer Flitzer fährt durch die Kehre.
|
||||
2026-11-12 13:32:21,463 [INFO] Sophias Rotes Auto steht an der Kreuzung (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:32:22,463 [INFO] Sophias Rotes Auto steht an der Kreuzung (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:32:23,495 [INFO] Sophias Rotes Auto steht an der Kreuzung (rot für OR-UL). Wartet 1 Sekunde...
|
||||
2026-11-12 13:32:24,510 [INFO] Sophias Rotes Auto hat Grün und überquert die Kreuzung.
|
||||
2026-11-12 13:32:25,446 [INFO] Sophias Rotes Auto fährt durch die Kehre.
|
||||
2026-11-12 13:32:25,666 [INFO] Reeborgs Blauer Flitzer fährt zur zweiten Kreuzung.
|
||||
2026-11-12 13:32:27,256 [INFO] Reeborgs Blauer Flitzer hat wieder Grün und passiert die zweite Kreuzung.
|
||||
Reference in new issue
Block a user