import pygame import sys import random import math # Initialize pygame pygame.init() # Game constants SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 GRAVITY = 0.5 JUMP_FORCE = -8 PIPE_SPEED = 3 PIPE_GAP = 200 PIPE_FREQUENCY = 1800 # milliseconds FLOOR_HEIGHT = 100 BIRD_RADIUS = 20 # Colors SKY_BLUE = (113, 197, 207) GREEN = (111, 196, 69) DARK_GREEN = (76, 145, 65) BROWN = (160, 120, 40) WHITE = (255, 255, 255) BLACK = (0, 0, 0) YELLOW = (255, 221, 45) ORANGE = (255, 148, 31) RED = (231, 76, 60) # Set up display screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption("Flappy Bird Clone") clock = pygame.time.Clock() # Font setup font = pygame.font.SysFont(None, 48) small_font = pygame.font.SysFont(None, 32) class Bird: def __init__(self): self.x = SCREEN_WIDTH // 4 self.y = SCREEN_HEIGHT // 2 self.velocity = 0 self.alive = True self.angle = 0 def jump(self): self.velocity = JUMP_FORCE self.angle = -30 # Tilt up when jumping def update(self): # Apply gravity self.velocity += GRAVITY self.y += self.velocity # Rotate bird based on velocity if self.velocity < 0: self.angle = max(-30, self.angle - 3) else: self.angle = min(70, self.angle + 2) # Floor collision if self.y >= SCREEN_HEIGHT - FLOOR_HEIGHT - BIRD_RADIUS: self.y = SCREEN_HEIGHT - FLOOR_HEIGHT - BIRD_RADIUS self.velocity = 0 self.alive = False # Ceiling collision if self.y <= BIRD_RADIUS: self.y = BIRD_RADIUS self.velocity = 0 def draw(self): # Save the current transformation matrix original_surface = screen.copy() # Draw the bird body pygame.draw.circle(screen, YELLOW, (self.x, self.y), BIRD_RADIUS) # Draw the bird eye pygame.draw.circle(screen, WHITE, (self.x + 8, self.y - 5), 8) pygame.draw.circle(screen, BLACK, (self.x + 10, self.y - 5), 4) # Draw the bird beak beak_points = [ (self.x + 15, self.y), (self.x + 35, self.y - 5), (self.x + 35, self.y + 5) ] pygame.draw.polygon(screen, ORANGE, beak_points) # Draw the wing wing_points = [ (self.x - 10, self.y), (self.x - 15, self.y - 15), (self.x, self.y - 5) ] pygame.draw.polygon(screen, ORANGE, wing_points) # Create a rotated surface for the bird rotated_bird = pygame.Surface((BIRD_RADIUS * 2, BIRD_RADIUS * 2), pygame.SRCALPHA) rotated_bird.blit(screen, (0, 0), (self.x - BIRD_RADIUS, self.y - BIRD_RADIUS, BIRD_RADIUS * 2, BIRD_RADIUS * 2)) rotated_bird = pygame.transform.rotate(rotated_bird, -self.angle) # Clear the original bird screen.blit(original_surface, (0, 0)) # Draw the rotated bird rotated_rect = rotated_bird.get_rect(center=(self.x, self.y)) screen.blit(rotated_bird, rotated_rect) def get_mask(self): # Return a simple collision mask (circle) return pygame.Rect(self.x - BIRD_RADIUS, self.y - BIRD_RADIUS, BIRD_RADIUS * 2, BIRD_RADIUS * 2) class Pipe: def __init__(self): self.x = SCREEN_WIDTH self.gap_y = random.randint(150, SCREEN_HEIGHT - FLOOR_HEIGHT - 150) self.width = 70 self.passed = False def update(self): self.x -= PIPE_SPEED def draw(self): # Draw top pipe pygame.draw.rect(screen, GREEN, (self.x, 0, self.width, self.gap_y - PIPE_GAP // 2)) pygame.draw.rect(screen, DARK_GREEN, (self.x - 5, self.gap_y - PIPE_GAP // 2 - 20, self.width + 10, 20)) # Draw bottom pipe pipe_top = self.gap_y + PIPE_GAP // 2 pygame.draw.rect(screen, GREEN, (self.x, pipe_top, self.width, SCREEN_HEIGHT - pipe_top)) pygame.draw.rect(screen, DARK_GREEN, (self.x - 5, pipe_top, self.width + 10, 20)) def collide(self, bird): bird_mask = bird.get_mask() # Top pipe collision top_pipe = pygame.Rect(self.x, 0, self.width, self.gap_y - PIPE_GAP // 2) # Bottom pipe collision bottom_pipe = pygame.Rect(self.x, self.gap_y + PIPE_GAP // 2, self.width, SCREEN_HEIGHT) if bird_mask.colliderect(top_pipe) or bird_mask.colliderect(bottom_pipe): return True return False class Cloud: def __init__(self): self.x = SCREEN_WIDTH + random.randint(0, 100) self.y = random.randint(50, SCREEN_HEIGHT // 2) self.speed = random.uniform(0.5, 1.5) self.size = random.randint(40, 80) def update(self): self.x -= self.speed if self.x < -self.size * 2: self.x = SCREEN_WIDTH + 50 self.y = random.randint(50, SCREEN_HEIGHT // 2) def draw(self): # Draw a fluffy cloud pygame.draw.circle(screen, WHITE, (self.x, self.y), self.size // 2) pygame.draw.circle(screen, WHITE, (self.x + self.size // 2, self.y - self.size // 4), self.size // 2) pygame.draw.circle(screen, WHITE, (self.x + self.size // 2, self.y + self.size // 4), self.size // 2) pygame.draw.circle(screen, WHITE, (self.x + self.size, self.y), self.size // 2) def draw_floor(): pygame.draw.rect(screen, BROWN, (0, SCREEN_HEIGHT - FLOOR_HEIGHT, SCREEN_WIDTH, FLOOR_HEIGHT)) # Draw grass on top of the floor pygame.draw.rect(screen, GREEN, (0, SCREEN_HEIGHT - FLOOR_HEIGHT, SCREEN_WIDTH, 20)) # Draw some grass details for i in range(0, SCREEN_WIDTH, 20): height = random.randint(5, 15) pygame.draw.line(screen, DARK_GREEN, (i, SCREEN_HEIGHT - FLOOR_HEIGHT), (i, SCREEN_HEIGHT - FLOOR_HEIGHT - height), 2) def draw_background(): # Sky screen.fill(SKY_BLUE) # Sun pygame.draw.circle(screen, YELLOW, (700, 80), 50) # Draw clouds for cloud in clouds: cloud.draw() def draw_game_over(score): overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA) overlay.fill((0, 0, 0, 150)) screen.blit(overlay, (0, 0)) game_over_text = font.render("Game Over", True, WHITE) score_text = font.render(f"Score: {score}", True, WHITE) restart_text = small_font.render("Press SPACE to Restart", True, WHITE) screen.blit(game_over_text, (SCREEN_WIDTH // 2 - game_over_text.get_width() // 2, SCREEN_HEIGHT // 2 - 60)) screen.blit(score_text, (SCREEN_WIDTH // 2 - score_text.get_width() // 2, SCREEN_HEIGHT // 2)) screen.blit(restart_text, (SCREEN_WIDTH // 2 - restart_text.get_width() // 2, SCREEN_HEIGHT // 2 + 60)) def draw_score(score): score_text = font.render(f"Score: {score}", True, WHITE) screen.blit(score_text, (20, 20)) def draw_start_screen(): screen.fill(SKY_BLUE) # Title title_text = font.render("Flappy Bird Clone", True, WHITE) screen.blit(title_text, (SCREEN_WIDTH // 2 - title_text.get_width() // 2, 100)) # Bird pygame.draw.circle(screen, YELLOW, (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2), 40) pygame.draw.circle(screen, WHITE, (SCREEN_WIDTH // 2 + 15, SCREEN_HEIGHT // 2 - 10), 15) pygame.draw.circle(screen, BLACK, (SCREEN_WIDTH // 2 + 20, SCREEN_HEIGHT // 2 - 10), 7) pygame.draw.polygon(screen, ORANGE, [ (SCREEN_WIDTH // 2 + 30, SCREEN_HEIGHT // 2), (SCREEN_WIDTH // 2 + 60, SCREEN_HEIGHT // 2 - 10), (SCREEN_WIDTH // 2 + 60, SCREEN_HEIGHT // 2 + 10) ]) # Instructions instruction_text = small_font.render("Press SPACE to Start", True, WHITE) screen.blit(instruction_text, (SCREEN_WIDTH // 2 - instruction_text.get_width() // 2, SCREEN_HEIGHT - 150)) # Draw some pipes pipe_width = 70 pipe_gap = 200 gap_y = SCREEN_HEIGHT // 2 # Left pipe pygame.draw.rect(screen, GREEN, (SCREEN_WIDTH // 2 - 200, 0, pipe_width, gap_y - pipe_gap // 2)) pygame.draw.rect(screen, DARK_GREEN, (SCREEN_WIDTH // 2 - 205, gap_y - pipe_gap // 2 - 20, pipe_width + 10, 20)) pygame.draw.rect(screen, GREEN, (SCREEN_WIDTH // 2 - 200, gap_y + pipe_gap // 2, pipe_width, SCREEN_HEIGHT)) pygame.draw.rect(screen, DARK_GREEN, (SCREEN_WIDTH // 2 - 205, gap_y + pipe_gap // 2, pipe_width + 10, 20)) # Right pipe pygame.draw.rect(screen, GREEN, (SCREEN_WIDTH // 2 + 130, 0, pipe_width, gap_y - pipe_gap // 2)) pygame.draw.rect(screen, DARK_GREEN, (SCREEN_WIDTH // 2 + 125, gap_y - pipe_gap // 2 - 20, pipe_width + 10, 20)) pygame.draw.rect(screen, GREEN, (SCREEN_WIDTH // 2 + 130, gap_y + pipe_gap // 2, pipe_width, SCREEN_HEIGHT)) pygame.draw.rect(screen, DARK_GREEN, (SCREEN_WIDTH // 2 + 125, gap_y + pipe_gap // 2, pipe_width + 10, 20)) # Draw floor draw_floor() # Game setup bird = Bird() pipes = [] clouds = [Cloud() for _ in range(5)] score = 0 game_state = "start" # "start", "playing", "game_over" last_pipe = pygame.time.get_ticks() # Main game loop while True: # Event handling for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: if game_state == "start": game_state = "playing" elif game_state == "playing": bird.jump() elif game_state == "game_over": # Reset game bird = Bird() pipes = [] score = 0 game_state = "playing" last_pipe = pygame.time.get_ticks() # Draw background draw_background() # Update and draw clouds for cloud in clouds: cloud.update() cloud.draw() # Draw floor draw_floor() if game_state == "start": draw_start_screen() elif game_state == "playing": # Update bird bird.update() # Generate new pipes current_time = pygame.time.get_ticks() if current_time - last_pipe > PIPE_FREQUENCY: pipes.append(Pipe()) last_pipe = current_time # Update pipes and check for score for pipe in pipes: pipe.update() # Check if bird passed the pipe if not pipe.passed and pipe.x + pipe.width < bird.x: pipe.passed = True score += 1 # Check for collisions if pipe.collide(bird): bird.alive = False game_state = "game_over" # Remove pipes that are off screen pipes = [pipe for pipe in pipes if pipe.x > -pipe.width] # Draw pipes for pipe in pipes: pipe.draw() # Draw bird bird.draw() # Draw score draw_score(score) # Check if bird hit the ground or ceiling if not bird.alive: game_state = "game_over" elif game_state == "game_over": # Draw pipes for pipe in pipes: pipe.draw() # Draw bird bird.draw() # Draw score draw_score(score) # Draw game over screen draw_game_over(score) # Update display pygame.display.flip() # Cap the frame rate clock.tick(60)

Comments