Lektion 2 von 4Spiele programmieren
Spiele programmieren · Lektion 2 · 45 Minuten
Projekt: Fangspiel
Das lernst du
- Mit random Dinge an zufälligen Stellen erscheinen lassen
- Prüfen, ob sich zwei Rechtecke berühren (Kollision)
- Punkte zählen, Leben abziehen und das Spiel mit
spiel.ende()beenden
Fang die Sterne!
Von oben fallen Sterne. Unten fährt dein Korb hin und her. Jeder gefangene Stern bringt einen Punkt. Dafür brauchst du drei neue Dinge: Zufall, Kollision und einen Punktestand.
Zufall: Wo kommt der nächste Stern?
random.randint(0, 380) liefert eine zufällige ganze Zahl von 0 bis 380. Jeder Stern fällt so an einer anderen Stelle.
import random
from codelix import spiel
spiel.fenster(400, 300)
stern = {"x": 190, "y": 0}
def schritt():
stern["y"] = stern["y"] + 5
if stern["y"] > 300:
stern["y"] = 0
stern["x"] = random.randint(0, 380)
spiel.rechteck(stern["x"], stern["y"], 20, 20, "gold")
spiel.starten(schritt)Kollision: Berühren sich zwei Rechtecke?
Fängt der Korb den Stern? Das ist die wichtigste Frage in fast jedem Spiel. Zwei Rechtecke überlappen, wenn sie sich sowohl nach links-rechts als auch nach oben-unten überschneiden.
Nach links-rechts überschneiden sie sich, wenn beides stimmt:
afängt links vom rechten Rand vonban:a["x"] < b["x"] + b["b"]ahört rechts vom linken Rand vonbauf:a["x"] + a["b"] > b["x"]
Für oben-unten gilt dasselbe mit y und der Höhe h. Probier es mit zwei Rechtecken aus:
a = {"x": 0, "y": 0, "b": 50, "h": 30}
b = {"x": 40, "y": 20, "b": 30, "h": 30}
links_rechts = a["x"] < b["x"] + b["b"] and a["x"] + a["b"] > b["x"]
oben_unten = a["y"] < b["y"] + b["h"] and a["y"] + a["h"] > b["y"]
print("überschneiden sich links-rechts:", links_rechts)
print("überschneiden sich oben-unten:", oben_unten)
print("Kollision:", links_rechts and oben_unten)Ändere b["x"] auf 60. Dann ist links-rechts False, und es gibt keine Kollision mehr.
Leben und Spielende
Ein echtes Spiel ist irgendwann vorbei. Mit spiel.ende() hörst du auf. Das letzte Bild bleibt stehen. Hier fallen drei Sterne durch – dann ist Schluss:
from codelix import spiel
spiel.fenster(400, 300)
stern = {"y": 0}
stand = {"leben": 3}
def schritt():
stern["y"] = stern["y"] + 15
if stern["y"] > 300:
stern["y"] = 0
stand["leben"] = stand["leben"] - 1
spiel.rechteck(190, stern["y"], 20, 20, "gold")
spiel.text(10, 10, f"Leben: {stand['leben']}")
if stand["leben"] == 0:
spiel.text(120, 130, "Spiel vorbei!", "tomato", 28)
spiel.ende()
spiel.starten(schritt)
print("Danke fürs Spielen!")Nach spiel.ende() läuft dein Programm weiter. Deshalb erscheint am Ende noch der Text in der Ausgabe.
Weiterbauen: Wenn deine Aufgabe klappt, bau Leben ein: Fällt ein Stern unten durch, verlierst du eins. Bei 0 Leben ist das Spiel vorbei. Noch schwieriger: Mit jedem Punkt fallen die Sterne ein bisschen schneller.
Deine Aufgabe
Jetzt bist du dran
Schreib die Funktion trifft(a, b). Sie bekommt zwei Rechtecke als Dictionaries mit x, y, b (Breite) und h (Höhe). Sie gibt True zurück, wenn sich die beiden überlappen, sonst False. Berühren sich nur die Kanten, zählt das nicht. Nutze trifft dann in schritt(): Fängt der Korb den Stern, gibt es einen Punkt und der Stern startet wieder oben (y = 0).
import random
from codelix import spiel
spiel.fenster(400, 300)
korb = {"x": 170, "y": 270, "b": 60, "h": 20}
stern = {"x": 190, "y": 0, "b": 20, "h": 20}
stand = {"punkte": 0}
def trifft(a, b):
return False
def schritt():
if spiel.taste("links") and korb["x"] > 0:
korb["x"] = korb["x"] - 6
if spiel.taste("rechts") and korb["x"] < 340:
korb["x"] = korb["x"] + 6
stern["y"] = stern["y"] + 4
if stern["y"] > 300:
stern["y"] = 0
stern["x"] = random.randint(0, 380)
# Hier: Hat der Korb den Stern gefangen?
spiel.rechteck(korb["x"], korb["y"], korb["b"], korb["h"], "sienna")
spiel.rechteck(stern["x"], stern["y"], stern["b"], stern["h"], "gold")
spiel.text(10, 10, f"Punkte: {stand['punkte']}")
spiel.starten(schritt)- Denkanstoß
Zwei Rechtecke überlappen, wenn a links von b’s rechtem Rand anfängt UND a’s rechter Rand rechts von b’s linkem Rand liegt – und dasselbe für oben/unten.
- Welcher Befehl hilft?
Nimm
<und>(nicht<=und>=), dann zählen bloß berührende Kanten nicht. Alle vier Bedingungen müssen mitandverbunden sein.Schreib in
schritt():iftrifft(korb, stern): – dannstand["punkte"]erhöhen undstern["y"]=0 setzen.Den Punkt gibt es nur innerhalb von
iftrifft(korb, stern). - Lückencode – ergänze die ___
import random from codelix import spiel spiel.fenster(400, 300) korb = {"x": 170, "y": 270, "b": 60, "h": 20} stern = {"x": 190, "y": 0, "b": 20, "h": 20} stand = {"punkte": 0} def trifft(a, b): return ___ ___ def schritt(): if spiel.taste("links") and korb["x"] > 0: korb["x"] = korb["x"] - 6 if spiel.taste("rechts") and korb["x"] < 340: korb["x"] = korb["x"] + 6 stern["y"] = stern["y"] + 4 if stern["y"] > 300: stern["y"] = 0 stern["x"] = random.randint(0, 380) if ___: stand["punkte"] = ___ stern["y"] = 0 stern["x"] = random.randint(0, 380) spiel.rechteck(korb["x"], korb["y"], korb["b"], korb["h"], "sienna") spiel.rechteck(stern["x"], stern["y"], stern["b"], stern["h"], "gold") spiel.text(10, 10, f"Punkte: {stand['punkte']}") 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:
import random
from codelix import spiel
spiel.fenster(400, 300)
korb = {"x": 170, "y": 270, "b": 60, "h": 20}
stern = {"x": 190, "y": 0, "b": 20, "h": 20}
stand = {"punkte": 0}
def trifft(a, b):
return (a["x"] < b["x"] + b["b"] and a["x"] + a["b"] > b["x"]
and a["y"] < b["y"] + b["h"] and a["y"] + a["h"] > b["y"])
def schritt():
if spiel.taste("links") and korb["x"] > 0:
korb["x"] = korb["x"] - 6
if spiel.taste("rechts") and korb["x"] < 340:
korb["x"] = korb["x"] + 6
stern["y"] = stern["y"] + 4
if stern["y"] > 300:
stern["y"] = 0
stern["x"] = random.randint(0, 380)
if trifft(korb, stern):
stand["punkte"] = stand["punkte"] + 1
stern["y"] = 0
stern["x"] = random.randint(0, 380)
spiel.rechteck(korb["x"], korb["y"], korb["b"], korb["h"], "sienna")
spiel.rechteck(stern["x"], stern["y"], stern["b"], stern["h"], "gold")
spiel.text(10, 10, f"Punkte: {stand['punkte']}")
spiel.starten(schritt)