python小游戏“笨鸟先飞”
import pygame
import sys
import random
import os
pygame.init()
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
GRAVITY = 0.5
JUMP_FORCE = -10
PIPE_SPEED = 5
PIPE_FREQUENCY = 1500
BIRD_SIZE = 25
PIPE_WIDTH = 70
PIPE_GAP = 210
MIN_PIPE_HEIGHT = 120
GROUND_HEIGHT = 100
SKY_BLUE = (135, 206, 235)
GREEN = (34, 139, 34)
BROWN = (139, 69, 19)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
CLOUD_COLOR = (250, 250, 250)
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("笨鸟先飞")
def create_font(size):
try:
font = pygame.font.SysFont('simhei', size)
test_surface = font.render("测试", True, WHITE)
if test_surface.get_width() > 0:
return font
except:
pass
return pygame.font.Font(None, size)
font = create_font(48)
small_font = create_font(36)
tiny_font = create_font(24)
class Bird:
def init(self):
self.x = SCREEN_WIDTH // 4
self.y = SCREEN_HEIGHT // 2
self.velocity = 0
self.alive = True
self.rotation = 0
self.flap_counter = 0
self.wing_up = False
def jump(self):
if self.alive:
self.velocity = JUMP_FORCE
self.flap_counter = 5
def update(self):
self.velocity += GRAVITY
self.y += self.velocity
self.rotation = max(-30, min(self.velocity * 3, 90))
if self.flap_counter > 0:
self.flap_counter -= 1
if self.flap_counter == 0:
self.wing_up = not self.wing_up
if self.y < 0:
self.y = 0
self.velocity = 0
if self.y > SCREEN_HEIGHT - GROUND_HEIGHT - BIRD_SIZE:
self.y = SCREEN_HEIGHT - GROUND_HEIGHT - BIRD_SIZE
self.velocity = 0
self.alive = False
def draw(self, surface):
bird_center = (self.x, self.y)
pygame.draw.circle(surface, YELLOW, bird_center, BIRD_SIZE // 2)
eye_center = (self.x + BIRD_SIZE // 3, self.y - BIRD_SIZE // 3)
pygame.draw.circle(surface, WHITE, eye_center, BIRD_SIZE // 3)
pygame.draw.circle(surface, BLACK, eye_center, BIRD_SIZE // 6)
beak_points = [
(self.x + BIRD_SIZE // 1.5, self.y),
(self.x + BIRD_SIZE * 1.5, self.y - BIRD_SIZE // 3),
(self.x + BIRD_SIZE * 1.5, self.y + BIRD_SIZE // 3)
]
pygame.draw.polygon(surface, RED, beak_points)
wing_y_offset = -BIRD_SIZE // 6 if self.wing_up else BIRD_SIZE // 6
wing_points = [
(self.x - BIRD_SIZE // 3, self.y),
(self.x, self.y + wing_y_offset),
(self.x + BIRD_SIZE // 3, self.y)
]
pygame.draw.polygon(surface, (200, 200, 0), wing_points)
def get_mask(self):
return pygame.Rect(self.x - BIRD_SIZE // 2, self.y - BIRD_SIZE // 2, BIRD_SIZE, BIRD_SIZE)
class Pipe:
def init(self):
self.x = SCREEN_WIDTH
min_gap_y = MIN_PIPE_HEIGHT + PIPE_GAP
max_gap_y = SCREEN_HEIGHT - GROUND_HEIGHT - MIN_PIPE_HEIGHT
gap_y = random.randint(min_gap_y, max_gap_y)
self.height = gap_y - PIPE_GAP
self.passed = False
self.top_rect = pygame.Rect(self.x, 0, PIPE_WIDTH, self.height)
self.bottom_rect = pygame.Rect(
self.x,
self.height + PIPE_GAP,
PIPE_WIDTH,
SCREEN_HEIGHT - self.height - PIPE_GAP - GROUND_HEIGHT
)
def update(self):
self.x -= PIPE_SPEED
self.top_rect.x = self.x
self.bottom_rect.x = self.x
def draw(self, surface):
pygame.draw.rect(surface, GREEN, self.top_rect)
pygame.draw.rect(surface, (0, 100, 0), self.top_rect, 3)
pygame.draw.rect(surface, (0, 100, 0),
(self.x - 5, self.height - 20, PIPE_WIDTH + 10, 20))
pygame.draw.rect(surface, GREEN, self.bottom_rect)
pygame.draw.rect(surface, (0, 100, 0), self.bottom_rect, 3)
pygame.draw.rect(surface, (0, 100, 0),
(self.x - 5, self.height + PIPE_GAP, PIPE_WIDTH + 10, 20))
def collide(self, bird):
bird_mask = bird.get_mask()
return bird_mask.colliderect(self.top_rect) or bird_mask.colliderect(self.bottom_rect)
class Cloud:
def init(self):
self.x = SCREEN_WIDTH + random.randint(0, 300)
self.y = random.randint(50, SCREEN_HEIGHT // 3)
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 + random.randint(0, 200)
self.y = random.randint(50, SCREEN_HEIGHT // 3)
def draw(self, surface):
pygame.draw.circle(surface, CLOUD_COLOR, (self.x, self.y), self.size)
pygame.draw.circle(surface, CLOUD_COLOR, (self.x + self.size * 0.8, self.y - self.size * 0.3), self.size * 0.7)
pygame.draw.circle(surface, CLOUD_COLOR, (self.x + self.size * 0.8, self.y + self.size * 0.3), self.size * 0.7)
pygame.draw.circle(surface, CLOUD_COLOR, (self.x + self.size * 1.6, self.y), self.size * 0.6)
class Game:
def init(self):
self.bird = Bird()
self.pipes = []
self.clouds = [Cloud() for _ in range(5)]
self.score = 0
self.game_over = False
self.last_pipe = pygame.time.get_ticks()
self.scroll_speed = 0
self.ground_offset = 0
self.flash_counter = 0
self.debug_info = ""
def handle_events(self):
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 self.game_over:
self.init()
else:
self.bird.jump()
elif event.key == pygame.K_d:
self.debug_info = f"小鸟位置: ({self.bird.x:.1f}, {self.bird.y:.1f}) 速度: {self.bird.velocity:.1f}"
if event.type == pygame.MOUSEBUTTONDOWN:
if self.game_over:
self.init()
else:
self.bird.jump()
def update(self):
if not self.game_over:
self.bird.update()
time_now = pygame.time.get_ticks()
if time_now - self.last_pipe > PIPE_FREQUENCY:
self.pipes.append(Pipe())
self.last_pipe = time_now
for pipe in self.pipes[:]:
pipe.update()
if pipe.collide(self.bird):
self.bird.alive = False
self.game_over = True
self.flash_counter = 10
if not pipe.passed and pipe.x < self.bird.x - PIPE_WIDTH // 2:
pipe.passed = True
self.score += 1
if pipe.x < -PIPE_WIDTH:
self.pipes.remove(pipe)
for cloud in self.clouds:
cloud.update()
self.scroll_speed = PIPE_SPEED
self.ground_offset = (self.ground_offset - self.scroll_speed) % 35
if not self.bird.alive:
self.game_over = True
if self.flash_counter > 0:
self.flash_counter -= 1
def draw(self, surface):
surface.fill(SKY_BLUE)
pygame.draw.circle(surface, (255, 255, 200), (700, 80), 60)
pygame.draw.circle(surface, (255, 215, 0), (700, 80), 50)
for cloud in self.clouds:
cloud.draw(surface)
for pipe in self.pipes:
pipe.draw(surface)
if self.flash_counter == 0 or self.flash_counter % 2 == 0:
self.bird.draw(surface)
pygame.draw.rect(surface, BROWN, (0, SCREEN_HEIGHT - GROUND_HEIGHT, SCREEN_WIDTH, GROUND_HEIGHT))
for i in range(0, SCREEN_WIDTH, 35):
pygame.draw.rect(surface, (160, 82, 45),
(i + self.ground_offset, SCREEN_HEIGHT - GROUND_HEIGHT, 30, 10))
score_text = font.render(f"得分: {self.score}", True, WHITE)
surface.blit(score_text, (20, 20))
if self.game_over:
game_over_text = font.render("游戏结束!", True, RED)
restart_text = small_font.render("按空格键重新开始", True, WHITE)
surface.blit(game_over_text, (SCREEN_WIDTH // 2 - game_over_text.get_width() // 2,
SCREEN_HEIGHT // 3))
surface.blit(restart_text, (SCREEN_WIDTH // 2 - restart_text.get_width() // 2,
SCREEN_HEIGHT // 3 + 60))
final_score = font.render(f"最终得分: {self.score}", True, YELLOW)
surface.blit(final_score, (SCREEN_WIDTH // 2 - final_score.get_width() // 2,
SCREEN_HEIGHT // 3 + 120))
if not self.game_over and self.score == 0:
help_text = small_font.render("按空格键或点击鼠标让小鸟飞起来", True, WHITE)
surface.blit(help_text, (SCREEN_WIDTH // 2 - help_text.get_width() // 2, 80))
game = Game()
clock = pygame.time.Clock()
while True:
game.handle_events()
game.update()
game.draw(screen)
pygame.display.flip()
clock.tick(60)
浙公网安备 33010602011771号