In Vorfreude auf mein ursprünglich als Festtagslektüre geplante Buch »Code the Classics«, das wohl nun doch erst am nächsten Sonnabend ausgeliefert wird, hatte ich mir noch einmal die zehn kurzen Video-Tutorials »Create a Casual Game with Pygame Zero« reingezogen. Das brachte mir soviel Spaß, daß auch ich ein Casual Game in Pygame Zero programmieren wollte. Im letzten Jahre hatte ich ja schon einmal das kleine Spiel Apple Invaders (Teil 2) nach einer Idee von Matthew Hopson in Processing.py, dem Python-Mode von Processing programmiert und dies ähnelte doch sehr dem Spiel im oben erwähnten Tutorial. Was lag also näher, als eine weitere Variante davon zu erstellen? Dieses Mal natürlich in Pygame Zero!
Die Idee des Spiels ist einfach. Aus irgendwelchen Gründen regnet es Äpfel und der Spieler, ein Gripe (was immer für ein Fabelwesen das auch sein mag 1), muß die grünen Äpfel fangen (jeder aufgefangenene oder aufgesammelte grüne Apfel bringt einen Punkt). Damit das Spiel nicht zu einfach wird, liegen die gefallenen Äpfel nur weniger als eine Sekunde (40 Frames) auf dem Fußboden, dann verschwinden sie. Jeder grüne Apfel, den der Gripe nicht aufgesammelt hat, kostet einen Punkt. Hat der Gripe weniger als null Punkte, endet das Spiel.
Absolut toxisch sind dagegen die roten Äpfel. Eine Berührung mit einem dieser roten Äpfel kostet dem Gripe das Leben und das Spiel ist ebenfalls zu Ende.
Zuerst einmal habe ich das Spielefenster mit dem Hintergrundbild und dem Fußboden, auf dem sich der Spieler bewegt, aufgebaut:
WIDTH = 480 HEIGHT = 380 CENTER = WIDTH/2 TITLE = "🍏🍎 Apple Invaders 🍎🍏" GROUNDWIDTH = 32 def draw(): screen.blit(images.background, (0, 0)) for i in range(15): screen.blit(images.ground, (i*GROUNDWIDTH, HEIGHT - 32)) screen.blit(images.checker, (i*GROUNDWIDTH, HEIGHT - 16))
Das Hintergrundbild, die Kacheln für den Fußboden wie auch den Gripe habe ich dem freien (CC-BY-4.0) Tileset von Marc Russell von Zingot Games entnommen, das es auf OpenGameArt.org zum Download gibt. Die Lizenzbedingungen verlangen die Namensnennung und das habe ich damit erledigt.
Dann habe ich den Gripe hinzugefügt:
## Player gripe = Actor("gripe") gripe.pos = midbottom=(CENTER, HEIGHT - 48) gripe.speed = 5 gripe_frame = 0 def gripe_walk_left(): global gripe_frame if gripe_frame < 7: gripe_frame += 1 else: gripe_frame = 0 gripe.image = "gl" + str(int(gripe_frame)) def gripe_walk_right(): global gripe_frame if gripe_frame < 7: gripe_frame += 1 else: gripe_frame = 0 gripe.image = "gr" + str(int(gripe_frame)) def gripe_move(): gripe.image = "gripe" if keyboard.left and gripe.left > 0: gripe_walk_left() gripe.x -= gripe.speed elif keyboard.right and gripe.right < WIDTH: gripe_walk_right() gripe.x += gripe.speed
Wenn man jetzt noch in der draw()
-Methode
def draw(): screen.blit(images.background, (0, 0)) gripe.draw()
und in der update()
-Funktion
def update(): gripe_move()
hinzufügt, dann kan man die Spielerfigur mit den Pfeiltasten rechts und links über den Bildschirm wuseln lassen.
Für die Bewegungen nach rechts und links existieren jeweils acht Einzelbilder, die grx.png
respektive glx.png
heißen, wobei das x
jeweils für eine Ziffer zwischen 0
und 8
steht. Daher habe ich in den jeweiligen Funktionen die Dateinamen mit
gripe.image = "gr" + str(int(gripe_frame))
respektive
gripe.image = "gl" + str(int(gripe_frame))
zusammengesetzt. Die Variable gripe_frame
mußte dafür als global
deklariert werden.
Ähnlich habe ich mit den Äpfeln verfahren, nur daß ich sie in Listen zusammengefaßt habe. Die Anzahl der Äpfel ist fix, die grünen Äpfel fallen auf den Fußboden und werden nach 40 Frames wieder an eine zufällige Position oberhalb des Bildschirmfensters gebeamt, die roten Äpfel fallen aus dem unteren Rand des Bildschirmfenster heraus, bevor sie wieder nach oben katapultiert werden.
Da die Äpfel auch in ihren Listen initialisiert werden, konnte ich ihnen keine Eigenschaften verpassen, sondern mußte diese in einfache Variablen hinterlegen, wie zum Beispiel:
green_apple_speed = 2 red_apple_speed = 3
Beispielhaft zeigen die Code-Schnipsel hier, wie die grünen Äpfel erzeugt werden, bis auf kleine Änderungen werden die roten Äpfel gleich behandelt:
green_apples = [] number_of_green_apples = 6 apple_frame = 0 def green_apples_spawn(): green_apples.append(Actor("applegreen", pos = (randint(8, WIDTH - 8), 16))) def green_apple_fall(apple): global apple_frame, score, game_over if apple.y < HEIGHT - 40: apple.y += green_apple_speed else: if apple_frame < 1: apple_frame += 0.025 else: apple.pos = (randint(8, WIDTH - 8), 16) score -= 1 if score < 0: score = 0 game_over = True apple_frame = 0 for i in range(number_of_green_apples): clock.schedule(green_apples_spawn, i*2)
Beide Äpfelsorten müssen natürlich in der draw()
- und in der update()
-Methode abgearbeitet werden:
def draw(): […] if not game_over: for apple in green_apples: apple.draw() for apple in red_apples: apple.draw() […] def update(): […] for apple in green_apples: green_apple_fall(apple) if gripe.colliderect(apple): apple.pos = (randint(8, WIDTH - 8), 16) score += 1 for apple in red_apples: red_apple_fall(apple) if gripe.colliderect(apple): game_over = True
Die Bildchen für die Äpfel habe ich Twitters freiem (CC-BY-4.0) Emoji-Set Twemoji entnommen und mit einem Bildverarbeitungsprogramm meines Vertrauens auf 16x16 Pixel heruntergerechnet.
Der Rest – wie zum Beispiel die Behandlung des Spielendes – war dann schnell erledigt, wie Ihr dem gesamten Quellcode des Spieles entnehmen könnt:
import pgzrun from random import randint WIDTH = 480 HEIGHT = 380 CENTER = WIDTH/2 TITLE = "🍏🍎 Apple Invaders 🍎🍏" GROUNDWIDTH = 32 green_apple_speed = 2 red_apple_speed = 3 score = 0 game_over = False ## Player gripe = Actor("gripe") gripe.pos = midbottom=(CENTER, HEIGHT - 48) gripe.speed = 5 gripe_frame = 0 def gripe_walk_left(): global gripe_frame if gripe_frame < 7: gripe_frame += 1 else: gripe_frame = 0 gripe.image = "gl" + str(int(gripe_frame)) def gripe_walk_right(): global gripe_frame if gripe_frame < 7: gripe_frame += 1 else: gripe_frame = 0 gripe.image = "gr" + str(int(gripe_frame)) def gripe_move(): gripe.image = "gripe" if keyboard.left and gripe.left > 0: gripe_walk_left() gripe.x -= gripe.speed elif keyboard.right and gripe.right < WIDTH: gripe_walk_right() gripe.x += gripe.speed ## Green Apples green_apples = [] number_of_green_apples = 6 apple_frame = 0 def green_apples_spawn(): green_apples.append(Actor("applegreen", pos = (randint(8, WIDTH - 8), 16))) def green_apple_fall(apple): global apple_frame, score, game_over if apple.y < HEIGHT - 40: apple.y += green_apple_speed else: if apple_frame < 1: apple_frame += 0.025 else: apple.pos = (randint(8, WIDTH - 8), 16) score -= 1 if score < 0: score = 0 game_over = True apple_frame = 0 for i in range(number_of_green_apples): clock.schedule(green_apples_spawn, i*2) ## Red Apples red_apples = [] number_of_red_apples = 2 def red_apples_spawn(): red_apples.append(Actor("applered", pos = (randint(8, WIDTH - 8), 16))) def red_apple_fall(apple): if apple.y < HEIGHT: apple.y += red_apple_speed else: apple.pos = (randint(8, WIDTH - 8), 16) for i in range(number_of_red_apples): clock.schedule(red_apples_spawn, i*5) ## Game Loop def draw(): screen.blit(images.background, (0, 0)) gripe.draw() if not game_over: for apple in green_apples: apple.draw() for apple in red_apples: apple.draw() else: gripe.image = "gdie" screen.draw.text("Game Over", center = (CENTER, HEIGHT/2), color = "red", fontsize = 64) for i in range(15): screen.blit(images.ground, (i*GROUNDWIDTH, HEIGHT - 32)) screen.blit(images.checker, (i*GROUNDWIDTH, HEIGHT - 16)) screen.draw.text(f"Score: {score}", midtop = (CENTER, 10), fontsize = 36) screen.draw.text("Vermeide die Roten und schnappe die Grünen", midbottom = (CENTER, HEIGHT - 3), fontsize = 24) def update(): global score, game_over if not game_over: gripe_move() for apple in green_apples: green_apple_fall(apple) if gripe.colliderect(apple): apple.pos = (randint(8, WIDTH - 8), 16) score += 1 for apple in red_apples: red_apple_fall(apple) if gripe.colliderect(apple): game_over = True pgzrun.go()
Es ist ein komplettes Spiel, das ich hier in weniger als 125 Zeilen Quellcode entwickelt habe. Und es ist – zumindest für meine Fähigkeiten – gar nicht so einfach zu spielen. Ihr könnt es ausprobieren, denn der gesamte Quellcode inklusive der Bildchen findet Ihr in meinem GitHub-Repositorium. Wenn Ihr die Ordnerstruktur beibehaltet und Pygame Zero auf Eurem Computer installiert habt, könnt Ihr es einfach aus einem Editor heraus starten. Habt Spaß damit!
Die Anleitung zum Spiel »Vermeide die Roten und schnappe die Grünen« solltet Ihr als politische Anspielung nicht zu ernst nehmen. Aber sie lag einfach in der Luft.
Über …
Der Schockwellenreiter ist seit dem 24. April 2000 das Weblog digitale Kritzelheft von Jörg Kantel (Neuköllner, EDV-Leiter Rentner, Autor, Netzaktivist und Hundesportler — Reihenfolge rein zufällig). Hier steht, was mir gefällt. Wem es nicht gefällt, der braucht ja nicht mitzulesen. Wer aber mitliest, ist herzlich willkommen und eingeladen, mitzudiskutieren!
Alle eigenen Inhalte des Schockwellenreiters stehen unter einer Creative-Commons-Lizenz, jedoch können fremde Inhalte (speziell Videos, Photos und sonstige Bilder) unter einer anderen Lizenz stehen.
Der Besuch dieser Webseite wird aktuell von der Piwik Webanalyse erfaßt. Hier können Sie der Erfassung widersprechen.
Diese Seite verwendet keine Cookies. Warum auch? Was allerdings die iframes
von Amazon, YouTube und Co. machen, entzieht sich meiner Kenntnis.
Werbung