So gebaut
Sternjäger ist ein reines Kiste-Programm. Es nutzt nur die eingebauten Module
gui (Fenster, Zeichnen, Tasten), klang (Töne und Musik),
liste, zufall und datei — keine fremde
Spiel-Engine. Hier sind die interessantesten Stellen.
1 · Der Spiel-Takt
Ein einziger Zeitgeber treibt alles an: 60 Mal pro Sekunde (alle 16 ms) bewegt sich
die Welt und wird neu gezeichnet. Ein modus-Wert entscheidet, ob gerade
das Menü, das Spiel, die Pause oder der Game-Over-Bildschirm läuft.
nimm uhr = gui.bei_zeit(16, funktion(t) {
sterne_bewegen()
partikel_bewegen()
wenn flash > 0 { flash = flash - 1 }
wenn modus == 1 { spiel_logik() } // nur im Spiel rechnen
zeichne() // aber immer neu zeichnen
}) 2 · Alles sind parallele Listen
Statt Objekten führt Sternjäger für jede Eigenschaft eine eigene Liste — Gegner
Nummer j hat seine Position in ex[j]/ey[j], seinen
Typ in et[j] und so weiter. Das ist schlicht und schnell.
// Jede Gegner-Eigenschaft ist eine eigene, parallele Liste.
// Leere Listen mit liste.gefüllt(0, …) anlegen, damit der
// Compiler den Elementtyp kennt.
nimm ex = liste.gefüllt(0, 0) // x-Position
nimm ey = liste.gefüllt(0, 0) // y-Position
nimm et = liste.gefüllt(0, 0) // Typ 0..4
nimm eh = liste.gefüllt(0, 0) // Trefferpunkte
nimm ealive = liste.gefüllt(0, 0) 3 · Gegner mit eigenem Verhalten
Fünf Gegnertypen. Je länger du überlebst (je höher die welle), desto
härtere Typen tauchen auf und werden häufiger.
// Mit steigender Welle kommen härtere Gegner dazu.
nimm r = zufall.ganz(0, 99)
nimm t = 0
wenn welle >= 4 und r < 6 + welle {
t = 4 // Panzer (ab Welle 5)
} sonstwenn welle >= 2 und r < 30 {
t = 3 // Verfolger (ab Welle 3)
} sonstwenn r < 22 + schwer {
t = 2 // Schütze
} sonstwenn r < 60 {
t = 1 // Zickzack
} sonst {
t = 0 // Drifter
} Jeder Typ verhält sich anders. Der Verfolger etwa schaut in jedem Takt, wo der Spieler steht, und lenkt seitlich auf ihn zu:
// Typ 3 (Verfolger) steuert seitlich auf den Spieler zu
wenn t == 3 {
wenn px > wert.als_ganz(ex[j]) { evx[j] = 2 } sonst { evx[j] = -2 }
} 4 · Sammelbare Items und Power-ups
Abgeschossene Gegner lassen manchmal ein Item fallen. Berührt dein Schiff es,
greift sammle: die Bombe fegt den Bildschirm leer, das
Schild macht dich kurz unverwundbar, der Doppelschuss
lässt dein Schiff doppelt feuern. Power-ups sind einfach Zähler, die jeden Takt
herunterlaufen.
funktion sammle(typ) {
spiele_ton(power_s)
wenn typ == 0 { zünde_bombe() } // löscht alle sichtbaren Gegner
sonstwenn typ == 1 { schild = 300 } // ~5 s unverwundbar
sonst { doppel = 480 } // ~8 s Doppelschuss
}
funktion spieler_getroffen() {
wenn schild > 0 { gib } // Schild fängt den Treffer ab
leben = leben - 1
flash = 8
wenn leben <= 0 { game_over() }
} 5 · Zeichnen mit Rechtecken und Kreisen
Es gibt keine Bilddateien für Schiff, Gegner oder Effekte — alles wird pro Bild aus
gui.rechteck, gui.kreis und gui.text_an
zusammengesetzt. Für sauber zentrierte Texte misst gui.text_breite die
echte Pixelbreite.
// Echtes Zentrieren dank gui.text_breite (misst die Pixelbreite)
funktion text_mitte(cx, y, txt, farbe, groesse) {
gui.text_an(bild, cx - gui.text_breite(txt, groesse) div 2, y, txt, farbe, groesse)
}
// Das Schiff — nur aus Rechtecken und einem Kreis
gui.rechteck(bild, px - 3, SPIELER_Y - 24, 6, 30, "#bae6fd")
gui.rechteck(bild, px - 18, SPIELER_Y + 2, 36, 8, "#38bdf8")
gui.kreis(bild, px, SPIELER_Y - 14, 4, "#e0f2fe") 6 · Menü, Logo und Beenden
Die Bestenliste wird als kleine Textdatei gespeichert und beim Start geladen. Ein eigenes Logo ersetzt das Standard-Icon, und „Beenden" schließt einfach das Hauptfenster.
// Eigenes Logo in Titel- und Taskleiste
gui.setze_app_icon("sternjaeger-logo.png")
// „Beenden" = das Hauptfenster schließen
funktion beende_spiel() {
gui.fenster_schließe(fenster)
} Das ist das ganze Rezept: ein Zeitgeber, ein paar Listen, Rechtecke und Kreise. Der komplette Quelltext liegt jedem Download oben bei — ändere die Gegner, erfinde neue Power-ups, bau dein eigenes Spiel daraus.