Dein erstes eigenes Programm
Du startest mit dem Minimal-Gerüst aus dem Tutorial und machst es zu deinem. Eigene Tastenbelegung, eigenes HUD, eigene Ausgabe nach dem Spiel.
schritt_01.py und liegt in einem Ordner schritt_01/
(nicht lunarlander.py — das ist die API!).
Die erste Zeile deines Programms enthält deinen Namen als Kommentar:
# Name: [Vorname Nachname]
# Name: [Vorname Nachname] ← deinen echten Namen eintragen!
from lunarlander import *
# ════════════════════════════════════════════════════════════
# DEFINITIONSBEREICH
# ════════════════════════════════════════════════════════════
# ── Steuerung (Hook) ────────────────────────────────────────────────────
def myHandleKey(keyCode):
# TODO: Wähle deine Tasten. Beispiele:
# Pfeiltasten: hoch=38, links=37, rechts=39
# WASD: W=87, A=65, D=68
pass
# ════════════════════════════════════════════════════════════
# SPIELEINSTELLUNGEN
# ════════════════════════════════════════════════════════════
# ── HUD ───────────────────────────────────────────────────────────────────
# erlaubt: "fuel", "vSpeed", "hSpeed", "height", "x",
# "gravity", "rotation", "scale", "paused", "frameTime"
setHudItems(["fuel", "vSpeed", "height"]) # TODO: nach Wunsch anpassen
# ════════════════════════════════════════════════════════════
# SPIELSTART
# ════════════════════════════════════════════════════════════
init(myHandleKey)
print("Mein LunarLander — viel Erfolg!") # TODO: eigene Startmeldung
start()
# ════════════════════════════════════════════════════════════
# AUSWERTUNG (läuft erst nach Spielende)
# ════════════════════════════════════════════════════════════
# TODO: Gib aus ob du gelandet oder abgestürzt bist.
# TODO: Gib aus wie viel Treibstoff du verbraucht hast.
# Tipp: Es gibt eine API-Funktion die den aktuellen Treibstoff liefert.
Wenn dein Programm läuft, erweitere es:
- Füge
setFuel(150)vorinit()ein — wird es schwieriger? Welchen Wert liefertgetFuel()nach dem Spielende? - Probiere
setGravity(0.08)— was ändert sich am Flugverhalten? - Gib nach dem Spielende auch die Horizontalgeschwindigkeit aus — welche API-Funktion brauchst du dafür?
Am Ende von Schritt 1 hast du:
- Eine funktionierende Steuerung mit selbst gewählten Tasten
- Ein HUD mit mindestens 3 sinnvollen Werten
- Eine Ausgabe nach Spielende: Ergebnis (gelandet/abgestürzt) + verbleibender Treibstoff
- Deine Datei
schritt_01.pymit deinem Namen in Zeile 1
setCustomDrawer() — Hook
Der gelbe Standard-Lander verschwindet. Du zeichnest deinen eigenen — mit eigenem Design, eigener Farbe, eigenem Charakter.
Bevor du anfängst: kopiere deinen schritt_01-Ordner,
benenne die Kopie in schritt_02 um und arbeite ab jetzt
nur in diesem neuen Ordner weiter.
So hast du immer eine funktionierende Version des vorherigen Schritts — falls etwas schiefgeht, kannst du zurück. Diese Methode nutzt du für jeden weiteren Schritt.
Dein Ordner-Schema: schritt_01/ → schritt_02/ → schritt_03/ → …
Zeichne deinen Lander auf Papier, bevor du Code schreibst.
Trage Koordinaten ein: der Mittelpunkt ist (0, 0).
Positive Y-Werte sind oben, negative unten.
Pflichtbestandteile:
- Ein erkennbarer Rumpf (Rechteck, Kapsel, Polygon …)
- Eine erkennbare Landebasis (Beine, Stützen, Kufen …)
- Ein individuelles Merkmal — Cockpit, Antenne, Flagge, Aufschrift …
- Mindestens zwei Farben
| Befehl | Wirkung |
|---|---|
| penUp() / penDown() | Stift heben / setzen |
| setPos(x, y) | Teleportieren — nie Linie |
| moveTo(x, y) | Linie zeichnen wenn penDown |
| setPenColor(f) | Farbe als String |
| setPenWidth(b) | Stiftbreite |
| dot(d) | Ausgefüllter Kreis |
Empfehlung:
Im Custom Drawer mit Koordinaten zeichnen —
setPos() und moveTo() mit (x,y)-Angaben
sind am einfachsten zu lesen und zu debuggen.
forward() und setHeading() funktionieren
ebenfalls, erfordern aber etwas mehr Vorstellungsvermögen.
from lunarlander import *
# ════════════════════════════════════════════════════════════
# DEFINITIONSBEREICH
# ════════════════════════════════════════════════════════════
# ── Eigener Lander (Hook) ───────────────────────────────────────────────
def meinLander():
# TODO: Dein Design — nur setPos() und moveTo() für Linien verwenden!
# Mindestens: Rumpf, Beine, 1 Merkmal, 2 Farben
pass
# ── Steuerung (Hook) ────────────────────────────────────────────────────
def myHandleKey(keyCode):
pass # TODO: deine Tastenbelegung aus Schritt 1
# ════════════════════════════════════════════════════════════
# SPIELEINSTELLUNGEN
# ════════════════════════════════════════════════════════════
# ── Lander ────────────────────────────────────────────────────────────────
# TODO: CollisionProbe anpassen wenn nötig (south = tiefster Punkt deines Landers)
# setCollisionProbe(0, 0, 24, 0)
# ── HUD ───────────────────────────────────────────────────────────────────
setHudItems(["fuel", "vSpeed", "height"])
# ════════════════════════════════════════════════════════════
# HOOKS ANMELDEN
# ════════════════════════════════════════════════════════════
setCustomDrawer(meinLander)
# ════════════════════════════════════════════════════════════
# SPIELSTART
# ════════════════════════════════════════════════════════════
init(myHandleKey)
start()
# ════════════════════════════════════════════════════════════
# AUSWERTUNG
# ════════════════════════════════════════════════════════════
if hasLanded():
print("Gelandet! Treibstoff:", getFuel())
elif hasCrashed():
print("Absturz!")
setPos() teleportiert immer ohne Linie — auch bei penDown().
Für Linien immer moveTo() verwenden — nicht forward().
Zum Debuggen: setShowCollisionProbe(True) zeigt den Kollisionspunkt als roten Punkt.
Am Ende von Schritt 2 hast du:
- Einen Lander mit Rumpf, Landebasis und individuellem Merkmal
- Mindestens zwei verschiedene Farben
- Eine korrekt gesetzte CollisionProbe (sichtbar mit
setShowCollisionProbe(True)überprüft)
Terrain, Landezone, Schwerkraft
Dein Lander braucht eine Welt. Du gestaltest das Gelände, legst fest wo gelandet werden darf — und entscheidest wie viel Schwerkraft herrscht.
Das Terrain ist eine Liste von Höhenwerten — von links nach rechts gelesen. Mindestens 8 Werte. Größere Zahlen = höheres Gelände.
Die Landezonen werden als Index-Bereich angegeben — Index 0 ist ganz links. Flache Bereiche im Terrain eignen sich als Landeplatz.
| Funktion | Wirkung | Standard |
|---|---|---|
| setTerrain([...]) | Geländeprofil setzen | [30,60,90,70,20,20,20,20,55,100,120,80,40] |
| setLandingZone(start, ende) | Einen Landeplatz | Indizes 4–7 ← die gelben Werte oben |
| setLandingZones([(startIndex1, endIndex1), (startIndex2, endIndex2)]) | Mehrere Landeplätze | – |
| setGravity(wert) | Schwerkraft | 0.15 |
| setFuel(menge) | Starttreibstoff | 200 |
Die gelb markierten Werte in der Terrain-Liste (Index 4–7) bilden den flachen Bereich — das ist die Landezone.
from lunarlander import *
# ════════════════════════════════════════════════════════════
# DEFINITIONSBEREICH
# ════════════════════════════════════════════════════════════
# ── Eigener Lander (Hook) ───────────────────────────────────────────────
def meinLander():
pass # TODO: dein Design aus Schritt 2
# ── Steuerung (Hook) ────────────────────────────────────────────────────
def myHandleKey(keyCode):
pass # TODO: deine Tastenbelegung
# ════════════════════════════════════════════════════════════
# SPIELEINSTELLUNGEN
# ════════════════════════════════════════════════════════════
# ── Lander ────────────────────────────────────────────────────────────────
# setCollisionProbe(0, 0, 24, 0) # TODO: aus Schritt 2 übernehmen
# ── Welt ──────────────────────────────────────────────────────────────────
# TODO: Gestalte dein Terrain. Flache Bereiche = mögliche Landeplätze.
setTerrain([30, 80, 40, 10, 10, 10, 60, 90, 50, 20]) # TODO: eigenes Terrain
# TODO: Setze deinen Landeplatz (Index des flachen Bereichs)
setLandingZone(3, 5)
# TODO: Wähle eine Schwerkraft (0.05 = leicht, 0.25 = schwer)
setGravity(0.15)
# TODO: Wie viel Treibstoff bekommt der Spieler?
setFuel(200)
# ── HUD ───────────────────────────────────────────────────────────────────
setHudItems(["fuel", "vSpeed", "height", "gravity"])
# ════════════════════════════════════════════════════════════
# HOOKS ANMELDEN
# ════════════════════════════════════════════════════════════
setCustomDrawer(meinLander)
# ════════════════════════════════════════════════════════════
# SPIELSTART
# ════════════════════════════════════════════════════════════
init(myHandleKey)
start()
# ════════════════════════════════════════════════════════════
# AUSWERTUNG
# ════════════════════════════════════════════════════════════
if hasLanded():
print("Gelandet! Treibstoff:", getFuel())
elif hasCrashed():
print("Absturz!")
Füge am Ende deiner schritt_03.py diese Kommentare ein und beantworte sie:
# ════════════════════════════════════════════════════════════
# WELT-BESCHREIBUNG
# ════════════════════════════════════════════════════════════
# Thema meiner Welt (Mond, Mars, Asteroid, …):
# [deine Antwort]
#
# Begründung meiner Schwerkraft (gewählt: ___):
# [warum genau dieser Wert?]
#
# Schwierigkeitsgrad — und ist das so gewollt?
# [deine Antwort]
Mehrere Landeplätze mit setLandingZones([[3,5],[8,10]]).
Der erste Landeplatz kann leichter sein (breiter, flacher),
ein zweiter schwieriger (schmal, schwer zugänglich).
Am Ende von Schritt 3 hast du:
- Ein eigenes Terrain mit mindestens einem sinnvoll platzierten Landeplatz
- Eine Schwerkraft die zur Welt passt
- Die drei Welt-Kommentare am Ende der
schritt_03.pyausgefüllt - Alles gespeichert im Ordner
schritt_03/
setUpdateFunction() — Hook
Das Spiel bekommt eine Stimme. Warnungen, Hinweise, ein einfaches Punktesystem — alles läuft in deiner Update-Funktion, die jeden Frame aufgerufen wird.
Variablen die du in einer Funktion veränderst, müssen mit global
deklariert werden. Nur lesen geht ohne global.
Eigene Hilfsfunktionen kannst du einfach per Name aufrufen —
auch aus Hooks heraus. Die global-Regel gilt dort genauso.
from lunarlander import *
# ════════════════════════════════════════════════════════════
# DEFINITIONSBEREICH
# ════════════════════════════════════════════════════════════
# ── Spielzustand (globale Variablen) ─────────────────────────────────────
punkte = 1000
warnungTreibstoff = False
warnungSpeed = False
# ── Hilfsfunktionen ──────────────────────────────────────────────────────
def zeigeWarnung(text):
print("*** WARNUNG:", text, "***")
# ── Eigener Lander (Hook) ───────────────────────────────────────────────
def meinLander():
pass # TODO: dein Design
# ── Update-Logik (Hook) ─────────────────────────────────────────────────
def meinUpdate():
global punkte, warnungTreibstoff, warnungSpeed
punkte = punkte - 1 # Zeitdruck: 1 Punkt pro Frame abziehen
# TODO: Warnung 1 — einmalig wenn Treibstoff unter 50 sinkt
# Nutze zeigeWarnung() und warnungTreibstoff als Merker
# TODO: Warnung 2 — einmalig wenn Höhe unter 60 und vSpeed über 3.5
# TODO (Bonus): Hinweis wenn isOverLandingZone() — aber nur alle 30 Frames
# ── Steuerung (Hook) ────────────────────────────────────────────────────
def myHandleKey(keyCode):
pass # TODO: deine Tastenbelegung
# ════════════════════════════════════════════════════════════
# SPIELEINSTELLUNGEN
# ════════════════════════════════════════════════════════════
# ── Lander ────────────────────────────────────────────────────────────────
# setCollisionProbe(0, 0, 24, 0) # TODO: aus Schritt 2 übernehmen
# ── Welt ──────────────────────────────────────────────────────────────────
# TODO: setTerrain, setLandingZone, setGravity, setFuel aus Schritt 3 einfügen
# ── HUD ───────────────────────────────────────────────────────────────────
setHudItems(["fuel", "vSpeed", "height"])
# ════════════════════════════════════════════════════════════
# HOOKS ANMELDEN
# ════════════════════════════════════════════════════════════
setCustomDrawer(meinLander)
setUpdateFunction(meinUpdate)
# ════════════════════════════════════════════════════════════
# SPIELSTART
# ════════════════════════════════════════════════════════════
init(myHandleKey)
start()
# ════════════════════════════════════════════════════════════
# AUSWERTUNG
# ════════════════════════════════════════════════════════════
if hasLanded():
bonus = getFuel() * 2
punkte = punkte + bonus
print("GELANDET! Punkte:", punkte, "| Treibstoffbonus:", bonus)
elif hasCrashed():
print("ABSTURZ. Punkte:", punkte)
Erweitere deine Update-Funktion:
- Eine dritte Warnung nach eigener Idee
- Baue eine Pause-Taste in deinen
handleKeyein (togglePause()) - Bonus: Schreibe eine eigene Hilfsfunktion
berechnePunkte()die die Punkteberechnung kapselt — und rufe sie aus dem Update auf
Am Ende von Schritt 4 hast du:
- Mindestens 2 verschiedene Warnmeldungen (einmalig, nicht jeden Frame)
- Ein Punktesystem das während des Spiels läuft
- Mindestens eine eigene Hilfsfunktion die aus dem Update aufgerufen wird
Das fertige Spiel
Alles zusammenführen, aufräumen, fertigstellen. Eine gute Startmeldung, eine vollständige Auswertung, ein Spiel das sich rund anfühlt.
Klicke die Punkte an wenn du sie erledigt hast — der Browser merkt sich deinen Stand.
from lunarlander import *
# ════════════════════════════════════════════════════════════
# Mein LunarLander
# Name: [dein Name]
# Klasse: WPF Informatik
# ════════════════════════════════════════════════════════════
# ════════════════════════════════════════════════════════════
# DEFINITIONSBEREICH
# ════════════════════════════════════════════════════════════
# ── Spielzustand (globale Variablen) ──────────────────────────────────────
punkte = 1000
# TODO: weitere Variablen (Warnungsmerker etc.)
# ── Hilfsfunktionen ───────────────────────────────────────────────────────
# TODO: deine Hilfsfunktionen hier
# ── Eigener Lander (Hook) ───────────────────────────────────────────────
def meinLander():
pass # TODO: dein fertiges Design
# ── Update-Logik (Hook) ─────────────────────────────────────────────────
def meinUpdate():
global punkte
# TODO: Warnungen, Punktelogik, Hinweise
# ── Steuerung (Hook) ────────────────────────────────────────────────────
def myHandleKey(keyCode):
pass # TODO: deine Tastenbelegung
# ════════════════════════════════════════════════════════════
# SPIELEINSTELLUNGEN
# ════════════════════════════════════════════════════════════
# ── Lander ────────────────────────────────────────────────────────────────
# setCollisionProbe(0, 0, 24, 0) # TODO: anpassen
# ── Welt ──────────────────────────────────────────────────────────────────
# TODO: setTerrain([...])
# TODO: setLandingZone(start, ende)
# TODO: setGravity(wert)
# TODO: setFuel(menge)
# ── HUD ───────────────────────────────────────────────────────────────────
setHudItems(["fuel", "vSpeed", "height"]) # TODO: anpassen
# ════════════════════════════════════════════════════════════
# HOOKS ANMELDEN
# ════════════════════════════════════════════════════════════
setCustomDrawer(meinLander)
setUpdateFunction(meinUpdate)
# ════════════════════════════════════════════════════════════
# SPIELSTART
# ════════════════════════════════════════════════════════════
init(myHandleKey)
print("=" * 40)
print("[dein Titel]")
print("Steuerung: [deine Tasten]")
print("Ziel: Weich auf der markierten Zone landen.")
print("=" * 40)
start()
# ════════════════════════════════════════════════════════════
# AUSWERTUNG
# ════════════════════════════════════════════════════════════
print("=" * 40)
if hasLanded():
bonus = getFuel() * 2
punkte = punkte + bonus
print("SOFT LANDING!")
print("Punkte:", punkte, "| Treibstoffbonus:", bonus)
elif hasCrashed():
print("ABSTURZ!")
print("Endpunkte:", punkte)
print("=" * 40)
Testphase — Ein Programm gilt erst dann als fertig wenn es getestet wurde.
Arbeite diese Test-Checkliste durch:
- Normalstart: Programm frisch starten — erscheint die Startmeldung vollständig und korrekt?
- Erfolgreiche Landung: Weich auf der Landezone aufsetzen — stimmt die Auswertung (Punkte, Treibstoff)?
- Absturz: Absichtlich zu schnell aufprallen — kommt die Absturz-Meldung?
- Kein Treibstoff: Solange Gas geben bis der Tank leer ist — was passiert?
- Falsche Zone: Außerhalb der Landezone landen — wird das als Absturz gewertet?
- Benutzersicht: Stell dir vor, du startest dein Programm zum ersten Mal — ist alles sofort verständlich? Kannst du es ohne Erklärung spielen?
Bonus: Entwickle ein eigenes Testszenario das einen möglichen Fehler in deiner Spiellogik aufdecken könnte — und dokumentiere es als Kommentar in deiner Datei.
Abgabe: Speichere deine fertige Datei als schritt_05.py
im Ordner schritt_05/. Die Datei muss lauffähig sein und deinen Namen
in der ersten Zeile tragen.