import pygame
import random
import sys
import math
# 初始化pygame
pygame.init()
pygame.mixer.init()
# 屏幕设置
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption(" 球球越障大挑战- 3111")
# 颜色定义
WHITE = (255, 255, 255)
BLUE = (100, 149, 237)
RED = (255, 0, 0)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
YELLOW = (255, 255, 0)
# 游戏参数
FPS = 60
clock = pygame.time.Clock()
GRAVITY = 0.5
SCROLL_SPEED = 5
BASE_SPEED = 5
MAX_SPEED = 15
JUMP_FORCE = -12
BOOST_FACTOR = 1.5
BOOST_DURATION = 180 # 3秒(60帧/秒)
# 加载图像和音效
try:
# 玩家图像
player_img = pygame.Surface((40, 60), pygame.SRCALPHA)
pygame.draw.ellipse(player_img, BLUE, (0, 0, 40, 60))
# 障碍物图像
rock_img = pygame.Surface((50, 50), pygame.SRCALPHA)
pygame.draw.circle(rock_img, (100, 100, 100), (25, 25), 25)
tree_img = pygame.Surface((60, 100), pygame.SRCALPHA)
pygame.draw.rect(tree_img, BROWN := (139, 69, 19), (20, 60, 20, 40))
pygame.draw.polygon(tree_img, GREEN, [(0, 60), (60, 60), (30, 0)])
# 道具图像
boost_img = pygame.Surface((30, 30), pygame.SRCALPHA)
pygame.draw.circle(boost_img, YELLOW, (15, 15), 15)
pygame.draw.line(boost_img, BLACK, (15, 5), (15, 25), 2)
pygame.draw.line(boost_img, BLACK, (5, 15), (25, 15), 2)
# 背景图像
bg_img = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
bg_img.fill((135, 206, 235)) # 天空蓝
pygame.draw.rect(bg_img, WHITE, (0, SCREEN_HEIGHT//2, SCREEN_WIDTH, SCREEN_HEIGHT//2)) # 雪地
# 音效
jump_sound = pygame.mixer.Sound(pygame.mixer.SoundType('jump.wav') if pygame.version.vernum[0] >= 2 else None)
crash_sound = pygame.mixer.Sound(pygame.mixer.SoundType('crash.wav') if pygame.version.vernum[0] >= 2 else None)
boost_sound = pygame.mixer.Sound(pygame.mixer.SoundType('boost.wav') if pygame.version.vernum[0] >= 2 else None)
except:
# 如果加载资源失败,使用简单图形代替
pass
# 玩家类
class Player:
def __init__(self):
self.reset()
self.img = player_img
self.width = 40
self.height = 60
self.rect = pygame.Rect(100, SCREEN_HEIGHT//2 - self.height, self.width, self.height)
self.jump_power = JUMP_FORCE
self.is_jumping = False
self.boost_timer = 0
self.invincible = 0
self.rotation = 0
def reset(self):
self.x = 100
self.y = SCREEN_HEIGHT//2 - 60
self.vel_y = 0
self.boost_timer = 0
self.invincible = 0
self.rotation = 0
def update(self, scroll_speed):
# 重力
self.vel_y += GRAVITY
self.y += self.vel_y
# 确保玩家不会超出屏幕底部
if self.y > SCREEN_HEIGHT - self.height:
self.y = SCREEN_HEIGHT - self.height
self.vel_y = 0
self.is_jumping = False
# 确保玩家不会超出屏幕顶部
if self.y < 0:
self.y = 0
self.vel_y = 0
# 更新矩形位置
self.rect.y = self.y
# 旋转效果
if self.is_jumping:
self.rotation = min(30, max(-30, self.vel_y * 3))
else:
self.rotation = 0
# 无敌时间减少
if self.invincible > 0:
self.invincible -= 1
# 加速时间减少
if self.boost_timer > 0:
self.boost_timer -= 1
def jump(self):
if not self.is_jumping:
self.vel_y = self.jump_power
self.is_jumping = True
try:
jump_sound.play()
except:
pass
def draw(self, screen):
# 绘制玩家(带旋转效果)
rotated_img = pygame.transform.rotate(self.img, self.rotation)
new_rect = rotated_img.get_rect(center=self.img.get_rect(topleft=(self.x, self.y)).center)
screen.blit(rotated_img, new_rect.topleft)
# 无敌状态闪烁效果
if self.invincible > 0 and self.invincible % 10 < 5:
pygame.draw.rect(screen, (255, 255, 255, 128), new_rect, 2)
# 障碍物类
class Obstacle:
def __init__(self, x, y, obstacle_type):
self.x = x
self.y = y
self.type = obstacle_type # 'rock' 或 'tree'
if self.type == 'rock':
self.width = 50
self.height = 50
self.img = rock_img
else: # tree
self.width = 60
self.height = 100
self.img = tree_img
self.rect = pygame.Rect(x, y, self.width, self.height)
def update(self, scroll_speed):
self.x -= scroll_speed
self.rect.x = self.x
def draw(self, screen):
screen.blit(self.img, (self.x, self.y))
# 道具类
class PowerUp:
def __init__(self, x, y, power_type):
self.x = x
self.y = y
self.type = power_type # 'boost'
self.width = 30
self.height = 30
self.img = boost_img
self.rect = pygame.Rect(x, y, self.width, self.height)
self.animation_timer = 0
def update(self, scroll_speed):
self.x -= scroll_speed
self.rect.x = self.x
self.animation_timer = (self.animation_timer + 1) % 60
def draw(self, screen):
# 闪烁动画
if self.animation_timer < 45: # 显示3/4的时间
size_factor = 1.0 + 0.2 * math.sin(self.animation_timer * 0.1)
scaled_img = pygame.transform.scale(self.img,
(int(self.width * size_factor),
int(self.height * size_factor)))
screen.blit(scaled_img,
(self.x - (scaled_img.get_width() - self.width) // 2,
self.y - (scaled_img.get_height() - self.height) // 2))
# 游戏状态
player = Player()
obstacles = []
powerups = []
scroll_speed = BASE_SPEED
score = 0
high_score = 0
game_over = False
obstacle_timer = 0
powerup_timer = 0
distance = 0
particles = []
# 粒子效果
class Particle:
def __init__(self, x, y, color):
self.x = x
self.y = y
self.color = color
self.size = random.randint(2, 5)
self.life = random.randint(20, 40)
self.vel_x = random.uniform(-2, 2)
self.vel_y = random.uniform(-2, 0)
def update(self):
self.x += self.vel_x
self.y += self.vel_y
self.life -= 1
self.size = max(0, self.size - 0.1)
def draw(self, screen):
alpha = min(255, self.life * 6)
color_with_alpha = (*self.color, alpha)
surf = pygame.Surface((self.size*2, self.size*2), pygame.SRCALPHA)
pygame.draw.circle(surf, color_with_alpha, (self.size, self.size), self.size)
screen.blit(surf, (int(self.x - self.size), int(self.y - self.size)))
# 游戏主循环
running = True
while running:
# 事件处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE or event.key == pygame.K_UP:
player.jump()
if event.key == pygame.K_r and game_over:
# 重置游戏
player.reset()
obstacles = []
powerups = []
scroll_speed = BASE_SPEED
score = 0
distance = 0
game_over = False
obstacle_timer = 0
powerup_timer = 0
if game_over:
# 显示游戏结束画面
screen.fill(BLUE)
# 绘制雪地
pygame.draw.rect(screen, WHITE, (0, SCREEN_HEIGHT//2, SCREEN_WIDTH, SCREEN_HEIGHT//2))
font_large = pygame.font.SysFont(None, 72)
font_small = pygame.font.SysFont(None, 36)
game_over_text = font_large.render("游戏结束!", True, RED)
score_text = font_large.render(f"得分: {score}", True, BLACK)
high_score_text = font_small.render(f"最高分: {high_score}", True, BLACK)
restart_text = font_small.render("按R键重新开始", True, BLACK)
screen.blit(game_over_text, (SCREEN_WIDTH//2 - game_over_text.get_width()//2, SCREEN_HEIGHT//2 - 100))
screen.blit(score_text, (SCREEN_WIDTH//2 - score_text.get_width()//2, SCREEN_HEIGHT//2))
screen.blit(high_score_text, (SCREEN_WIDTH//2 - high_score_text.get_width()//2, SCREEN_HEIGHT//2 + 70))
screen.blit(restart_text, (SCREEN_WIDTH//2 - restart_text.get_width()//2, SCREEN_HEIGHT//2 + 120))
# 绘制特殊标志 3111
special_text = font_small.render("3111", True, RED)
screen.blit(special_text, (SCREEN_WIDTH - 60, 20))
pygame.display.flip()
clock.tick(FPS)
continue
# 更新游戏状态
# 更新滚动速度(根据加速状态)
if player.boost_timer > 0:
scroll_speed = min(MAX_SPEED, BASE_SPEED * BOOST_FACTOR)
else:
scroll_speed = BASE_SPEED
# 更新玩家
player.update(scroll_speed)
# 更新距离和分数
distance += scroll_speed / 10
score = int(distance)
# 生成障碍物
obstacle_timer += 1
if obstacle_timer >= 90: # 每1.5秒生成一个障碍物
obstacle_timer = 0
obstacle_type = random.choice(['rock', 'tree'])
y_pos = SCREEN_HEIGHT - (100 if obstacle_type == 'tree' else 50)
obstacles.append(Obstacle(SCREEN_WIDTH, y_pos, obstacle_type))
# 生成道具
powerup_timer += 1
if powerup_timer >= 300 and random.random() < 0.1: # 大约每5秒有10%几率生成道具
powerup_timer = 0
y_pos = random.randint(SCREEN_HEIGHT//2, SCREEN_HEIGHT - 50)
powerups.append(PowerUp(SCREEN_WIDTH, y_pos, 'boost'))
# 更新障碍物
for obstacle in obstacles[:]:
obstacle.update(scroll_speed)
# 移除屏幕外的障碍物
if obstacle.x < -obstacle.width:
obstacles.remove(obstacle)
# 检测碰撞(无敌状态下不检测)
if player.invincible <= 0 and player.rect.colliderect(obstacle.rect):
try:
crash_sound.play()
except:
pass
# 创建碰撞粒子效果
for _ in range(20):
particles.append(Particle(
player.x + player.width//2,
player.y + player.height//2,
(random.randint(200, 255), random.randint(100, 200), random.randint(100, 200))
))
game_over = True
high_score = max(high_score, score)
# 更新道具
for powerup in powerups[:]:
powerup.update(scroll_speed)
# 移除屏幕外的道具
if powerup.x < -powerup.width:
powerups.remove(powerup)
# 检测收集
if player.rect.colliderect(powerup.rect):
if powerup.type == 'boost':
player.boost_timer = BOOST_DURATION
try:
boost_sound.play()
except:
pass
# 创建收集粒子效果
for _ in range(15):
particles.append(Particle(
powerup.x + powerup.width//2,
powerup.y + powerup.height//2,
(random.randint(200, 255), random.randint(200, 255), random.randint(0, 100))
))
powerups.remove(powerup)
# 更新粒子
for particle in particles[:]:
particle.update()
if particle.life <= 0:
particles.remove(particle)
# 绘制
# 绘制背景
screen.blit(bg_img, (0, 0))
# 绘制雪地(带视差效果)
for i in range(5):
offset = (distance * (i+1)*0.1) % SCREEN_WIDTH
pygame.draw.rect(screen, WHITE, (offset - SCREEN_WIDTH, SCREEN_HEIGHT//2 + i*20, SCREEN_WIDTH, 20))
pygame.draw.rect(screen, WHITE, (offset, SCREEN_HEIGHT//2 + i*20, SCREEN_WIDTH, 20))
# 绘制粒子
for particle in particles:
particle.draw(screen)
# 绘制障碍物
for obstacle in obstacles:
obstacle.draw(screen)
# 绘制道具
for powerup in powerups:
powerup.draw(screen)
# 绘制玩家
player.draw(screen)
# 绘制UI
font = pygame.font.SysFont(None, 36)
score_text = font.render(f"分数: {score}", True, BLACK)
screen.blit(score_text, (20, 20))
# 绘制加速状态
if player.boost_timer > 0:
boost_text = font.render(f"加速: {player.boost_timer//60 + 1}s", True, YELLOW)
screen.blit(boost_text, (20, 60))
# 绘制特殊标志 3111
special_text = font.render("3111", True, RED)
screen.blit(special_text, (SCREEN_WIDTH - 60, 20))
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
sys.exit()