API = Application Programming Interface. Du rufst Funktionen auf, ohne zu wissen, wie sie intern funktionieren — wie ein Fernseher mit Fernbedienung. Beispielsweise liefert getFuel() den aktuellen Treibstoffstand, und setGravity(0.05) macht die Schwerkraft sanfter — ohne dass du die Physik dahinter kennst.
Das Spiel läuft in einer Schleife. Pro Frame passieren diese Dinge in dieser Reihenfolge. Klicke auf eine Box, um eine Erklärung mit Beispiel zu sehen.
Diese Funktionen kannst du einsetzen. Du schreibst sie, die Engine ruft sie auf.
Physik und Rendering laufen automatisch — tick() und render() rufst du nie selbst auf.
start() aufgerufen werden. Gibt beim Start eine Versionsmeldung auf der Konsole aus (abschaltbar mit setStartupMessage(False)).LunarLander API v0.9.8 ready. aus — zeigt SuS immer welche Version aktiv istdef handleKey(keyCode): if keyCode == 38: # Pfeil hoch thrust() init(handleKey) # Fenster öffnen, Tastatur verbinden start() # Spielschleife starten
init() gibt beim Start LunarLander API vX.X.X ready. auf der Konsole ausinit() aufrufen. Nützlich wenn die Konsole für eigene Ausgaben frei bleiben soll.setStartupMessage(False) # Meldung unterdrücken init(handleKey) # kein "ready."-Text in der Konsole
start() läuft nach dem Spielende.init(handleKey) start() # Hier läuft Code erst NACH dem Spielende: if hasLanded(): print("Erfolg! Treibstoff:", getFuel())
elif keyCode == 82: # R-Taste restart()
if keyCode == 38 or keyCode == 32: # Pfeil hoch oder Leertaste thrust()
"height"if getHeight() < 50: print("Landeanflug! Höhe:", round(getHeight(), 1))
getSpeed()"vSpeed"if getVSpeed() > 4.0 and getHeight() < 60: print("Zu schnell! Schub!")
"hSpeed""fuel"if getFuel() < 40: print("Treibstoff niedrig!")
"x"if isOverLandingZone() and getHeight() < 80: print("Landezone – Geschwindigkeit prüfen!")
start() if hasLanded(): print("Erfolg! Rest:", getFuel()) elif hasCrashed(): print("Absturz. V:", round(getVSpeed(), 2))
h = getTerrainHeight(getX())
"frameTime"if getFrameTime() > 100: print("Langsamer Frame:", round(getFrameTime(), 1))
def handleKey(keyCode): if keyCode == 80: # P-Taste togglePause() elif keyCode == 38: thrust()
"paused"zaehler = 0 def meinUpdate(): global zaehler # Variablen von außen verändern zaehler += 1 if getFuel() < 40: print("Treibstoff kritisch!") setUpdateFunction(meinUpdate) # vor init() anmelden
def meinLander(): # Empfohlen: absolut mit setPos/moveTo — (0,0) = Lander-Mitte # +Y = oben, –Y = unten, +X = rechts, –X = links setPenColor("cyan") setPenWidth(2) penUp() setPos(-12, 14) # oben-links penDown() moveTo(12, 14) # → oben-rechts moveTo(12, -14) # → unten-rechts moveTo(-12, -14) # → unten-links moveTo(-12, 14) # → schließt Rechteck penUp() setCustomDrawer(meinLander) # vor init()
limit = 300 def pruefeEnde(): global limit limit -= 1 return limit <= 0 # True = Spiel endet setGameEndFunction(pruefeEnde)
setGroundLevel() nie aufgerufen, berechnet setWindowSize() den Bodenwert neu aus dem festen Verhältnis (95% der halben Fensterhöhe). Wurde er manuell gesetzt, wird er proportional skaliert.setWindowSize(500, 700) # vor init()
setTerrain([10, 10, 40, 80, 5, 5, 5, 60, 90, 20]) setLandingZone(4, 6) # flacher Bereich = Landeplatz
setLandingZones([[2, 4], [8, 10]]) # mind. 1 Zone
windowHeight an.setGroundLevel() aufruft, überschreibt das automatische Verhältnis. Ab dann skaliert setWindowSize() diesen Wert proportional.Setzt sofort den aktuellen Tank und den Startwert für restart().
"scale""rotation"winkel = 0 def update(): global winkel winkel = (winkel + 3) % 360 setRotation(winkel)
setGravity(0.05) # sanfte Mondgravitation setGravity(0.30) # hohe Schwerkraft = schwieriger
Alle erlaubten Schlüssel:
itemListe = ["fuel", "vSpeed", "height"] setHudItems(itemListe) setHudItems([]) # HUD ausblenden
Im Custom Drawer gibt es zwei Arten zu zeichnen:
setPos(x,y) und moveTo(x,y) — du siehst sofort welcher Punkt wo liegt.penUp(); setPos(0, 15) # Spitze oben penDown() moveTo(-18, -15) # unten links moveTo(18, -15) # unten rechts moveTo(0, 15) # Dreieck schließen penUp()
forward(), left(), right() — funktionieren, aber die Winkelkonvention unterscheidet sich vom Schulunterricht. 0° = oben (nicht rechts!), Uhrzeigersinn. Das führt leicht zu gespiegelten oder gedrehten Formen.Lander-Koordinatensystem — Mitte = (0,0)
Pink = Dreieck mit moveTo()
setPos() teleportiert immer ohne Linie. Für Linien: penDown() + moveTo() oder forward().penUp() setPos(-10, 10) # teleportieren — keine Linie penDown() moveTo(10, 10) # Linie zeichnen penUp()
"white", "cyan", "yellow", "lime", "red", "orange", "gray", "blue", …
setPos() / moveTo() mit direkten Koordinaten verwenden — weniger fehleranfällig als Winkelrechnen.setHeading()-Winkels. Achtung: 0 = oben, 90 = rechts, 180 = unten — nicht wie in der Schulmathematik. Wird durch scaleFactor skaliert und durch rotationAngle gedreht.setPos() / moveTo() mit konkreten Koordinaten statt Winkelrechnen — übersichtlicher und fehlerfreier.# setHeading(0) = nach OBEN — Quadrat wird von oben nach rechts gezeichnet setHeading(0); penDown() for _ in range(4): forward(20); right(90) # Tipp: setPos()/moveTo() ist für Formen einfacher!
Durchmesser in Pixeln, skaliert durch scaleFactor.
penUp(); setPos(-10, 15); penDown() moveTo(10, 15) # → Linie moveTo(10, -15) # → Linie moveTo(-10, -15) # → Linie moveTo(-10, 15) # → schließt Rechteck penUp()
setCollisionProbe(0, 0, 14, 0) # Probe am Lander-Fuß (y=-14) setShowCollisionProbe(True) # Debug: Punkt anzeigen
# Playfield-Rand sichtbar machen (nur zur Entwicklung) setShowInnerPlayfieldBorder(True) setPlayfieldMargin(10, 10, 10, 10)
Häufige Keycodes: ESC=27, Enter=10, Leertaste=32, A-Z=65–90, 0-9=48–57, Pfeile=37–40