Lektion 4 von 4Spiele programmieren
Spiele programmieren · Lektion 4 · 60 Minuten
Projekt: Ballduell
Das lernst du
- Einen Ball mit Geschwindigkeit in x- und y-Richtung bewegen
- Den Ball an Wänden und Schlägern abprallen lassen
- Einen einfachen Computer-Gegner programmieren
Zwei Schläger, ein Ball
Beim Ballduell steht links und rechts je ein Schläger. Dazwischen fliegt ein Ball hin und her. Wer ihn durchlässt, gibt dem anderen einen Punkt. Du spielst rechts, links spielt der Computer.
Ein Ball mit Tempo
Bisher lief alles nur in eine Richtung. Jetzt bekommt der Ball zwei Geschwindigkeiten: dx für links-rechts und dy für oben-unten. In jedem Bild kommt beides dazu. Ein negatives dy heißt: nach oben.
from codelix import spiel
spiel.fenster(400, 300)
ball = {"x": 50, "y": 250, "dx": 3, "dy": -2}
def schritt():
ball["x"] = ball["x"] + ball["dx"]
ball["y"] = ball["y"] + ball["dy"]
spiel.kreis(ball["x"], ball["y"], 8, "orange")
spiel.starten(schritt)Der Ball fliegt schräg nach oben rechts – und dann aus dem Bild.
Abprallen
Prallt ein Ball an einer Wand ab, dreht sich eine Richtung um. An der Decke wird aus dy = -2 dann dy = 2. Das schreibst du so: ball["dy"] = -ball["dy"].
from codelix import spiel
spiel.fenster(400, 300)
ball = {"x": 50, "y": 150, "dx": 4, "dy": 3, "r": 10}
def schritt():
ball["x"] = ball["x"] + ball["dx"]
ball["y"] = ball["y"] + ball["dy"]
if ball["x"] - ball["r"] < 0 or ball["x"] + ball["r"] > 400:
ball["dx"] = -ball["dx"]
if ball["y"] - ball["r"] < 0 or ball["y"] + ball["r"] > 300:
ball["dy"] = -ball["dy"]
spiel.kreis(ball["x"], ball["y"], ball["r"], "orange")
spiel.starten(schritt)Achtung, Klebefalle: Ist der Ball nach dem Umdrehen noch ein Stück in der Wand, dreht er im nächsten Bild wieder um. Dann zittert er an der Wand entlang. Deshalb prüfst du in der Aufgabe auch die Richtung: Oben dreht er nur um, wenn er gerade nach oben fliegt.
Der Computer-Gegner
Wie spielt ein Computer? Ganz einfach: Liegt der Ball tiefer als die Mitte seines Schlägers, fährt er nach unten. Sonst nach oben. Weil er nur 3 Pixel pro Bild schafft, ist er schlagbar:
schlaeger = {"y": 120, "h": 60}
ball_y = 200
for bild in range(5):
mitte = schlaeger["y"] + schlaeger["h"] / 2
if mitte < ball_y:
schlaeger["y"] = schlaeger["y"] + 3
elif mitte > ball_y:
schlaeger["y"] = schlaeger["y"] - 3
print(f"Bild {bild}: Schläger bei y = {schlaeger['y']}")In der Aufgabe ist alles drumherum schon fertig: die Steuerung, der Gegner und die Punkte. Es fehlen nur die Funktionen für den Ball. Danach kannst du spielen – mit ↑ und ↓ oder mit den Knöpfen unter dem Spielfeld.
Weiterbauen: Zu zweit spielen: Steuere den linken Schläger mit
spiel.taste("w")undspiel.taste("s")statt mit dem Computer. Lass den Ball nach jedem Treffer ein bisschen schneller werden. Oder beende das Spiel mitspiel.ende(), sobald jemand 5 Punkte hat.
Deine Aufgabe
Jetzt bist du dran
Schreib die zwei Funktionen, die das Ballduell zum Laufen bringen. 1. ball_bewegen(ball, hoehe): Bewege den Ball um dx und dy. Stößt er danach oben (y - r < 0) oder unten (y + r > hoehe) an, dreh dy um – aber nur, wenn er sich gerade auf diese Wand zubewegt. 2. abprallen(ball, schlaeger): Berührt der Ball den Schläger, dreh dx um und gib True zurück, sonst False. Der Ball zählt dabei wie ein Quadrat von x - r bis x + r und von y - r bis y + r.
from codelix import spiel
spiel.fenster(400, 300)
ball = {"x": 200, "y": 150, "dx": 4, "dy": 3, "r": 8}
links = {"x": 10, "y": 120, "b": 10, "h": 60}
rechts = {"x": 380, "y": 120, "b": 10, "h": 60}
stand = {"links": 0, "rechts": 0}
def ball_bewegen(ball, hoehe):
pass
def abprallen(ball, schlaeger):
return False
def schritt():
# Du steuerst rechts mit ↑ und ↓, der Computer steuert links
if spiel.taste("oben") and rechts["y"] > 0:
rechts["y"] = rechts["y"] - 6
if spiel.taste("unten") and rechts["y"] < 240:
rechts["y"] = rechts["y"] + 6
if links["y"] + 30 < ball["y"]:
links["y"] = links["y"] + 3
elif links["y"] + 30 > ball["y"]:
links["y"] = links["y"] - 3
ball_bewegen(ball, 300)
if ball["dx"] < 0:
abprallen(ball, links)
else:
abprallen(ball, rechts)
if ball["x"] < 0 or ball["x"] > 400:
if ball["x"] < 0:
stand["rechts"] = stand["rechts"] + 1
else:
stand["links"] = stand["links"] + 1
ball["x"], ball["y"] = 200, 150
spiel.linie(200, 0, 200, 300, "#334", 2)
spiel.rechteck(links["x"], links["y"], links["b"], links["h"], "white")
spiel.rechteck(rechts["x"], rechts["y"], rechts["b"], rechts["h"], "cyan")
spiel.kreis(ball["x"], ball["y"], ball["r"], "orange")
spiel.text(160, 10, f"{stand['links']} : {stand['rechts']}", "white", 24)
spiel.starten(schritt)- Denkanstoß
ball["x"]=ball["x"]+ball["dx"]– und genauso für y mit dy. - Welcher Befehl hilft?
Umdrehen heißt:
ball["dy"]=-ball["dy"]. Oben stößt der Ball an, wennball["y"]-ball["r"]<0 ist.Dreh dy oben nur um, wenn dy
<0 ist (der Ball fliegt nach oben), und unten nur, wenn dy>0 ist.Das ist dieselbe Kollision wie beim Fangspiel – nur ist der Ball ein Quadrat von x − r bis x
+r. - Lückencode – ergänze die ___
from codelix import spiel spiel.fenster(400, 300) ball = {"x": 200, "y": 150, "dx": 4, "dy": 3, "r": 8} links = {"x": 10, "y": 120, "b": 10, "h": 60} rechts = {"x": 380, "y": 120, "b": 10, "h": 60} stand = {"links": 0, "rechts": 0} def ball_bewegen(ball, hoehe): ball["x"] = ___ ball["y"] = ___ if ___: ball["dy"] = ___ if ___: ball["dy"] = ___ def abprallen(ball, schlaeger): r = ___ ___ ___ ball["dx"] = ___ return ___ return False def schritt(): # Du steuerst rechts mit ↑ und ↓, der Computer steuert links if spiel.taste("oben") and rechts["y"] > 0: rechts["y"] = rechts["y"] - 6 if spiel.taste("unten") and rechts["y"] < 240: rechts["y"] = rechts["y"] + 6 if links["y"] + 30 < ball["y"]: links["y"] = links["y"] + 3 elif links["y"] + 30 > ball["y"]: links["y"] = links["y"] - 3 ball_bewegen(ball, 300) if ball["dx"] < 0: abprallen(ball, links) else: abprallen(ball, rechts) if ball["x"] < 0 or ball["x"] > 400: if ball["x"] < 0: stand["rechts"] = stand["rechts"] + 1 else: stand["links"] = stand["links"] + 1 ball["x"], ball["y"] = 200, 150 spiel.linie(200, 0, 200, 300, "#334", 2) spiel.rechteck(links["x"], links["y"], links["b"], links["h"], "white") spiel.rechteck(rechts["x"], rechts["y"], rechts["b"], rechts["h"], "cyan") spiel.kreis(ball["x"], ball["y"], ball["r"], "orange") spiel.text(160, 10, f"{stand['links']} : {stand['rechts']}", "white", 24) spiel.starten(schritt)
Ohne Hinweise gelöst gibt es einen ⭐ auf deiner Fortschrittsseite.
Lösung anzeigen🔒 Erst nach allen Hinweisen oder 2 Prüf-Versuchen
Versuch es erst selbst – aus Fehlern lernt man am meisten. Hier ist eine mögliche Lösung:
from codelix import spiel
spiel.fenster(400, 300)
ball = {"x": 200, "y": 150, "dx": 4, "dy": 3, "r": 8}
links = {"x": 10, "y": 120, "b": 10, "h": 60}
rechts = {"x": 380, "y": 120, "b": 10, "h": 60}
stand = {"links": 0, "rechts": 0}
def ball_bewegen(ball, hoehe):
ball["x"] = ball["x"] + ball["dx"]
ball["y"] = ball["y"] + ball["dy"]
if ball["y"] - ball["r"] < 0 and ball["dy"] < 0:
ball["dy"] = -ball["dy"]
if ball["y"] + ball["r"] > hoehe and ball["dy"] > 0:
ball["dy"] = -ball["dy"]
def abprallen(ball, schlaeger):
r = ball["r"]
if (ball["x"] - r < schlaeger["x"] + schlaeger["b"] and ball["x"] + r > schlaeger["x"]
and ball["y"] - r < schlaeger["y"] + schlaeger["h"] and ball["y"] + r > schlaeger["y"]):
ball["dx"] = -ball["dx"]
return True
return False
def schritt():
# Du steuerst rechts mit ↑ und ↓, der Computer steuert links
if spiel.taste("oben") and rechts["y"] > 0:
rechts["y"] = rechts["y"] - 6
if spiel.taste("unten") and rechts["y"] < 240:
rechts["y"] = rechts["y"] + 6
if links["y"] + 30 < ball["y"]:
links["y"] = links["y"] + 3
elif links["y"] + 30 > ball["y"]:
links["y"] = links["y"] - 3
ball_bewegen(ball, 300)
if ball["dx"] < 0:
abprallen(ball, links)
else:
abprallen(ball, rechts)
if ball["x"] < 0 or ball["x"] > 400:
if ball["x"] < 0:
stand["rechts"] = stand["rechts"] + 1
else:
stand["links"] = stand["links"] + 1
ball["x"], ball["y"] = 200, 150
spiel.linie(200, 0, 200, 300, "#334", 2)
spiel.rechteck(links["x"], links["y"], links["b"], links["h"], "white")
spiel.rechteck(rechts["x"], rechts["y"], rechts["b"], rechts["h"], "cyan")
spiel.kreis(ball["x"], ball["y"], ball["r"], "orange")
spiel.text(160, 10, f"{stand['links']} : {stand['rechts']}", "white", 24)
spiel.starten(schritt)