Einführung
In diesem Projekt werden wir den Code für das Erstellen eines einfachen Flappy Bird-Spiels mit der Pygame-Bibliothek in bewältigbare Schritte aufteilen. Indem Sie diesen Schritten folgen, lernen Sie, wie Sie das Spiel schrittweise aufbauen. Jeder Schritt wird eine kurze Erklärung, Codeblöcke und Kommentare enthalten, um Ihnen zu helfen, das Spiel zu verstehen und umzusetzen. Los geht's!
👀 Vorschau

🎯 Aufgaben
In diesem Projekt werden Sie lernen:
- Wie Sie die Projektdateien für das Flappy Bird-Spiel einrichten
- Wie Sie die Willkommensanimation für das Spiel anzeigen
- Wie Sie die Hauptspiel-logik für Flappy Bird implementieren
- Wie Sie den Spiel-over-Bildschirm anzeigen, wenn der Spieler verliert
- Wie Sie Hilfsfunktionen für das Spiel definieren
🏆 Errungenschaften
Nach Abschluss dieses Projekts werden Sie in der Lage sein:
- Die Pygame-Bibliothek zum Erstellen von Spielen zu verwenden
- Spielentwicklungskonzepte wie Spielschleifen, Kollisionen und Animation zu verstehen
Erstelle die Projekt-Dateien
Zunächst werden wir die Projektdateien für das Flappy Bird-Spiel erstellen.
cd ~/project
touch flappy.py
sudo pip install pygame
In diesem Schritt werden wir die grundlegende Projektstruktur einrichten und die erforderlichen Bibliotheken importieren. Wir definieren auch einige Konstanten und laden die initialen Spielressourcen.
from itertools import cycle
import random
import sys
import pygame
from pygame.locals import *
FPS = 30
SCREENWIDTH = 288
SCREENHEIGHT = 512
PIPEGAPSIZE = 100 ## gap between upper and lower part of pipe
BASEY = SCREENHEIGHT * 0.79
## image and hitmask dicts
IMAGES, HITMASKS = {}, {}
## list of all possible players (tuple of 3 positions of flap)
PLAYERS_LIST = (
## red bird
(
"data/sprites/redbird-upflap.png",
"data/sprites/redbird-midflap.png",
"data/sprites/redbird-downflap.png",
),
## blue bird
(
"data/sprites/bluebird-upflap.png",
"data/sprites/bluebird-midflap.png",
"data/sprites/bluebird-downflap.png",
),
## yellow bird
(
"data/sprites/yellowbird-upflap.png",
"data/sprites/yellowbird-midflap.png",
"data/sprites/yellowbird-downflap.png",
),
)
## list of backgrounds
BACKGROUNDS_LIST = (
"data/sprites/background-day.png",
"data/sprites/background-night.png",
)
## list of pipes
PIPES_LIST = (
"data/sprites/pipe-green.png",
"data/sprites/pipe-red.png",
)
- Wir importieren die erforderlichen Bibliotheken für das Spiel, einschließlich
pygamezum Erstellen des Spiels,randomzum Generieren von zufälligen Elementen,sysfür systembezogene Funktionen undpygame.localsfür Schlüsselkonstanten. - Wir initialisieren Pygame mit
pygame.init(). - Konstanten wie
FPS,SCREENWIDTH,SCREENHEIGHT,PIPEGAPSIZEundBASEYwerden definiert, um die Abmessungen und Geschwindigkeit des Spiels einzustellen. - Wir erstellen leere Dictionaries (
IMAGESundHITMASKS), um die Spielressourcen zu speichern. - Listen von Spieler-, Hintergrund- und Rohrressourcen werden mithilfe von Dateipfaden definiert.
Zeige die Willkommensanimation
In diesem Schritt werden wir die Willkommensbildschirmanimation des Flappy Bird-Spiels erstellen.
def showWelcomeAnimation():
"""Zeigt die Willkommensbildschirmanimation von Flappy Bird"""
## Index des Spielers, der auf dem Bildschirm angezeigt werden soll
playerIndex = 0
playerIndexGen = cycle([0, 1, 2, 1])
## Iterator, der verwendet wird, um den playerIndex nach jeder 5. Iteration zu ändern
loopIter = 0
playerx = int(SCREENWIDTH * 0.2)
playery = int((SCREENHEIGHT - IMAGES["player"][0].get_height()) / 2)
messagex = int((SCREENWIDTH - IMAGES["message"].get_width()) / 2)
messagey = int(SCREENHEIGHT * 0.12)
basex = 0
## Betrag, um den sich die Basis maximal nach links verschieben kann
baseShift = IMAGES["base"].get_width() - IMAGES["background"].get_width()
## Spieler-Schmierung für die Hoch-Runter-Bewegung auf dem Willkommensbildschirm
playerShmVals = {"val": 0, "dir": 1}
while True:
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
if event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_UP):
## mache den ersten Flap-Sound und gib die Werte für mainGame zurück
return {
"playery": playery + playerShmVals["val"],
"basex": basex,
"playerIndexGen": playerIndexGen,
}
## passe playery, playerIndex, basex an
if (loopIter + 1) % 5 == 0:
playerIndex = next(playerIndexGen)
loopIter = (loopIter + 1) % 30
basex = -((-basex + 4) % baseShift)
playerShm(playerShmVals)
## zeichne Sprites
SCREEN.blit(IMAGES["background"], (0, 0))
SCREEN.blit(
IMAGES["player"][playerIndex], (playerx, playery + playerShmVals["val"])
)
SCREEN.blit(IMAGES["message"], (messagex, messagey))
SCREEN.blit(IMAGES["base"], (basex, BASEY))
pygame.display.update()
FPSCLOCK.tick(FPS)
- Wir definieren die
showWelcomeAnimation-Funktion, die für das Anzeigen der Willkommensbildschirmanimation verantwortlich ist. - Die Funktion setzt Variablen für die Animation ein und behandelt die Benutzereingabe, um das Spiel zu starten.
- Sie verwendet eine Schleife, um die Animationsframes zu aktualisieren und nach Benutzereingaben zu suchen, um das Spiel zu beginnen.
- Die Animation umfasst das Flattern des Vogels und eine Nachricht, die auf dem Bildschirm angezeigt wird.
- Die
pygame.display.update()-Funktion wird verwendet, um die Anzeige zu aktualisieren, undFPSCLOCK.tick(FPS)steuert die Framerate.
Hauptspiel-Logik
In diesem Schritt werden wir die Hauptspiel-logik für Flappy Bird implementieren.
def mainGame(movementInfo):
score = playerIndex = loopIter = 0
playerIndexGen = movementInfo["playerIndexGen"]
playerx, playery = int(SCREENWIDTH * 0.2), movementInfo["playery"]
basex = movementInfo["basex"]
baseShift = IMAGES["base"].get_width() - IMAGES["background"].get_width()
## bekomme 2 neue Rohre, um sie der upperPipes lowerPipes Liste hinzuzufügen
newPipe1 = getRandomPipe()
newPipe2 = getRandomPipe()
## Liste der oberen Rohre
upperPipes = [
{"x": SCREENWIDTH + 200, "y": newPipe1[0]["y"]},
{"x": SCREENWIDTH + 200 + (SCREENWIDTH / 2), "y": newPipe2[0]["y"]},
]
## Liste der unteren Rohre
lowerPipes = [
{"x": SCREENWIDTH + 200, "y": newPipe1[1]["y"]},
{"x": SCREENWIDTH + 200 + (SCREENWIDTH / 2), "y": newPipe2[1]["y"]},
]
dt = FPSCLOCK.tick(FPS) / 1000
pipeVelX = -128 * dt
## Spieler-Geschwindigkeit, maximale Geschwindigkeit, abwärts-Acceleration, Acceleration beim Flattern
playerVelY = -9 ## Spieler-Geschwindigkeit entlang der Y-Achse, standardmäßig gleich playerFlapped
playerMaxVelY = 10 ## maximale Geschwindigkeit entlang der Y-Achse, maximale Abwärtsgeschwindigkeit
playerMinVelY = -8 ## minimale Geschwindigkeit entlang der Y-Achse, maximale Aufwärtsgeschwindigkeit
playerAccY = 1 ## Abwärts-Acceleration des Spielers
playerRot = 45 ## Rotation des Spielers
playerVelRot = 3 ## Winkelgeschwindigkeit
playerRotThr = 20 ## Rotationsschwelle
playerFlapAcc = -9 ## Geschwindigkeit des Spielers beim Flattern
playerFlapped = False ## True, wenn der Spieler flattert
while True:
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
if event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_UP):
if playery > -2 * IMAGES["player"][0].get_height():
playerVelY = playerFlapAcc
playerFlapped = True
## prüfe hier auf einen Absturz
crashTest = checkCrash(
{"x": playerx, "y": playery, "index": playerIndex}, upperPipes, lowerPipes
)
if crashTest[0]:
return {
"y": playery,
"groundCrash": crashTest[1],
"basex": basex,
"upperPipes": upperPipes,
"lowerPipes": lowerPipes,
"score": score,
"playerVelY": playerVelY,
"playerRot": playerRot,
}
## prüfe auf Punkte
playerMidPos = playerx + IMAGES["player"][0].get_width() / 2
for pipe in upperPipes:
pipeMidPos = pipe["x"] + IMAGES["pipe"][0].get_width() / 2
if pipeMidPos <= playerMidPos < pipeMidPos + 4:
score += 1
## Änderung von playerIndex und basex
if (loopIter + 1) % 3 == 0:
playerIndex = next(playerIndexGen)
loopIter = (loopIter + 1) % 30
basex = -((-basex + 100) % baseShift)
## drehe den Spieler
if playerRot > -90:
playerRot -= playerVelRot
## Bewegung des Spielers
if playerVelY < playerMaxVelY and not playerFlapped:
playerVelY += playerAccY
if playerFlapped:
playerFlapped = False
## mehr Rotation, um die Schwelle zu überdecken (berechnet in sichtbarer Rotation)
playerRot = 45
playerHeight = IMAGES["player"][playerIndex].get_height()
playery += min(playerVelY, BASEY - playery - playerHeight)
## bewege die Rohre nach links
for uPipe, lPipe in zip(upperPipes, lowerPipes):
uPipe["x"] += pipeVelX
lPipe["x"] += pipeVelX
## füge ein neues Rohr hinzu, wenn das erste Rohr fast den linken Rand des Bildschirms berührt
if 3 > len(upperPipes) > 0 and 0 < upperPipes[0]["x"] < 5:
newPipe = getRandomPipe()
upperPipes.append(newPipe[0])
lowerPipes.append(newPipe[1])
## entferne das erste Rohr, wenn es außerhalb des Bildschirms ist
if len(upperPipes) > 0 and upperPipes[0]["x"] < -IMAGES["pipe"][0].get_width():
upperPipes.pop(0)
lowerPipes.pop(0)
## zeichne die Sprites
SCREEN.blit(IMAGES["background"], (0, 0))
for uPipe, lPipe in zip(upperPipes, lowerPipes):
SCREEN.blit(IMAGES["pipe"][0], (uPipe["x"], uPipe["y"]))
SCREEN.blit(IMAGES["pipe"][1], (lPipe["x"], lPipe["y"]))
SCREEN.blit(IMAGES["base"], (basex, BASEY))
## zeige den Score an, sodass der Spieler den Score überdeckt
showScore(score)
## Die Spielerrotation hat eine Schwelle
visibleRot = playerRotThr
if playerRot <= playerRotThr:
visibleRot = playerRot
playerSurface = pygame.transform.rotate(
IMAGES["player"][playerIndex], visibleRot
)
SCREEN.blit(playerSurface, (playerx, playery))
pygame.display.update()
FPSCLOCK.tick(FPS)
- Wir definieren die
mainGame-Funktion, die die Kernlogik für das Flappy Bird-Spiel enthält. - Die Funktion behandelt die Benutzereingabe, aktualisiert den Spielzustand, prüft auf Kollisionen und hält den Score fest.
- Die Spielschleife läuft kontinuierlich und aktualisiert die Anzeige und die Logik des Spiels.
- Die Spielersteuerung wird über Tasteneingaben (Leertaste oder Pfeil nach oben) behandelt.
- Die Funktion prüft auch auf Kollisionen mit Rohren und dem Boden, aktualisiert den Score und verwaltet die Animation des Vogels.
- Die Spielschleife setzt sich fort, bis der Spieler abstürzt oder das Spiel beendet wird.
Zeige das Game-Over-Fenster an
In diesem Schritt werden wir den Spiel-over-Bildschirm erstellen, der erscheint, wenn der Spieler verliert.
def showGameOverScreen(crashInfo):
""" lässt den Spieler nach unten fallen und zeigt das Spiel-over-Bild an """
score = crashInfo["score"]
playerx = SCREENWIDTH * 0.2
playery = crashInfo["y"]
playerHeight = IMAGES["player"][0].get_height()
playerVelY = crashInfo["playerVelY"]
playerAccY = 2
playerRot = crashInfo["playerRot"]
playerVelRot = 7
basex = crashInfo["basex"]
upperPipes, lowerPipes = crashInfo["upperPipes"], crashInfo["lowerPipes"]
while True:
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
if event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_UP):
if playery + playerHeight >= BASEY - 1:
return
## Verschiebung des Spielers in y-Richtung
if playery + playerHeight < BASEY - 1:
playery += min(playerVelY, BASEY - playery - playerHeight)
## Änderung der Spieler-Geschwindigkeit
if playerVelY < 15:
playerVelY += playerAccY
## Drehe nur, wenn es eine Rohrkollision ist
if not crashInfo["groundCrash"]:
if playerRot > -90:
playerRot -= playerVelRot
## zeichne die Sprites
SCREEN.blit(IMAGES["background"], (0, 0))
for uPipe, lPipe in zip(upperPipes, lowerPipes):
SCREEN.blit(IMAGES["pipe"][0], (uPipe["x"], uPipe["y"]))
SCREEN.blit(IMAGES["pipe"][1], (lPipe["x"], lPipe["y"]))
SCREEN.blit(IMAGES["base"], (basex, BASEY))
showScore(score)
playerSurface = pygame.transform.rotate(IMAGES["player"][1], playerRot)
SCREEN.blit(playerSurface, (playerx, playery))
SCREEN.blit(IMAGES["gameover"], (50, 180))
FPSCLOCK.tick(FPS)
pygame.display.update()
- Die
showGameOverScreen-Funktion zeigt den Spiel-over-Bildschirm an, wenn der Spieler verliert. - Sie zeigt das endgültige Ergebnis des Spielers, spielt Soundeffekte ab und wartet darauf, dass der Spieler die Leertaste oder die Pfeiltaste nach oben drückt, um das Spiel neu zu starten.
- Die Animation umfasst das Sinken des Vogels auf den Boden und die Anzeige der Spiel-over-Nachricht auf dem Bildschirm.
Definiere Hilfsfunktionen
In diesem Schritt definieren wir Hilfsfunktionen, die im Spiel verwendet werden.
def playerShm(playerShm):
"""schwingt den Wert von playerShm['val'] zwischen 8 und -8"""
if abs(playerShm["val"]) == 8:
playerShm["dir"] *= -1
if playerShm["dir"] == 1:
playerShm["val"] += 1
else:
playerShm["val"] -= 1
def getRandomPipe():
"""gibt ein zufällig generiertes Rohr zurück"""
## y des Spiegels zwischen oberem und unterem Rohr
gapY = random.randrange(0, int(BASEY * 0.6 - PIPEGAPSIZE))
gapY += int(BASEY * 0.2)
pipeHeight = IMAGES["pipe"][0].get_height()
pipeX = SCREENWIDTH + 10
return [
{"x": pipeX, "y": gapY - pipeHeight}, ## oberes Rohr
{"x": pipeX, "y": gapY + PIPEGAPSIZE}, ## unteres Rohr
]
def showScore(score):
"""zeigt den Score in der Mitte des Bildschirms an"""
scoreDigits = [int(x) for x in list(str(score))]
totalWidth = 0 ## Gesamtbreite aller Zahlen, die gedruckt werden sollen
for digit in scoreDigits:
totalWidth += IMAGES["numbers"][digit].get_width()
Xoffset = (SCREENWIDTH - totalWidth) / 2
for digit in scoreDigits:
SCREEN.blit(IMAGES["numbers"][digit], (Xoffset, SCREENHEIGHT * 0.1))
Xoffset += IMAGES["numbers"][digit].get_width()
def checkCrash(player, upperPipes, lowerPipes):
"""gibt True zurück, wenn der Spieler mit der Basis oder den Rohren kollidiert."""
pi = player["index"]
player["w"] = IMAGES["player"][0].get_width()
player["h"] = IMAGES["player"][0].get_height()
## Wenn der Spieler in den Boden fällt
if player["y"] + player["h"] >= BASEY - 1:
return [True, True]
else:
playerRect = pygame.Rect(player["x"], player["y"], player["w"], player["h"])
pipeW = IMAGES["pipe"][0].get_width()
pipeH = IMAGES["pipe"][0].get_height()
for uPipe, lPipe in zip(upperPipes, lowerPipes):
## obere und untere Rohr-Rects
uPipeRect = pygame.Rect(uPipe["x"], uPipe["y"], pipeW, pipeH)
lPipeRect = pygame.Rect(lPipe["x"], lPipe["y"], pipeW, pipeH)
## Spieler und obere/untere Rohr-Hitmasks
pHitMask = HITMASKS["player"][pi]
uHitmask = HITMASKS["pipe"][0]
lHitmask = HITMASKS["pipe"][1]
## Wenn der Vogel mit einem oberen oder unteren Rohr kollidiert
uCollide = pixelCollision(playerRect, uPipeRect, pHitMask, uHitmask)
lCollide = pixelCollision(playerRect, lPipeRect, pHitMask, lHitmask)
if uCollide or lCollide:
return [True, False]
return [False, False]
def pixelCollision(rect1, rect2, hitmask1, hitmask2):
"""prüft, ob zwei Objekte kollidieren und nicht nur ihre Rects"""
rect = rect1.clip(rect2)
if rect.width == 0 or rect.height == 0:
return False
x1, y1 = rect.x - rect1.x, rect.y - rect1.y
x2, y2 = rect.x - rect2.x, rect.y - rect2.y
for x in range(rect.width):
for y in range(rect.height):
if hitmask1[x1 + x][y1 + y] and hitmask2[x2 + x][y2 + y]:
return True
return False
def getHitmask(image):
"""gibt eine Hitmask basierend auf der Alpha-Kanal eines Bildes zurück"""
mask = []
for x in range(image.get_width()):
mask.append([])
for y in range(image.get_height()):
mask[x].append(bool(image.get_at((x, y))[3]))
return mask
- Die
playerShm-Funktion schwingt den Wert vonplayerShm["val"]zwischen 8 und -8. Dies wird verwendet, um den Vogel auf dem Willkommensbildschirm nach oben und unten zu bewegen. - Die
getRandomPipe-Funktion gibt ein zufällig generiertes Rohr zurück. Sie generiert einen zufälligen Spiegel zwischen dem oberen und unteren Rohr. - Die
showScore-Funktion zeigt den Score in der Mitte des Bildschirms an. Sie verwendet dieIMAGES["numbers"]-Liste, um den Score anzuzeigen. - Die
checkCrash-Funktion gibtTruezurück, wenn der Spieler mit dem Boden oder den Rohren kollidiert. Sie verwendet diepixelCollision-Funktion, um Kollisionen zu überprüfen. - Die
pixelCollision-Funktion prüft, ob zwei Objekte kollidieren und nicht nur ihre Rects. Sie verwendet diegetHitmask-Funktion, um die Hitmask für den Spieler und die Rohre zu erhalten. - Die
getHitmask-Funktion gibt eine Hitmask basierend auf der Alpha-Kanal eines Bildes zurück. Sie verwendet dieimage.get_at-Funktion, um den Alpha-Wert jedes Pixels im Bild zu erhalten.
Die Hauptfunktion
In diesem Schritt definieren wir die Hauptfunktion, die das Spiel initialisiert und die Spielschleife startet.
def main():
global SCREEN, FPSCLOCK
pygame.init()
FPSCLOCK = pygame.time.Clock()
SCREEN = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
pygame.display.set_caption("Flappy Bird")
## Sprites für die Zahlenanzeige des Scores
IMAGES["numbers"] = (
pygame.image.load("data/sprites/0.png").convert_alpha(),
pygame.image.load("data/sprites/1.png").convert_alpha(),
pygame.image.load("data/sprites/2.png").convert_alpha(),
pygame.image.load("data/sprites/3.png").convert_alpha(),
pygame.image.load("data/sprites/4.png").convert_alpha(),
pygame.image.load("data/sprites/5.png").convert_alpha(),
pygame.image.load("data/sprites/6.png").convert_alpha(),
pygame.image.load("data/sprites/7.png").convert_alpha(),
pygame.image.load("data/sprites/8.png").convert_alpha(),
pygame.image.load("data/sprites/9.png").convert_alpha(),
)
## Spiel-over-Sprite
IMAGES["gameover"] = pygame.image.load("data/sprites/gameover.png").convert_alpha()
## Nachrichtensprite für den Willkommensbildschirm
IMAGES["message"] = pygame.image.load("data/sprites/message.png").convert_alpha()
## Basis (Boden)-Sprite
IMAGES["base"] = pygame.image.load("data/sprites/base.png").convert_alpha()
while True:
## wähle zufällige Hintergrund-Sprites
randBg = random.randint(0, len(BACKGROUNDS_LIST) - 1)
IMAGES["background"] = pygame.image.load(BACKGROUNDS_LIST[randBg]).convert()
## wähle zufällige Spieler-Sprites
randPlayer = random.randint(0, len(PLAYERS_LIST) - 1)
IMAGES["player"] = (
pygame.image.load(PLAYERS_LIST[randPlayer][0]).convert_alpha(),
pygame.image.load(PLAYERS_LIST[randPlayer][1]).convert_alpha(),
pygame.image.load(PLAYERS_LIST[randPlayer][2]).convert_alpha(),
)
## wähle zufällige Rohr-Sprites
pipeindex = random.randint(0, len(PIPES_LIST) - 1)
IMAGES["pipe"] = (
pygame.transform.flip(
pygame.image.load(PIPES_LIST[pipeindex]).convert_alpha(), False, True
),
pygame.image.load(PIPES_LIST[pipeindex]).convert_alpha(),
)
## Hitmask für die Rohre
HITMASKS["pipe"] = (
getHitmask(IMAGES["pipe"][0]),
getHitmask(IMAGES["pipe"][1]),
)
## Hitmask für den Spieler
HITMASKS["player"] = (
getHitmask(IMAGES["player"][0]),
getHitmask(IMAGES["player"][1]),
getHitmask(IMAGES["player"][2]),
)
movementInfo = showWelcomeAnimation()
crashInfo = mainGame(movementInfo)
showGameOverScreen(crashInfo)
- Die
main-Funktion initialisiert das Spiel, setzt die Anzeige ein und startet die Spielschleife. - Sie lädt die Spielressourcen, einschließlich Bilder, und wählt zufällig Hintergrund-, Spieler- und Rohrsprites aus.
- Die Spielschleife behandelt die Willkommensanimation, das Hauptspiel und den Spiel-over-Bildschirm.
- Das Spiel läuft in einer Schleife fort, bis der Spieler das Spiel beendet oder das Fenster schließt.
Starte das Spiel
In diesem Schritt werden wir das Flappy Bird-Spiel starten.
if __name__ == "__main__":
main()
- Die Bedingung
__name__ == "__main__"prüft, ob das aktuelle Modul selbst ausgeführt wird oder von einem anderen Modul importiert wird. - Wenn das aktuelle Modul selbst ausgeführt wird, wird die
main-Funktion aufgerufen, um das Spiel zu starten.
Wenn Sie alle Schritte abgeschlossen haben, können Sie das Flappy Bird-Spiel mit dem folgenden Befehl starten:
cd ~/project
python flappy.py

Zusammenfassung
In diesem Projekt haben wir den Code des Flappy Bird-Spiels in mehrere Schritte unterteilt und für jeden Schritt Erklärungen gegeben. Sie haben gelernt, wie Sie eine grundlegende Spielstruktur erstellen, die Spieler-Eingaben verarbeiten, den Spielzustand aktualisieren, Kollisionen überprüfen und die Spielbilder anzeigen. Sie können jetzt das Flappy Bird-Spiel mit dem bereitgestellten Code ausführen und spielen. Genießen Sie Ihre Reise beim Game-Entwicklung!



