""" FlappyBird Web Version Angepasst für Pygbag Web-Export """ import pygame import sys import random import math import asyncio # Wichtig für Web-Export! # Pygame initialisieren pygame.init() pygame.mixer.init() # Bildschirmgröße BREITE = 400 HOEHE = 600 # Farben HIMMEL_BLAU = (135, 206, 250) GELB = (255, 255, 0) ORANGE = (255, 165, 0) GRUEN = (0, 200, 0) DUNKELGRUEN = (0, 150, 0) WEISS = (255, 255, 255) ROT = (255, 0, 0) BRAUN = (139, 69, 19) # Fenster bildschirm = pygame.display.set_mode((BREITE, HOEHE)) pygame.display.set_caption("Flappy Bird - Web Edition") # Schriftarten schrift = pygame.font.Font(None, 50) kleine_schrift = pygame.font.Font(None, 30) # Spieluhr uhr = pygame.time.Clock() class Vogel: def __init__(self): self.x = 50 self.y = HOEHE // 2 self.radius = 20 self.geschwindigkeit_y = 0 self.schwerkraft = 0.5 self.sprungkraft = -8 self.winkel = 0 self.fluegelschlag = 0 def springen(self): self.geschwindigkeit_y = self.sprungkraft self.fluegelschlag = 10 def bewegen(self): self.geschwindigkeit_y += self.schwerkraft self.y += self.geschwindigkeit_y if self.geschwindigkeit_y < 0: self.winkel = min(30, -self.geschwindigkeit_y * 3) else: self.winkel = max(-90, -self.geschwindigkeit_y * 3) if self.fluegelschlag > 0: self.fluegelschlag -= 1 if self.y < self.radius: self.y = self.radius self.geschwindigkeit_y = 0 elif self.y > HOEHE - self.radius - 50: self.y = HOEHE - self.radius - 50 self.geschwindigkeit_y = 0 def zeichnen(self): pos = (int(self.x), int(self.y)) pygame.draw.circle(bildschirm, GELB, pos, self.radius) if self.fluegelschlag > 5: fluegel_y = self.y - 5 else: fluegel_y = self.y pygame.draw.ellipse( bildschirm, (255, 200, 0), (self.x - 25, fluegel_y - 10, 30, 20) ) schnabel_x = self.x + self.radius * math.cos(math.radians(-self.winkel)) schnabel_y = self.y - self.radius * math.sin(math.radians(-self.winkel)) schnabel = [ (schnabel_x, schnabel_y), (schnabel_x + 10, schnabel_y - 3), (schnabel_x + 10, schnabel_y + 3), ] pygame.draw.polygon(bildschirm, ORANGE, schnabel) pygame.draw.circle(bildschirm, (0, 0, 0), (int(self.x + 5), int(self.y - 5)), 3) pygame.draw.circle(bildschirm, WEISS, (int(self.x + 6), int(self.y - 6)), 1) def get_rect(self): return pygame.Rect( self.x - self.radius, self.y - self.radius, self.radius * 2, self.radius * 2 ) class Rohr: def __init__(self, x): self.x = x self.breite = 60 self.luecke = 150 self.luecke_y = random.randint(150, HOEHE - 200) self.geschwindigkeit = 3 self.vorbei = False def bewegen(self): self.x -= self.geschwindigkeit def zeichnen(self): pygame.draw.rect( bildschirm, (0, 150, 0), (self.x + 3, 3, self.breite, self.luecke_y - self.luecke // 2), ) pygame.draw.rect( bildschirm, GRUEN, (self.x, 0, self.breite, self.luecke_y - self.luecke // 2), ) pygame.draw.rect( bildschirm, DUNKELGRUEN, (self.x - 5, self.luecke_y - self.luecke // 2 - 30, self.breite + 10, 30), ) pygame.draw.rect( bildschirm, (0, 150, 0), (self.x + 3, self.luecke_y + self.luecke // 2 + 3, self.breite, HOEHE), ) pygame.draw.rect( bildschirm, GRUEN, (self.x, self.luecke_y + self.luecke // 2, self.breite, HOEHE), ) pygame.draw.rect( bildschirm, DUNKELGRUEN, (self.x - 5, self.luecke_y + self.luecke // 2, self.breite + 10, 30), ) def ist_ausserhalb(self): return self.x + self.breite < 0 def kollision(self, vogel): vogel_rect = vogel.get_rect() oberes_rohr = pygame.Rect( self.x, 0, self.breite, self.luecke_y - self.luecke // 2 ) unteres_rohr = pygame.Rect( self.x, self.luecke_y + self.luecke // 2, self.breite, HOEHE ) return vogel_rect.colliderect(oberes_rohr) or vogel_rect.colliderect( unteres_rohr ) def punkt_erzielt(self, vogel): if not self.vorbei and vogel.x > self.x + self.breite: self.vorbei = True return True return False class Wolke: def __init__(self): self.x = BREITE + random.randint(0, 200) self.y = random.randint(50, 200) self.geschwindigkeit = random.uniform(0.5, 1.5) self.groesse = random.randint(30, 60) def bewegen(self): self.x -= self.geschwindigkeit if self.x < -100: self.x = BREITE + random.randint(0, 200) self.y = random.randint(50, 200) def zeichnen(self): pygame.draw.circle(bildschirm, WEISS, (int(self.x), int(self.y)), self.groesse) pygame.draw.circle( bildschirm, WEISS, (int(self.x - self.groesse / 2), int(self.y)), int(self.groesse * 0.8), ) pygame.draw.circle( bildschirm, WEISS, (int(self.x + self.groesse / 2), int(self.y)), int(self.groesse * 0.8), ) def zeichne_boden(): pygame.draw.rect(bildschirm, BRAUN, (0, HOEHE - 50, BREITE, 50)) for x in range(0, BREITE, 20): pygame.draw.rect(bildschirm, (0, 150, 0), (x, HOEHE - 50, 20, 10)) def zeige_startbildschirm(): bildschirm.fill(HIMMEL_BLAU) titel = schrift.render("FLAPPY BIRD", True, GELB) titel_rect = titel.get_rect(center=(BREITE // 2, HOEHE // 3)) bildschirm.blit(titel, titel_rect) start = kleine_schrift.render("Klicke oder LEERTASTE", True, WEISS) start_rect = start.get_rect(center=(BREITE // 2, HOEHE // 2)) bildschirm.blit(start, start_rect) web = kleine_schrift.render("Web Edition", True, ORANGE) web_rect = web.get_rect(center=(BREITE // 2, HOEHE // 2 + 40)) bildschirm.blit(web, web_rect) pygame.display.flip() # Hauptfunktion für async async def main(): # Spielvariablen vogel = Vogel() rohre = [] rohr_timer = 0 punkte = 0 game_over = False wolken = [Wolke() for _ in range(3)] highscore = 0 spiel_gestartet = False laeuft = True while laeuft: # Events for ereignis in pygame.event.get(): if ereignis.type == pygame.QUIT: laeuft = False elif ereignis.type == pygame.KEYDOWN: if ereignis.key == pygame.K_SPACE: if not spiel_gestartet: spiel_gestartet = True elif not game_over: vogel.springen() else: # Neustart vogel = Vogel() rohre = [] rohr_timer = 0 punkte = 0 game_over = False elif ereignis.type == pygame.MOUSEBUTTONDOWN: # Maus-Support für Web if not spiel_gestartet: spiel_gestartet = True elif not game_over: vogel.springen() else: vogel = Vogel() rohre = [] rohr_timer = 0 punkte = 0 game_over = False if not spiel_gestartet: zeige_startbildschirm() await asyncio.sleep(0) # Wichtig für Web! continue if not game_over: # Spiellogik vogel.bewegen() for wolke in wolken: wolke.bewegen() rohr_timer += 1 if rohr_timer > 90: rohre.append(Rohr(BREITE)) rohr_timer = 0 for rohr in rohre[:]: rohr.bewegen() if rohr.ist_ausserhalb(): rohre.remove(rohr) if rohr.kollision(vogel): game_over = True if punkte > highscore: highscore = punkte if rohr.punkt_erzielt(vogel): punkte += 1 if vogel.y >= HOEHE - vogel.radius - 50: game_over = True if punkte > highscore: highscore = punkte # Zeichnen bildschirm.fill(HIMMEL_BLAU) for wolke in wolken: wolke.zeichnen() for rohr in rohre: rohr.zeichnen() zeichne_boden() vogel.zeichnen() # Punkte punkte_text = schrift.render(str(punkte), True, WEISS) punkte_schatten = schrift.render(str(punkte), True, (100, 100, 100)) punkte_rect = punkte_text.get_rect(center=(BREITE // 2, 50)) bildschirm.blit(punkte_schatten, (punkte_rect.x + 2, punkte_rect.y + 2)) bildschirm.blit(punkte_text, punkte_rect) if highscore > 0: hs_text = kleine_schrift.render(f"Best: {highscore}", True, GELB) bildschirm.blit(hs_text, (10, 10)) if game_over: game_over_text = schrift.render("GAME OVER", True, ROT) game_over_rect = game_over_text.get_rect( center=(BREITE // 2, HOEHE // 2 - 50) ) bildschirm.blit(game_over_text, game_over_rect) final_punkte = kleine_schrift.render(f"Punkte: {punkte}", True, WEISS) final_rect = final_punkte.get_rect(center=(BREITE // 2, HOEHE // 2)) bildschirm.blit(final_punkte, final_rect) if punkte == highscore and punkte > 0: neu_text = kleine_schrift.render("NEUER REKORD!", True, GELB) neu_rect = neu_text.get_rect(center=(BREITE // 2, HOEHE // 2 + 30)) bildschirm.blit(neu_text, neu_rect) restart_text = kleine_schrift.render("Klicke für Neustart", True, WEISS) restart_rect = restart_text.get_rect(center=(BREITE // 2, HOEHE // 2 + 60)) bildschirm.blit(restart_text, restart_rect) pygame.display.flip() uhr.tick(60) # Wichtig für Web-Export! await asyncio.sleep(0) pygame.quit() # Starte das Spiel if __name__ == "__main__": asyncio.run(main())