import pygame
import sys
import random
from pygame import mixer
import math
# 初始化pygame
pygame.init()
mixer.init()
# 游戏常量
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 700
FPS = 60
GRAVITY = 0.75
SCROLL_THRESH = 200
TILE_SIZE = 40
# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
SKY_BLUE = (135, 206, 235)
GROUND_COL = (144, 118, 82)
PURPLE = (128, 0, 128)
ORANGE = (255, 165, 0)
# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("障碍狂跳(Obstacle Bounce)")
clock = pygame.time.Clock()
# 初始化字体
try:
font_large = pygame.font.SysFont('Arial', 50)
font_medium = pygame.font.SysFont('Arial', 30)
font_small = pygame.font.SysFont('Arial', 20)
except:
font_large = pygame.font.Font(None, 50)
font_medium = pygame.font.Font(None, 30)
font_small = pygame.font.Font(None, 20)
# 辅助函数:居中绘制文本
def draw_centered_text(text, font, color, y_offset=0):
img = font.render(text, True, color)
x = (SCREEN_WIDTH - img.get_width()) // 2
y = (SCREEN_HEIGHT - img.get_height()) // 2 + y_offset
screen.blit(img, (x, y))
# 绘制文本函数
def draw_text(text, font, color, x, y):
img = font.render(text, True, color)
screen.blit(img, (x, y))
# 加载图像(使用简单形状)
def load_image(name, scale=1, colorkey=None):
img = pygame.Surface((50, 50), pygame.SRCALPHA)
if "player" in name:
pygame.draw.circle(img, BLUE, (25, 25), 20)
elif "enemy" in name:
pygame.draw.rect(img, RED, (10, 10, 30, 30))
elif "coin" in name:
pygame.draw.circle(img, YELLOW, (25, 25), 15)
elif "platform" in name:
pygame.draw.rect(img, GROUND_COL, (0, 0, 50, 50))
elif "obstacle_static" in name:
pygame.draw.rect(img, BLACK, (5, 5, 40, 40))
elif "obstacle_moving" in name:
pygame.draw.rect(img, PURPLE, (5, 5, 40, 40))
elif "obstacle_tracking" in name:
pygame.draw.polygon(img, RED, [(25, 5), (5, 45), (45, 45)])
elif "obstacle_jumping" in name:
pygame.draw.rect(img, ORANGE, (5, 5, 40, 40))
elif "powerup" in name:
pygame.draw.circle(img, GREEN, (25, 25), 15)
size = img.get_size()
return pygame.transform.scale(img, (int(size[0] * scale), int(size[1] * scale)))
# 游戏资源
class Assets:
def __init__(self):
# 玩家动画帧
self.player_imgs = {
"idle": [load_image("player_idle_1"), load_image("player_idle_2")],
"run": [load_image("player_run_1"), load_image("player_run_2"), load_image("player_run_3")],
"jump": [load_image("player_jump")],
"fall": [load_image("player_fall")]
}
# 敌人图像
self.enemy_imgs = {
"slime": [load_image("enemy_slime_1"), load_image("enemy_slime_2")],
"flying": [load_image("enemy_flying")],
"spike": [load_image("enemy_spike")]
}
# 物品图像
self.item_imgs = {
"coin": [load_image("coin_1"), load_image("coin_2"), load_image("coin_3")],
"health": load_image("health"),
"powerup": load_image("powerup")
}
# 障碍物图像
self.obstacle_imgs = {
"static": load_image("obstacle_static"),
"moving": load_image("obstacle_moving"),
"tracking": load_image("obstacle_tracking"),
"jumping": load_image("obstacle_jumping")
}
# 平台和背景
self.platform_img = load_image("platform", scale=2)
self.bg_img = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
self.bg_img.fill(SKY_BLUE)
# 游戏参数
self.coin_respawn_time = 5000 # 金币刷新时间(毫秒)
self.max_coins = 15 # 最大金币数
self.obstacle_respawn_time = 6000 # 障碍物刷新时间
self.max_obstacles = 8 # 最大障碍物数
self.initial_obstacle_distance = 300 # 初始障碍物间距
self.min_obstacle_distance = 100 # 最小障碍物间距
self.difficulty_increase_interval = 30000 # 每30秒增加难度(毫秒)
self.last_difficulty_increase = 0 # 上次增加难度的时间
self.difficulty_level = 1 # 当前难度等级
# 音效
self.sounds = {
"jump": None,
"coin": None,
"hurt": None,
"powerup": None
}
# 尝试加载音效
try:
self.sounds["jump"] = mixer.Sound("jump.wav") if mixer.get_init() else None
self.sounds["coin"] = mixer.Sound("coin.wav") if mixer.get_init() else None
self.sounds["hurt"] = mixer.Sound("hurt.wav") if mixer.get_init() else None
self.sounds["powerup"] = mixer.Sound("powerup.wav") if mixer.get_init() else None
except:
pass
assets = Assets()
# 玩家类
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.reset(x, y)
def reset(self, x, y):
self.image = assets.player_imgs["idle"][0]
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.width = self.image.get_width()
self.height = self.image.get_height()
# 玩家属性
self.vel_y = 0
self.jumped = False
self.direction = 1
self.in_air = True
self.flip = False
self.frame_index = 0
self.action = "idle"
self.update_time = pygame.time.get_ticks()
# 游戏属性
self.score = 0
self.health = 100
self.max_health = 100
self.coins = 0
self.lives = 3
self.invincible = False # 无敌状态
self.invincible_time = 0 # 无敌时间
self.powered_up = False # 强化状态
self.power_time = 0 # 强化时间
self.jump_power = 15 # 默认跳跃力量
def update(self, game_over, world):
dx = 0
dy = 0
scroll = 0
if not game_over:
# 处理状态效果
current_time = pygame.time.get_ticks()
if self.invincible and current_time - self.invincible_time > 1000: # 1秒无敌时间
self.invincible = False
if self.powered_up and current_time - self.power_time > 10000: # 10秒强化时间
self.powered_up = False
self.jump_power = 15
# 获取按键输入
key = pygame.key.get_pressed()
if key[pygame.K_SPACE] and not self.jumped and not self.in_air:
self.vel_y = -self.jump_power
self.jumped = True
if assets.sounds["jump"]:
assets.sounds["jump"].play()
if not key[pygame.K_SPACE]:
self.jumped = False
if key[pygame.K_LEFT]:
dx -= 5
self.direction = -1
self.flip = True
if key[pygame.K_RIGHT]:
dx += 5
self.direction = 1
self.flip = False
# 应用重力
self.vel_y += GRAVITY
if self.vel_y > 10:
self.vel_y = 10
dy += self.vel_y
# 检查碰撞
self.in_air = True
for tile in world.tile_list:
if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height):
dx = 0
if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height):
if self.vel_y < 0:
dy = tile[1].bottom - self.rect.top
self.vel_y = 0
elif self.vel_y >= 0:
dy = tile[1].top - self.rect.bottom
self.vel_y = 0
self.in_air = False
# 更新玩家坐标
self.rect.x += dx
self.rect.y += dy
# 屏幕滚动
if self.rect.right > SCREEN_WIDTH - SCROLL_THRESH and world.level_length > SCREEN_WIDTH:
scroll = -(SCREEN_WIDTH - SCROLL_THRESH - self.rect.right)
self.rect.right = SCREEN_WIDTH - SCROLL_THRESH
elif self.rect.left < SCROLL_THRESH and scroll < 0:
scroll = SCROLL_THRESH - self.rect.left
self.rect.left = SCROLL_THRESH
# 更新动画状态
if dx != 0:
self.update_action("run")
elif self.in_air:
if self.vel_y < 0:
self.update_action("jump")
else:
self.update_action("fall")
else:
self.update_action("idle")
# 更新动画
self.update_animation()
return scroll
def update_animation(self):
ANIMATION_COOLDOWN = 100
self.image = assets.player_imgs[self.action][self.frame_index]
if pygame.time.get_ticks() - self.update_time > ANIMATION_COOLDOWN:
self.update_time = pygame.time.get_ticks()
self.frame_index += 1
if self.frame_index >= len(assets.player_imgs[self.action]):
self.frame_index = 0
def update_action(self, new_action):
if new_action != self.action:
self.action = new_action
self.frame_index = 0
self.update_time = pygame.time.get_ticks()
def take_damage(self, amount):
if not self.invincible and not self.powered_up:
self.health -= amount
self.invincible = True
self.invincible_time = pygame.time.get_ticks()
if assets.sounds["hurt"]:
assets.sounds["hurt"].play()
if self.health <= 0:
self.lives -= 1
self.health = 100
return True # 表示生命减少
return False
def activate_powerup(self):
self.powered_up = True
self.power_time = pygame.time.get_ticks()
self.jump_power = 20 # 强化跳跃高度
if assets.sounds["powerup"]:
assets.sounds["powerup"].play()
# 敌人类
class Enemy(pygame.sprite.Sprite):
def __init__(self, x, y, enemy_type):
super().__init__()
self.enemy_type = enemy_type
self.image = assets.enemy_imgs[enemy_type][0]
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.move_direction = 1
self.move_counter = 0
self.vel_y = 0
self.flip = False
self.frame_index = 0
self.update_time = pygame.time.get_ticks()
# 敌人特有属性
if enemy_type == "flying":
self.vel_y = random.choice([-1, 1])
self.move_range = random.randint(50, 150)
elif enemy_type == "spike":
self.move_direction = random.choice([-1, 1])
self.speed = random.randint(2, 4)
def update(self, scroll, world):
if self.enemy_type == "slime":
self.rect.x += self.move_direction
self.move_counter += 1
if abs(self.move_counter) > 50:
self.move_direction *= -1
self.move_counter *= -1
self.flip = not self.flip
# 应用重力
self.vel_y += GRAVITY
if self.vel_y > 10:
self.vel_y = 10
self.rect.y += self.vel_y
# 地面碰撞检测
for tile in world.tile_list:
if tile[1].colliderect(self.rect.x, self.rect.y + self.vel_y, self.rect.width, self.rect.height):
if self.vel_y >= 0:
self.rect.bottom = tile[1].top
self.vel_y = 0
elif self.enemy_type == "flying":
# 上下飞行
self.rect.y += self.vel_y
self.move_counter += 1
if abs(self.move_counter) > self.move_range:
self.vel_y *= -1
self.move_counter *= -1
elif self.enemy_type == "spike":
# 快速左右移动
self.rect.x += self.move_direction * self.speed
self.move_counter += 1
if self.move_counter > 100:
self.move_direction *= -1
self.move_counter = 0
# 动画更新
ANIMATION_COOLDOWN = 150
self.image = assets.enemy_imgs[self.enemy_type][self.frame_index]
if pygame.time.get_ticks() - self.update_time > ANIMATION_COOLDOWN:
self.update_time = pygame.time.get_ticks()
self.frame_index = (self.frame_index + 1) % len(assets.enemy_imgs[self.enemy_type])
# 应用屏幕滚动
self.rect.x += scroll
# 物品类
class Item(pygame.sprite.Sprite):
def __init__(self, x, y, item_type):
super().__init__()
self.item_type = item_type
if isinstance(assets.item_imgs[item_type], list):
self.animation_frames = assets.item_imgs[item_type]
self.image = self.animation_frames[0]
else:
self.animation_frames = [assets.item_imgs[item_type]]
self.image = assets.item_imgs[item_type]
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.frame_index = 0
self.update_time = pygame.time.get_ticks()
self.spawn_time = pygame.time.get_ticks()
# 特殊属性
if item_type == "powerup":
self.float_offset = 0
self.float_direction = 1
def update(self, scroll):
ANIMATION_COOLDOWN = 150
if isinstance(self.animation_frames, list):
self.image = self.animation_frames[self.frame_index]
if pygame.time.get_ticks() - self.update_time > ANIMATION_COOLDOWN:
self.update_time = pygame.time.get_ticks()
self.frame_index = (self.frame_index + 1) % len(self.animation_frames)
# 特殊物品浮动效果
if self.item_type == "powerup":
self.float_offset += 0.1 * self.float_direction
if abs(self.float_offset) > 5:
self.float_direction *= -1
self.rect.y += 0.1 * self.float_direction
# 应用屏幕滚动
self.rect.x += scroll
# 障碍物类
class Obstacle(pygame.sprite.Sprite):
def __init__(self, x, y, obstacle_type, difficulty_level=1):
super().__init__()
self.obstacle_type = obstacle_type
self.image = assets.obstacle_imgs[obstacle_type]
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.move_direction = random.choice([-1, 1])
self.move_counter = 0
self.speed = random.randint(1, 3) * difficulty_level
self.lifetime = random.randint(8000, 12000) // max(1, difficulty_level)
self.spawn_time = pygame.time.get_ticks()
self.move_range = random.randint(50, 200) # 移动障碍物的移动范围
# 跳跃障碍物特有属性
if obstacle_type == "jumping":
self.jump_height = random.randint(5, 15)
self.jump_speed = random.uniform(0.05, 0.1) * difficulty_level
self.jump_offset = 0
self.jump_direction = 1
def update(self, scroll, player=None):
# 移动逻辑
if self.obstacle_type == "moving":
self.rect.x += self.move_direction * self.speed
self.move_counter += 1
if self.move_counter > self.move_range:
self.move_direction *= -1
self.move_counter = 0
elif self.obstacle_type == "tracking" and player:
# 追踪逻辑 - 只在y轴追踪,x轴保持移动
self.rect.x += self.move_direction * self.speed
# 在x轴边界反弹
if self.rect.left < 0 or self.rect.right > SCREEN_WIDTH:
self.move_direction *= -1
# 在y轴追踪玩家,但有延迟
if self.rect.y < player.rect.y:
self.rect.y += min(self.speed, player.rect.y - self.rect.y)
elif self.rect.y > player.rect.y:
self.rect.y -= min(self.speed, self.rect.y - player.rect.y)
elif self.obstacle_type == "jumping":
# 跳跃障碍物上下跳动
self.jump_offset += self.jump_speed * self.jump_direction
if abs(self.jump_offset) > self.jump_height:
self.jump_direction *= -1
self.rect.y += self.jump_speed * self.jump_direction
# 同时可能左右移动
self.rect.x += self.move_direction * (self.speed / 2)
self.move_counter += 1
if self.move_counter > self.move_range:
self.move_direction *= -1
self.move_counter = 0
# 生命周期检查
if pygame.time.get_ticks() - self.spawn_time > self.lifetime:
self.kill()
# 应用屏幕滚动
self.rect.x += scroll
# 世界类
class World():
def __init__(self, level_data):
self.tile_list = []
self.coin_spawn_areas = []
self.obstacle_spawn_areas = []
# 创建世界
row_count = 0
for row in level_data:
col_count = 0
for tile in row:
if tile == 1:
img = assets.platform_img
img_rect = img.get_rect()
img_rect.x = col_count * TILE_SIZE
img_rect.y = row_count * TILE_SIZE
tile = (img, img_rect)
self.tile_list.append(tile)
elif tile == 0:
# 检查下方是否有平台
if row_count < len(level_data) - 1 and level_data[row_count + 1][col_count] == 1:
self.coin_spawn_areas.append((col_count * TILE_SIZE, row_count * TILE_SIZE))
self.obstacle_spawn_areas.append((col_count * TILE_SIZE, row_count * TILE_SIZE))
col_count += 1
row_count += 1
self.level_length = len(level_data[0]) * TILE_SIZE
def draw(self, screen, scroll):
for tile in self.tile_list:
tile[1].x += scroll
screen.blit(tile[0], tile[1])
tile[1].x -= scroll
def get_random_coin_position(self):
if self.coin_spawn_areas:
return random.choice(self.coin_spawn_areas)
return (random.randint(100, SCREEN_WIDTH - 100), random.randint(100, SCREEN_HEIGHT - 200))
def get_smart_obstacle_position(self, player_x, last_obstacle_x, min_distance):
# 尝试找到合适位置最多尝试10次
for _ in range(10):
if self.obstacle_spawn_areas:
x, y = random.choice(self.obstacle_spawn_areas)
else:
x, y = random.randint(100, SCREEN_WIDTH - 100), random.randint(100, SCREEN_HEIGHT - 200)
# 检查与玩家的距离
if abs(x - player_x) < min_distance:
continue
# 检查与上一个障碍物的距离
if last_obstacle_x and abs(x - last_obstacle_x) < min_distance:
continue
return x, y
# 如果找不到理想位置,返回随机位置
if self.obstacle_spawn_areas:
return random.choice(self.obstacle_spawn_areas)
return (random.randint(100, SCREEN_WIDTH - 100), random.randint(100, SCREEN_HEIGHT - 200))
# 开始界面
def show_start_screen():
screen.fill(SKY_BLUE)
# 居中绘制所有文本
draw_centered_text("Obstacle Bounce", font_medium, BLACK, -150)
draw_centered_text("Start: Space", font_medium, BLACK, -50)
draw_centered_text("Move: Arrow Keys", font_small, BLACK, 20)
draw_centered_text("Jump: Spacebar", font_small, BLACK, 50)
draw_centered_text("Pause: Esc", font_small, BLACK, 80)
draw_centered_text("Collect coins, avoid obstacles!", font_small, BLACK, 120)
draw_centered_text("Green items: Power boost", font_small, GREEN, 150)
pygame.display.update()
waiting = True
while waiting:
clock.tick(FPS)
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:
waiting = False
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
# 暂停界面
def show_pause_screen():
screen.fill(SKY_BLUE)
draw_centered_text("游戏暂停", font_large, BLACK, -50)
draw_centered_text("按ESC键继续游戏", font_medium, BLACK, 20)
draw_centered_text("按Q键退出游戏", font_medium, BLACK, 60)
pygame.display.update()
paused = True
while paused:
clock.tick(FPS)
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_ESCAPE:
paused = False
if event.key == pygame.K_q:
pygame.quit()
sys.exit()
# 结束界面
def show_game_over_screen(score):
screen.fill(SKY_BLUE)
draw_centered_text("Game Over", font_large, RED, -100)
draw_centered_text(f"Final Score: {score}", font_medium, BLACK, -30)
draw_centered_text("Restart: R", font_medium, BLACK, 30)
draw_centered_text("Quit: Q", font_medium, BLACK, 80)
pygame.display.update()
waiting = True
while waiting:
clock.tick(FPS)
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_r:
waiting = False
if event.key == pygame.K_q:
pygame.quit()
sys.exit()
return True
# 游戏主循环
def main():
# 创建玩家
player = Player(100, SCREEN_HEIGHT - 130)
# 创建世界
world_data = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]
world = World(world_data)
# 创建精灵组
enemies = pygame.sprite.Group()
items = pygame.sprite.Group()
obstacles = pygame.sprite.Group()
# 添加初始敌人和金币
enemies.add(Enemy(300, SCREEN_HEIGHT - 180, "slime"))
enemies.add(Enemy(600, SCREEN_HEIGHT - 180, "slime"))
enemies.add(Enemy(450, SCREEN_HEIGHT - 400, "flying"))
enemies.add(Enemy(800, SCREEN_HEIGHT - 180, "spike"))
for i in range(5):
items.add(Item(200 + i * 150, SCREEN_HEIGHT - 200, "coin"))
# 添加初始障碍物
obstacles.add(Obstacle(400, SCREEN_HEIGHT - 250, "static", assets.difficulty_level))
obstacles.add(Obstacle(700, SCREEN_HEIGHT - 250, "moving", assets.difficulty_level))
obstacles.add(Obstacle(500, SCREEN_HEIGHT - 350, "jumping", assets.difficulty_level))
# 游戏变量
scroll = 0
game_over = False
running = True
paused = False
# 计时器和距离跟踪
last_coin_spawn_time = pygame.time.get_ticks()
last_obstacle_spawn_time = pygame.time.get_ticks()
last_powerup_spawn_time = pygame.time.get_ticks()
last_obstacle_x = None
min_obstacle_distance = assets.initial_obstacle_distance
# 显示开始界面
show_start_screen()
while running:
current_time = pygame.time.get_ticks()
clock.tick(FPS)
# 事件处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE and not game_over:
paused = not paused
if paused:
show_pause_screen()
if game_over:
if event.key == pygame.K_r:
# 重置游戏状态
player.reset(100, SCREEN_HEIGHT - 130)
scroll = 0
game_over = False
# 重置所有元素
enemies.empty()
enemies.add(Enemy(300, SCREEN_HEIGHT - 180, "slime"))
enemies.add(Enemy(600, SCREEN_HEIGHT - 180, "slime"))
enemies.add(Enemy(450, SCREEN_HEIGHT - 400, "flying"))
enemies.add(Enemy(800, SCREEN_HEIGHT - 180, "spike"))
items.empty()
for i in range(5):
items.add(Item(200 + i * 150, SCREEN_HEIGHT - 200, "coin"))
obstacles.empty()
obstacles.add(Obstacle(400, SCREEN_HEIGHT - 250, "static", 1))
obstacles.add(Obstacle(700, SCREEN_HEIGHT - 250, "moving", 1))
obstacles.add(Obstacle(500, SCREEN_HEIGHT - 350, "jumping", 1))
last_coin_spawn_time = current_time
last_obstacle_spawn_time = current_time
last_powerup_spawn_time = current_time
last_obstacle_x = None
min_obstacle_distance = assets.initial_obstacle_distance
assets.difficulty_level = 1
assets.last_difficulty_increase = current_time
elif event.key == pygame.K_q:
running = False
if paused:
continue
if game_over:
if show_game_over_screen(player.score):
# 重置游戏状态
player.reset(100, SCREEN_HEIGHT - 130)
scroll = 0
game_over = False
# 重置所有元素
enemies.empty()
enemies.add(Enemy(300, SCREEN_HEIGHT - 180, "slime"))
enemies.add(Enemy(600, SCREEN_HEIGHT - 180, "slime"))
enemies.add(Enemy(450, SCREEN_HEIGHT - 400, "flying"))
enemies.add(Enemy(800, SCREEN_HEIGHT - 180, "spike"))
items.empty()
for i in range(5):
items.add(Item(200 + i * 150, SCREEN_HEIGHT - 200, "coin"))
obstacles.empty()
obstacles.add(Obstacle(400, SCREEN_HEIGHT - 250, "static", 1))
obstacles.add(Obstacle(700, SCREEN_HEIGHT - 250, "moving", 1))
obstacles.add(Obstacle(500, SCREEN_HEIGHT - 350, "jumping", 1))
last_coin_spawn_time = current_time
last_obstacle_spawn_time = current_time
last_powerup_spawn_time = current_time
last_obstacle_x = None
min_obstacle_distance = assets.initial_obstacle_distance
assets.difficulty_level = 1
assets.last_difficulty_increase = current_time
else:
running = False
continue
# 难度递增系统
if current_time - assets.last_difficulty_increase > assets.difficulty_increase_interval:
assets.difficulty_level += 0.5
assets.last_difficulty_increase = current_time
# 逐渐减少最小间距,但不低于最小值
min_obstacle_distance = max(
assets.min_obstacle_distance,
assets.initial_obstacle_distance - (assets.difficulty_level * 20)
)
# 金币刷新逻辑
if (current_time - last_coin_spawn_time > assets.coin_respawn_time and
len(items) < assets.max_coins):
x, y = world.get_random_coin_position()
items.add(Item(x, y, "coin"))
last_coin_spawn_time = current_time
# 强化道具刷新逻辑 (每20-30秒)
if (current_time - last_powerup_spawn_time > random.randint(20000, 30000) and
len([i for i in items if i.item_type == "powerup"]) < 1):
x, y = world.get_random_coin_position()
items.add(Item(x, y, "powerup"))
last_powerup_spawn_time = current_time
# 障碍物刷新逻辑
if (current_time - last_obstacle_spawn_time > assets.obstacle_respawn_time and
len(obstacles) < assets.max_obstacles):
# 获取智能位置
x, y = world.get_smart_obstacle_position(
player.rect.x,
last_obstacle_x,
min_obstacle_distance
)
# 随机选择障碍物类型,难度越高追踪和跳跃障碍物出现几率越大
obstacle_types = ["static", "moving", "tracking", "jumping"]
weights = [
0.4, # static
0.3, # moving
0.1 + (assets.difficulty_level * 0.1), # tracking
0.2 + (assets.difficulty_level * 0.1) # jumping
]
obstacle_type = random.choices(obstacle_types, weights=weights, k=1)[0]
obstacles.add(Obstacle(x, y, obstacle_type, assets.difficulty_level))
last_obstacle_spawn_time = current_time
last_obstacle_x = x
# 更新游戏状态
scroll = player.update(game_over, world)
enemies.update(scroll, world)
items.update(scroll)
obstacles.update(scroll, player)
# 检查碰撞 - 敌人
for enemy in enemies:
if player.rect.colliderect(enemy.rect):
if player.take_damage(10):
if player.lives <= 0:
game_over = True
# 检查碰撞 - 物品
for item in items:
if player.rect.colliderect(item.rect):
if item.item_type == "coin":
player.score += 10
player.coins += 1
if assets.sounds["coin"]:
assets.sounds["coin"].play()
elif item.item_type == "powerup":
player.activate_powerup()
items.remove(item)
# 30%几率立即生成新金币
if random.random() < 0.3 and item.item_type == "coin":
x, y = world.get_random_coin_position()
items.add(Item(x, y, "coin"))
# 检查碰撞 - 障碍物
for obstacle in obstacles:
if player.rect.colliderect(obstacle.rect):
if player.take_damage(15):
if player.lives <= 0:
game_over = True
# 绘制游戏
screen.blit(assets.bg_img, (0, 0))
world.draw(screen, scroll)
enemies.draw(screen)
items.draw(screen)
obstacles.draw(screen)
# 绘制玩家(无敌状态时闪烁)
if not player.invincible or (pygame.time.get_ticks() // 200) % 2 == 0:
screen.blit(pygame.transform.flip(player.image, player.flip, False),
(player.rect.x - scroll, player.rect.y))
# 绘制UI
draw_text(f"score: {player.score}", font_small, BLACK, 20, 20)
draw_text(f"life: {player.lives}", font_small, BLACK, 20, 50)
draw_text(f"coin: {player.coins}", font_small, BLACK, 20, 80)
# 血条
pygame.draw.rect(screen, RED, (20, 110, player.health, 20))
pygame.draw.rect(screen, BLACK, (20, 110, player.max_health, 20), 2)
# 难度指示器
draw_text(f"Level: {int(assets.difficulty_level)}", font_small, BLACK, 20, 140)
# 强化状态指示器
if player.powered_up:
remaining_time = max(0, 10 - (pygame.time.get_ticks() - player.power_time) / 1000)
draw_text(f"Power-up: {remaining_time:.1f}s", font_small, GREEN, 20, 170)
pygame.display.update()
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()
给里面的角色和障碍添加图片