-
-
Save charlesfrye/a3788c61019c32cb7947f4f5b1c04818 to your computer and use it in GitHub Desktop.
"Flappy Bird" by DeepSeek-R1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pygame | |
import random | |
import sys | |
# Constants | |
SCREEN_WIDTH = 800 | |
SCREEN_HEIGHT = 600 | |
GRAVITY = 0.5 | |
JUMP_FORCE = -8 | |
PIPE_SPEED = 3 | |
PIPE_GAP = 200 | |
PIPE_WIDTH = 50 | |
LAND_HEIGHT = 50 | |
# Generate random colors | |
def random_light_color(): | |
return ( | |
random.randint(200, 255), | |
random.randint(200, 255), | |
random.randint(200, 255), | |
) | |
def random_dark_color(): | |
return (random.randint(0, 100), random.randint(0, 100), random.randint(0, 100)) | |
pipe_colors = [ | |
(47, 79, 47), # dark green | |
(139, 69, 19), # saddle brown | |
(64, 64, 64), # dark gray | |
] | |
land_colors = {"brown": (139, 69, 19), "yellow": (255, 215, 0)} | |
# Bird class | |
class Bird: | |
def __init__(self): | |
self.x = SCREEN_WIDTH // 4 | |
self.y = SCREEN_HEIGHT // 2 | |
self.color = random_dark_color() | |
self.shape = random.choice(["square", "circle", "triangle"]) | |
self.velocity = 0 # this line had to be fixed manually | |
self.rect = pygame.Rect(self.x, self.y, 30, 30) | |
def jump(self): | |
self.velocity = JUMP_FORCE | |
def update(self): | |
self.velocity += GRAVITY | |
self.y += self.velocity | |
self.rect.center = (self.x, self.y) | |
def draw(self, screen): | |
if self.shape == "square": | |
pygame.draw.rect(screen, self.color, self.rect) | |
elif self.shape == "circle": | |
pygame.draw.circle(screen, self.color, self.rect.center, 15) | |
elif self.shape == "triangle": | |
points = [ | |
(self.x, self.y - 15), | |
(self.x - 15, self.y + 15), | |
(self.x + 15, self.y + 15), | |
] | |
pygame.draw.polygon(screen, self.color, points) | |
# Pipe class | |
class Pipe: | |
def __init__(self): | |
self.gap_position = random.randint( | |
100, SCREEN_HEIGHT - LAND_HEIGHT - PIPE_GAP - 100 | |
) | |
self.top_pipe = pygame.Rect(SCREEN_WIDTH, 0, PIPE_WIDTH, self.gap_position) | |
self.bottom_pipe = pygame.Rect( | |
SCREEN_WIDTH, | |
self.gap_position + PIPE_GAP, | |
PIPE_WIDTH, | |
SCREEN_HEIGHT - (self.gap_position + PIPE_GAP) - LAND_HEIGHT, | |
) | |
self.color = random.choice(pipe_colors) | |
self.passed = False | |
def update(self): | |
self.top_pipe.x -= PIPE_SPEED | |
self.bottom_pipe.x -= PIPE_SPEED | |
def draw(self, screen): | |
pygame.draw.rect(screen, self.color, self.top_pipe) | |
pygame.draw.rect(screen, self.color, self.bottom_pipe) | |
def offscreen(self): | |
return self.top_pipe.right < 0 | |
# Game setup | |
def main(): | |
pygame.init() | |
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) | |
clock = pygame.time.Clock() | |
font = pygame.font.Font(None, 36) | |
bg_color = random_light_color() | |
land_color = random.choice(list(land_colors.values())) | |
bird = Bird() | |
pipes = [] | |
score = 0 | |
best_score = 0 | |
game_over = False | |
while True: | |
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 not game_over: | |
bird.jump() | |
else: | |
# Restart game | |
bg_color = random_light_color() | |
land_color = random.choice(list(land_colors.values())) | |
bird = Bird() | |
pipes = [] | |
score = 0 | |
game_over = False | |
if event.key == pygame.K_q or event.key == pygame.K_ESCAPE: | |
pygame.quit() | |
sys.exit() | |
if not game_over: | |
bird.update() | |
# Check ground collision | |
if bird.y + 15 >= SCREEN_HEIGHT - LAND_HEIGHT: | |
game_over = True | |
# Update pipes | |
for pipe in pipes: | |
pipe.update() | |
if pipe.offscreen(): | |
pipes.remove(pipe) | |
# Spawn new pipes | |
if len(pipes) == 0 or pipes[-1].top_pipe.x < SCREEN_WIDTH - 400: | |
pipes.append(Pipe()) | |
# Check pipe collisions | |
for pipe in pipes: | |
if bird.rect.colliderect(pipe.top_pipe) or bird.rect.colliderect( | |
pipe.bottom_pipe | |
): | |
game_over = True | |
# Update score | |
for pipe in pipes: | |
if bird.rect.left > pipe.top_pipe.right and not pipe.passed: | |
score += 1 | |
pipe.passed = True | |
if score > best_score: | |
best_score = score | |
# Draw everything | |
screen.fill(bg_color) | |
# Draw land | |
pygame.draw.rect( | |
screen, | |
land_color, | |
(0, SCREEN_HEIGHT - LAND_HEIGHT, SCREEN_WIDTH, LAND_HEIGHT), | |
) | |
# Draw bird | |
bird.draw(screen) | |
# Draw pipes | |
for pipe in pipes: | |
pipe.draw(screen) | |
# Draw score | |
score_text = font.render(f"Score: {score}", True, (0, 0, 0)) | |
screen.blit(score_text, (SCREEN_WIDTH - 150, 20)) | |
if game_over: | |
game_over_text = font.render( | |
f"Game Over! Best Score: {best_score}", True, (0, 0, 0) | |
) | |
screen.blit( | |
game_over_text, (SCREEN_WIDTH // 2 - 150, SCREEN_HEIGHT // 2 - 50) | |
) | |
restart_text = font.render("Press SPACE to Restart", True, (0, 0, 0)) | |
screen.blit(restart_text, (SCREEN_WIDTH // 2 - 150, SCREEN_HEIGHT // 2)) | |
pygame.display.update() | |
clock.tick(60) | |
if __name__ == "__main__": | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Create a Flappy Bird game in Python. You must include these things: | |
You must use pygame. | |
The background color should be randomly chosen and is a light shade. Start with a light blue color. | |
Pressing SPACE multiple times will accelerate the bird. | |
The bird's shape should be randomly chosen as a square, circle or triangle. The color should be randomly chosen as a dark color. | |
Place on the bottom some land colored as dark brown or yellow chosen randomly. | |
Make a score shown on the top right side. Increment if you pass pipes and don't hit them. | |
Make randomly spaced pipes with enough space. Color them randomly as dark green or light brown or a dark gray shade. | |
When you lose, show the best score. Make the text inside the screen. Pressing q or Esc will quit the game. Restarting is pressing SPACE again. | |
The final game should be inside a markdown section in Python. Check your code for errors and fix them before the final markdown section. | |
Okay, I need to create a Flappy Bird game in Python using pygame. Let's start by setting up the basic structure. First, I'll import pygame and other necessary modules. Then, initialize pygame and set up the game window. The background color should be a light shade, starting with light blue. Hmm, I'll create a tuple for that, maybe (135, 206, 250) for sky blue. But the user wants the background color to be randomly chosen as a light shade. So I need a function to generate a random light color. How to do that? Maybe by generating RGB values where each component is between 200 and 255 to ensure it's a light color. | |
Next, the bird. The bird's shape can be square, circle, or triangle. The color should be a dark color. So for the color, I'll generate RGB values where each component is between 0 and 100. The shape selection can be done by randomly choosing from a list of options. The bird's movement: pressing SPACE makes it accelerate. So each time the user presses SPACE, the bird's velocity increases. I'll need to track the bird's y position and apply gravity, with jumps when SPACE is pressed. | |
Pipes: they need to be randomly spaced with enough space. The color should be randomly chosen from dark green, light brown, or dark gray. So I'll create a list of these colors and randomly select one for each pipe. The spacing between the pipes should have a gap where the bird can pass. The pipes are placed at random heights but must have a consistent gap. The bird passes through the gap, and each time it does, the score increases. The score is displayed on the top right. | |
The land at the bottom should be dark brown or yellow, chosen randomly. So, when the game starts, I'll randomly pick between these two colors and draw a rectangle at the bottom. | |
Handling collisions: if the bird hits a pipe or the ground, the game ends. When the game is over, display the best score. The best score is the highest score achieved during the session. The game over screen should have text indicating the best score, and options to quit (q or Esc) or restart (SPACE). | |
I need to structure the code. Start by defining classes for the Bird and Pipe. The Bird class will handle the bird's position, shape, color, and movement. The Pipe class will manage the creation and movement of pipes. The main game loop will handle events, update the game state, and render everything. | |
Let's outline the steps: | |
1. Initialize pygame and set up the window. | |
2. Define functions for generating random colors (background, bird, pipes, land). | |
3. Create Bird class with properties: position, color, shape, and physics (gravity, jump velocity). | |
4. Create Pipe class to generate pairs of pipes with a gap. The gap's position is random but within a certain range. | |
5. Manage the game loop with states: playing, game over. | |
6. Handle user input: SPACE to jump, q/Esc to quit, SPACE to restart after game over. | |
7. Track the score, updating when the bird passes a pipe. | |
8. Check collisions between bird and pipes or ground. | |
9. Display score and best score on the screen. | |
10. Implement restart functionality. | |
Potential issues: ensuring that pipes are generated correctly with the right spacing, handling the bird's jump acceleration (multiple presses increase velocity), correctly drawing different shapes for the bird, and handling the game states properly. | |
Testing each component separately. For example, the bird's movement: applying gravity and jump mechanics. When the user presses SPACE, the bird's velocity decreases (since it's moving up). Each press adds to the velocity. Wait, no—typically, in Flappy Bird, a tap gives a fixed upward velocity. Maybe each press gives a boost. So every time SPACE is pressed, the bird's velocity is set to a negative value (since y increases downwards in pygame). Hmm, maybe the bird has a vertical velocity, and each SPACE press adds a negative acceleration (like a jump). So in each frame, apply gravity (velocity increases), and on jump, velocity decreases. | |
The code structure: | |
- Use pygame.sprite.Sprite for Bird and Pipes? Maybe, but perhaps simpler without Sprites for simplicity. | |
Set up constants like SCREEN_WIDTH and SCREEN_HEIGHT. Let's say 800x600. | |
The bird starts in the middle. The pipes move from the right to the left. Each pipe pair has a top and bottom pipe. The gap is the space where the bird can pass. | |
Score increases when a pipe pair is passed. Need to track which pipes have been passed. | |
Now, putting this into code. | |
First, the imports: | |
import pygame | |
import random | |
import sys | |
Then, define constants: | |
SCREEN_WIDTH = 800 | |
SCREEN_HEIGHT = 600 | |
GRAVITY = 0.5 | |
JUMP_FORCE = -8 | |
PIPE_SPEED = 3 | |
PIPE_GAP = 200 | |
PIPE_WIDTH = 50 | |
LAND_HEIGHT = 50 | |
Then, colors: | |
def random_light_color(): | |
return (random.randint(200, 255), random.randint(200, 255), random.randint(200, 255)) | |
def random_dark_color(): | |
return (random.randint(0, 100), random.randint(0, 100), random.randint(0, 100)) | |
pipe_colors = [ | |
(47, 79, 47), # dark green | |
(139, 69, 19), # light brown (saddlebrown) | |
(64, 64, 64) # dark gray | |
] | |
land_colors = { | |
'brown': (139, 69, 19), | |
'yellow': (255, 215, 0) | |
} | |
Then, Bird class: | |
class Bird: | |
def __init__(self): | |
self.x = SCREEN_WIDTH // 4 | |
self.y = SCREEN_HEIGHT // 2 | |
self.color = random_dark_color() | |
self.shape = random.choice(['square', 'circle', 'triangle']) | |
self.velocity = 0 | |
self.rect = pygame.Rect(self.x, self.y, 30, 30) # assuming size 30x30 | |
def jump(self): | |
self.velocity = JUMP_FORCE | |
def update(self): | |
self.velocity += GRAVITY | |
self.y += self.velocity | |
self.rect.center = (self.x, self.y) | |
def draw(self, screen): | |
if self.shape == 'square': | |
pygame.draw.rect(screen, self.color, self.rect) | |
elif self.shape == 'circle': | |
pygame.draw.circle(screen, self.color, self.rect.center, 15) | |
elif self.shape == 'triangle': | |
# Triangle points: maybe three points around the center | |
points = [(self.x, self.y - 15), (self.x - 15, self.y + 15), (self.x + 15, self.y + 15)] | |
pygame.draw.polygon(screen, self.color, points) | |
Wait, the bird's shape is square, circle, or triangle. So for the square, a rectangle. For circle, a circle. For triangle, a polygon with three points. The size is 30x30? Maybe adjust based on shape. | |
Pipe class: | |
class Pipe: | |
def __init__(self): | |
self.top_pipe = pygame.Rect(0, 0, PIPE_WIDTH, 0) | |
self.bottom_pipe = pygame.Rect(0, 0, PIPE_WIDTH, 0) | |
self.color = random.choice(pipe_colors) | |
self.passed = False | |
self.x = SCREEN_WIDTH | |
self.gap_position = random.randint(100, SCREEN_HEIGHT - LAND_HEIGHT - 100 - PIPE_GAP) | |
self.top_pipe = pygame.Rect(self.x, 0, PIPE_WIDTH, self.gap_position) | |
self.bottom_pipe = pygame.Rect(self.x, self.gap_position + PIPE_GAP, PIPE_WIDTH, SCREEN_HEIGHT - (self.gap_position + PIPE_GAP) - LAND_HEIGHT) | |
# bottom_pipe starts at gap_position + gap, height is from that point to the bottom (minus land height) | |
# Wait, the bottom pipe should be from gap_position + gap to the bottom, but subtract land height? | |
# Maybe adjust the bottom pipe's height to SCREEN_HEIGHT - (gap_position + PIPE_GAP) - LAND_HEIGHT | |
# That way, the bottom pipe's height is from gap_position + PIPE_GAP to SCREEN_HEIGHT - LAND_HEIGHT | |
def update(self): | |
self.top_pipe.x -= PIPE_SPEED | |
self.bottom_pipe.x -= PIPE_SPEED | |
def draw(self, screen): | |
pygame.draw.rect(screen, self.color, self.top_pipe) | |
pygame.draw.rect(screen, self.color, self.bottom_pipe) | |
def offscreen(self): | |
return self.top_pipe.right < 0 | |
Now, the game loop: | |
def main(): | |
pygame.init() | |
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) | |
clock = pygame.time.Clock() | |
bg_color = random_light_color() | |
land_color = random.choice(list(land_colors.values())) | |
bird = Bird() | |
pipes = [] | |
score = 0 | |
best_score =DangerousError | |
running = True | |
game_over = False | |
font = pygame.font.Font(None, 36) | |
while running: | |
# Handle events | |
for event in pygame.event.get(): | |
if event.type == pygame.QUIT: | |
running = False | |
if event.type == pygame.KEYDOWN: | |
if event.key == pygame.K_SPACE: | |
if not game_over: | |
bird.jump() | |
else: | |
# Restart the game | |
bg_color = random_light_color() | |
land_color = random.choice(list(land_colors.values())) | |
bird = Bird() | |
pipes = [] | |
score = 0 | |
game_over = False | |
if event.key == pygame.K_q or event.key == pygame.K_ESCAPE: | |
running = False | |
if not game_over: | |
# Update game state | |
bird.update() | |
# Check for collision with ground | |
if bird.y + 15 >= SCREEN_HEIGHT - LAND_HEIGHT: | |
game_over = True | |
# Update pipes | |
for pipe in pipes: | |
pipe.update() | |
if pipe.top_pipe.right < 0: | |
pipes.remove(pipe) | |
# Add new pipes | |
if len(pipes) == 0 or pipes[-1].top_pipe.x < SCREEN_WIDTH - 400: | |
pipes.append(Pipe()) | |
# Check for collisions with pipes | |
for pipe in pipes: | |
if bird.rect.colliderect(pipe.top_pipe) or bird.rect.colliderect(pipe.bottom_pipe): | |
game_over = True | |
# Update score | |
for pipe in pipes: | |
if bird.x > pipe.top_pipe.right and not pipe.passed: | |
score += 1 | |
pipe.passed = True | |
# Check best score | |
if score > best_score: | |
best_score = score | |
else: | |
# Game over state | |
pass | |
# Draw everything | |
screen.fill(bg_color) | |
# Draw land | |
pygame.draw.rect(screen, land_color, pygame.Rect(0, SCREEN_HEIGHT - LAND_HEIGHT, SCREEN_WIDTH, LAND_HEIGHT)) | |
# Draw bird | |
bird.draw(screen) | |
# Draw pipes | |
for pipe in pipes: | |
pipe.draw(screen) | |
# Draw score | |
score_text = font.render(f'Score: {score}', True, (0, 0, 0)) | |
screen.blit(score_text, (SCREEN_WIDTH - 150, 20)) | |
if game_over: | |
# Draw game over text and best score | |
go_text = font.render('Game Over! Best Score: {}'.format(best_score), True, (0, 0, 0)) | |
screen.blit(go_text, (SCREEN_WIDTH//2 - 150, SCREEN_HEIGHT//2 - 50)) | |
restart_text = font.render('Press SPACE to restart', True, (0, 0, 0)) | |
screen.blit(restart_text, (SCREEN_WIDTH//2 - 150, SCREEN_HEIGHT//2)) | |
pygame.display.update() | |
clock.tick(60) | |
pygame.quit() | |
if __name__ == '__main__': | |
main() | |
Wait, let's check for errors. In the Bird class, the jump method sets velocity to JUMP_FORCE. Then, in update, velocity increases by GRAVITY. That's correct. The bird's y position is updated, and the rect is updated. | |
In the Pipe class, when creating a new pipe, the gap_position is random. The top pipe is from 0 to gap_position, and the bottom pipe starts at gap_position + PIPE_GAP. Wait, the top pipe's height is gap_position, starting at 0. The bottom pipe's height is from gap_position + PIPE_GAP to SCREEN_HEIGHT - LAND_HEIGHT. Hmm, perhaps the bottom pipe's height is SCREEN_HEIGHT - (gap_position + PIPE_GAP) - LAND_HEIGHT. That may not be correct. Maybe the bottom pipe starts at gap_position + PIPE_GAP and has height SCREEN_HEIGHT - (gap_position + PIPE_GAP) - LAND_HEIGHT. | |
Wait, perhaps the correct calculation is: | |
The top pipe is from 0 to gap_position, so height is gap_position. | |
The bottom pipe starts at gap_position + PIPE_GAP, and its height is from that point to the bottom (SCREEN_HEIGHT - LAND_HEIGHT), so the height is SCREEN_HEIGHT - LAND_HEIGHT - (gap_position + PIPE_GAP). | |
But in the Pipe's __init__: | |
self.bottom_pipe = pygame.Rect(self.x, self.gap_position + PIPE_GAP, PIPE_WIDTH, SCREEN_HEIGHT - (self.gap_position + PIPE_GAP) - LAND_HEIGHT) | |
Yes, that's how it's set. So the bottom pipe's y position is gap_position + PIPE_GAP, and its height is from that point to the bottom (minus land height). So the height is SCREEN_HEIGHT - (gap_position + PIPE_GAP) - LAND_HEIGHT. | |
But when the gap_position is, say, 200, then the bottom pipe starts at 200 + gap (200 + 200=400), and height is 600 - 400 - 50 (LAND_HEIGHT) = 150. So the bottom pipe is from 400 to 550 (600-50=550). But that's incorrect because the LAND_HEIGHT is subtracted at the bottom. | |
Yes, the land is at the bottom, 50 pixels high. So the bottom pipe must end at SCREEN_HEIGHT - LAND_HEIGHT. | |
Hmm, perhaps the bottom pipe's height is SCREEN_HEIGHT - (gap_position + PIPE_GAP) - LAND_HEIGHT. So the calculation is correct. | |
In the game loop, new pipes are added when the last pipe is at some distance (e.g., 400 pixels away). Wait, the code checks if pipes[-1].top_pipe.x < SCREEN_WIDTH - 400. That may not be the best way to spawn pipes. Alternative approach: use a timer or distance-based spawning. Maybe using a time-based approach, but perhaps the current code may work. | |
For collision detection, the bird's rect is checked against the top and bottom pipes. Also, the ground (y + 15 >= SCREEN_HEIGHT - LAND_HEIGHT). The bird's size is 30x30, so radius 15. So when the bird's y is 600 - 50 (land) - 15, it's touching the land. | |
The score is incremented when the bird passes a pipe. The code checks if bird.x > pipe.top_pipe.right and pipe hasn't been passed yet. That's a possible way, but maybe better to check when the pipe's x is behind the bird. | |
Handling game over: when the bird hits a pipe or the ground, game_over is set to True. | |
In the game over screen, the best score is displayed. Pressing SPACE restarts the game with new colors and resets variables. | |
Potential issues: | |
- The bird's shape drawing: for the triangle, the points may not be correctly centered. Need to adjust the points based on the bird's position. | |
- Pipe generation: the code adds a new pipe when the last pipe is at a certain x position. But the initial pipe spawn may happen too quickly. Maybe using a timer or frame-based spawning. | |
- The bird's velocity and gravity may need tweaking for smoother movement. | |
- The score increment may not be accurate. It's checked for each pipe, and if the bird's x is beyond the pipe's right, it's counted. But since pipes are moving left, once the bird has passed the pipe's right edge, the score increases. | |
Testing: Ensure that the bird can jump, the pipes move, collision detection works, and the game restarts correctly. | |
Now, putting all this together into a markdown section as a code block. | |
</think> | |
```python | |
import pygame | |
import random | |
import sys | |
# Constants | |
SCREEN_WIDTH = 800 | |
SCREEN_HEIGHT = 600 | |
GRAVITY = 0.5 | |
JUMP_FORCE = -8 | |
PIPE_SPEED = 3 | |
PIPE_GAP = 200 | |
PIPE_WIDTH = 50 | |
LAND_HEIGHT = 50 | |
# Generate random colors | |
def random_light_color(): | |
return (random.randint(200, 255), random.randint(200, 255), random.randint(200, 255)) | |
def random_dark_color(): | |
return (random.randint(0, 100), random.randint(0, 100), random.randint(0, 100)) | |
pipe_colors = [ | |
(47, 79, 47), # dark green | |
(139, 69, 19), # saddle brown | |
(64, 64, 64) # dark gray | |
] | |
land_colors = { | |
'brown': (139, 69, 19), | |
'yellow': (255, 215, 0) | |
} | |
# Bird class | |
class Bird: | |
def __init__(self): | |
self.x = SCREEN_WIDTH // 4 | |
self.y = SCREEN_HEIGHT // 2 | |
self.color = random_dark_color() | |
self.shape = random.choice(['square', 'circle', 'triangle']) | |
self.velocity =DangerousError | |
self.rect = pygame.Rect(self.x, self.y, 30, 30) | |
def jump(self): | |
self.velocity = JUMP_FORCE | |
def update(self): | |
self.velocity += GRAVITY | |
self.y += self.velocity | |
self.rect.center = (self.x, self.y) | |
def draw(self, screen): | |
if self.shape == 'square': | |
pygame.draw.rect(screen, self.color, self.rect) | |
elif self.shape == 'circle': | |
pygame.draw.circle(screen, self.color, self.rect.center, 15) | |
elif self.shape == 'triangle': | |
points = [(self.x, self.y - 15), (self.x - 15, self.y + 15), (self.x + 15, self.y + 15)] | |
pygame.draw.polygon(screen, self.color, points) | |
# Pipe class | |
class Pipe: | |
def __init__(self): | |
self.gap_position = random.randint(100, SCREEN_HEIGHT - LAND_HEIGHT - PIPE_GAP - 100) | |
self.top_pipe = pygame.Rect(SCREEN_WIDTH, 0, PIPE_WIDTH, self.gap_position) | |
self.bottom_pipe = pygame.Rect(SCREEN_WIDTH, self.gap_position + PIPE_GAP, PIPE_WIDTH, SCREEN_HEIGHT - (self.gap_position + PIPE_GAP) - LAND_HEIGHT) | |
self.color = random.choice(pipe_colors) | |
self.passed = False | |
def update(self): | |
self.top_pipe.x -= PIPE_SPEED | |
self.bottom_pipe.x -= PIPE_SPEED | |
def draw(self, screen): | |
pygame.draw.rect(screen, self.color, self.top_pipe) | |
pygame.draw.rect(screen, self.color, self.bottom_pipe) | |
def offscreen(self): | |
return self.top_pipe.right < 0 | |
# Game setup | |
def main(): | |
pygame.init() | |
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) | |
clock = pygame.time.Clock() | |
font = pygame.font.Font(None, 36) | |
bg_color = random_light_color() | |
land_color = random.choice(list(land_colors.values())) | |
bird = Bird() | |
pipes = [] | |
score = 0 | |
best_score = 0 | |
game_over = False | |
while True: | |
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 not game_over: | |
bird.jump() | |
else: | |
# Restart game | |
bg_color = random_light_color() | |
land_color = random.choice(list(land_colors.values())) | |
bird = Bird() | |
pipes = [] | |
score = 0 | |
game_over = False | |
if event.key == pygame.K_q or event.key == pygame.K_ESCAPE: | |
pygame.quit() | |
sys.exit() | |
if not game_over: | |
bird.update() | |
# Check ground collision | |
if bird.y + 15 >= SCREEN_HEIGHT - LAND_HEIGHT: | |
game_over = True | |
# Update pipes | |
for pipe in pipes: | |
pipe.update() | |
if pipe.offscreen(): | |
pipes.remove(pipe) | |
# Spawn new pipes | |
if len(pipes) == 0 or pipes[-1].top_pipe.x < SCREEN_WIDTH - 400: | |
pipes.append(Pipe()) | |
# Check pipe collisions | |
for pipe in pipes: | |
if bird.rect.colliderect(pipe.top_pipe) or bird.rect.colliderect(pipe.bottom_pipe): | |
game_over = True | |
# Update score | |
for pipe in pipes: | |
if bird.rect.left > pipe.top_pipe.right and not pipe.passed: | |
score += 1 | |
pipe.passed = True | |
if score > best_score: | |
best_score = score | |
# Draw everything | |
screen.fill(bg_color) | |
# Draw land | |
pygame.draw.rect(screen, land_color, (0, SCREEN_HEIGHT - LAND_HEIGHT, SCREEN_WIDTH, LAND_HEIGHT)) | |
# Draw bird | |
bird.draw(screen) | |
# Draw pipes | |
for pipe in pipes: | |
pipe.draw(screen) | |
# Draw score | |
score_text = font.render(f'Score: {score}', True, (0, 0, 0)) | |
screen.blit(score_text, (SCREEN_WIDTH - 150, 20)) | |
if game_over: | |
game_over_text = font.render(f'Game Over! Best Score: {best_score}', True, (0, 0, 0)) | |
screen.blit(game_over_text, (SCREEN_WIDTH//2 - 150, SCREEN_HEIGHT//2 - 50)) | |
restart_text = font.render('Press SPACE to Restart', True, (0, 0, 0)) | |
screen.blit(restart_text, (SCREEN_WIDTH//2 - 150, SCREEN_HEIGHT//2)) | |
pygame.display.update() | |
clock.tick(60) | |
if __name__ == "__main__": | |
main() | |
``` [end of text] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment