Pygame游戏之躲避游戏
一、项目概述
1.1 项目背景
该项目是一个基于Pygame的2D躲避类游戏(Dodger Game),玩家通过左右移动控制角色,避免被从屏幕上方不断下落的敌人撞击。游戏的核心机制包括:
- 玩家控制:左右移动
- 敌人生成与下落
- 碰撞检测
- 得分系统
- 难度递增机制
- 游戏结束与重开逻辑
1.2 技术选型
- Pygame:Python的2D游戏开发库,提供图形渲染、事件处理、音效支持等功能
- 面向对象编程:通过
Player
和Enemy
类封装角色行为 - 精灵组(Sprite Groups):管理游戏对象的更新与渲染
- 帧率控制:通过
FPS
常量调节游戏流畅度
二、代码结构分析
2.1 常量定义
代码开头通过常量定义模块化配置参数:
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
FPS = 60
设计亮点:
- 将颜色、尺寸、帧率等参数集中管理,便于后期维护
- 使用元组表示RGB颜色值,符合Pygame标准
- 常量命名采用全大写加下划线格式(PEP8规范)
2.2 类设计
2.2.1 Player
类
class Player(pygame.sprite.Sprite):def __init__(self):super().__init__()self.image = pygame.Surface([PLAYER_WIDTH, PLAYER_HEIGHT])self.image.fill(GREEN)self.rect = self.image.get_rect()self.rect.x = SCREEN_WIDTH // 2 - PLAYER_WIDTH // 2self.rect.y = SCREEN_HEIGHT - PLAYER_HEIGHT - 10self.speed_x = 0def update(self):# 键盘事件处理与位置更新
关键实现:
- 初始化:
- 创建绿色矩形作为玩家形象
- 设置初始位置在屏幕底部中央
- 运动控制:
- 通过
pygame.key.get_pressed()
检测左右箭头键 - 限制玩家不超出屏幕边界
- 通过
- 继承设计:
- 继承
pygame.sprite.Sprite
类,便于后续精灵组管理
- 继承
2.2.2 Enemy
类
class Enemy(pygame.sprite.Sprite):def __init__(self):super().__init__()self.image = pygame.Surface([ENEMY_WIDTH, ENEMY_HEIGHT])self.image.fill(RED)self.rect = self.image.get_rect()self.rect.x = random.randrange(SCREEN_WIDTH - ENEMY_WIDTH)self.rect.y = random.randrange(-150, -ENEMY_HEIGHT - 10)self.speed_y = random.randint(ENEMY_SPEED_MIN, ENEMY_SPEED_MAX)def update(self):self.rect.y += self.speed_yif self.rect.top > SCREEN_HEIGHT + ENEMY_HEIGHT + 5:self.kill()
关键实现:
- 随机生成:
- 初始位置在屏幕上方随机位置
- 下落速度在3-8之间随机
- 自动移除:
- 敌人移出屏幕后调用
kill()
方法销毁
- 敌人移出屏幕后调用
- 视觉设计:
- 使用红色矩形表示敌人,与玩家形成对比
2.3 游戏功能函数
2.3.1 draw_text
函数
def draw_text(surface, text, size, x, y, color, font_name='arial'):font = pygame.font.Font(pygame.font.match_font(font_name), size)text_surface = font.render(text, True, color)text_rect = text_surface.get_rect()text_rect.midtop = (x, y)surface.blit(text_surface, text_rect)
设计特点:
- 支持自定义字体、大小和颜色
- 文本对齐方式灵活(
midtop
) - 通过
pygame.font.Font
实现文本渲染
2.3.2 show_game_over_screen
函数
def show_game_over_screen(screen, clock, score):screen.fill(BLACK)draw_text(screen, "游戏结束!", 64, SCREEN_WIDTH // 2, SCREEN_HEIGHT / 4, RED)draw_text(screen, f"最终得分: {score}", 30, SCREEN_WIDTH // 2, SCREEN_HEIGHT / 2 - 50, WHITE)draw_text(screen, "按 'R' 重新开始", 22, SCREEN_WIDTH // 2, SCREEN_HEIGHT / 2 + 20, WHITE)draw_text(screen, "按 'Q' 退出游戏", 22, SCREEN_WIDTH // 2, SCREEN_HEIGHT / 2 + 50, WHITE)pygame.display.flip()waiting_for_input = Truewhile waiting_for_input:clock.tick(FPS)for event in pygame.event.get():if event.type == pygame.QUIT:return "QUIT"if event.type == pygame.KEYDOWN:if event.key == pygame.K_r:return "RESTART"if event.key == pygame.K_q:return "QUIT"return "QUIT"
交互设计:
- 提供清晰的视觉反馈(红色标题、白色提示)
- 支持两种操作:重新开始(R)或退出(Q)
- 通过事件循环等待用户输入
2.4 主游戏控制器
def main_game_controller():pygame.init()screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))pygame.display.set_caption("Dodger Game")clock = pygame.time.Clock()running_game_instance = Truewhile running_game_instance:# 初始化游戏会话变量all_sprites = pygame.sprite.Group()enemies = pygame.sprite.Group()player = Player()all_sprites.add(player)score = 0last_difficulty_increase_score = 0enemy_spawn_timer = 0current_enemy_spawn_interval = INITIAL_ENEMY_SPAWN_INTERVALgame_session_active = Truewhile game_session_active:clock.tick(FPS)for event in pygame.event.get():if event.type == pygame.QUIT:game_session_active = Falserunning_game_instance = Falseif not running_game_instance:breakall_sprites.update()# 敌人生成与难度调整enemy_spawn_timer += 1if enemy_spawn_timer >= current_enemy_spawn_interval:enemy_spawn_timer = 0new_enemy = Enemy()all_sprites.add(new_enemy)enemies.add(new_enemy)# 难度递增逻辑# 碰撞检测collided_enemies = pygame.sprite.spritecollide(player, enemies, True)if collided_enemies:game_session_active = False# 渲染screen.fill(BLACK)all_sprites.draw(screen)draw_text(screen, f"得分: {score}", 24, SCREEN_WIDTH // 2, 10, WHITE)pygame.display.flip()# 游戏结束处理if running_game_instance:action_after_game_over = show_game_over_screen(screen, clock, score)if action_after_game_over == "QUIT":running_game_instance = Falsepygame.quit()
架构设计亮点:
- 双层循环结构:
- 外层循环控制游戏会话(重启/退出)
- 内层循环处理单局游戏逻辑
- 状态管理:
- 使用
running_game_instance
和game_session_active
标志位控制流程
- 使用
- 精灵组管理:
all_sprites
管理所有游戏对象enemies
专门管理敌人精灵
三、核心功能实现详解
3.1 游戏循环
Pygame游戏循环遵循经典模式:
while running:handle_events()update_game_state()render()
在本项目中,主循环嵌套了两层:
- 外层循环(
running_game_instance
):控制游戏会话(重启/退出) - 内层循环(
game_session_active
):控制单局游戏运行
优化点:
- 使用
clock.tick(FPS)
控制帧率 - 事件处理优先级合理(先处理退出事件)
3.2 碰撞检测
collided_enemies = pygame.sprite.spritecollide(player, enemies, True)
实现细节:
- 使用
pygame.sprite.spritecollide()
检测玩家与敌人碰撞 dokill=True
参数表示碰撞后自动销毁敌人- 碰撞后立即结束当前游戏会话
潜在改进空间:
- 当前实现简单直接,但无法区分多个敌人碰撞
- 可添加爆炸特效或生命值系统
3.3 敌人生成机制
enemy_spawn_timer += 1
if enemy_spawn_timer >= current_enemy_spawn_interval:enemy_spawn_timer = 0new_enemy = Enemy()all_sprites.add(new_enemy)enemies.add(new_enemy)
动态调整:
- 初始生成间隔为50帧(约0.83秒)
- 每累积250分减少生成间隔(
ENEMY_SPAWN_INTERVAL_DECREMENT_STEP=5
) - 最小间隔为15帧(约0.25秒)
难度曲线设计:
if score - last_difficulty_increase_score >= SCORE_MILESTONE_FOR_DIFFICULTY_INCREASE:last_difficulty_increase_score = scoreif current_enemy_spawn_interval > MIN_ENEMY_SPAWN_INTERVAL:current_enemy_spawn_interval -= ENEMY_SPAWN_INTERVAL_DECREMENT_STEP
通过降低敌人生成间隔逐步提升难度,但缺乏敌人速度变化等维度。
3.4 得分系统
设计特点:
- 每帧增加1分(实际为每帧计分)
- 与游戏时长直接相关
- 未考虑敌人数量或难度系数
改进建议:
- 添加基于存活时间的计分
- 引入不同敌人类型(如高分敌人、危险敌人)
四、游戏机制设计
4.1 控制逻辑
玩家通过左右箭头键控制移动:
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:self.speed_x = -PLAYER_SPEED
if keystate[pygame.K_RIGHT]:self.speed_x = PLAYER_SPEED
优化点:
- 使用连续按键检测而非单次事件处理
- 移动速度与方向分离,便于扩展
4.2 敌人行为
敌人从屏幕上方随机位置生成,以固定速度下落:
self.rect.y += self.speed_y
设计特点:
- 敌人速度在3-8之间随机
- 超出屏幕后自动销毁
- 未实现水平移动或追踪玩家
4.3 游戏结束逻辑
碰撞检测失败后触发游戏结束:
collided_enemies = pygame.sprite.spritecollide(player, enemies, True)
if collided_enemies:game_session_active = False
用户体验:
- 清晰的视觉反馈(红色标题)
- 简单的重启/退出选项
- 未添加游戏结束音效
五、优化建议
5.1 代码结构优化
-
模块化重构:
- 将常量定义、类定义、功能函数拆分为独立模块
- 使用
__init__.py
组织包结构
# game_config.py SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600
-
配置文件支持:
- 使用JSON/YAML文件存储配置参数
{"screen": {"width": 800,"height": 600},"player": {"speed": 8} }
-
依赖注入:
- 通过参数传递依赖项(如
pygame.display.set_mode
返回的Surface)
- 通过参数传递依赖项(如
5.2 性能优化
-
精灵组优化:
- 使用
pygame.sprite.LayeredUpdates
管理精灵层级 - 避免频繁创建/销毁精灵
- 使用
-
碰撞检测优化:
- 对大型敌人使用
pygame.sprite.collide_circle_ratio
提高精度 - 实现空间分区算法(如四叉树)
- 对大型敌人使用
-
图像优化:
- 使用预加载精灵表(Sprite Sheet)
- 启用
convert_alpha()
优化透明通道
5.3 功能扩展
-
生命值系统:
class Player:def __init__(self):self.lives = 3
-
多级难度:
- 添加不同级别的敌人(如快速敌人、追踪敌人)
- 引入关卡编辑器
-
音效系统:
hit_sound = pygame.mixer.Sound('hit.wav') hit_sound.play()
-
数据持久化:
- 存储最高分记录
- 实现排行榜功能
5.4 用户体验改进
-
动画效果:
- 玩家移动时添加尾迹
- 敌人碰撞时显示爆炸动画
-
过渡效果:
- 游戏开始时的淡入动画
- 游戏结束时的粒子效果
-
自适应布局:
- 支持窗口化/全屏切换
- 自动调整分辨率
六、总结与展望
6.1 项目价值
该项目作为Pygame入门案例具有以下价值:
- 展示了游戏开发的核心流程(初始化、更新、渲染)
- 体现了面向对象编程的优势(类封装、继承)
- 提供了基础的游戏机制参考(碰撞检测、得分系统)
6.2 改进方向
方向 | 具体措施 |
---|---|
架构优化 | 拆分模块、使用配置文件 |
性能提升 | 优化精灵管理、碰撞检测算法 |
功能扩展 | 添加生命值、音效、排行榜 |
视觉升级 | 使用精灵表、添加动画效果 |
多平台支持 | 移植到Web(Pygame.js)、移动端 |
6.3 潜在应用场景
-
教育领域:
- 作为Python游戏开发教学案例
- 演示面向对象编程概念
-
商业游戏:
- 扩展为付费游戏(添加内购元素)
- 集成广告系统(如激励视频)
-
技术验证:
- 测试AI算法(如训练玩家AI)
- 验证游戏物理引擎表现
七、附录
7.1 依赖管理
项目依赖Pygame库,可通过以下命令安装:
pip install pygame
7.2 运行环境
- Python 3.7+
- Windows/Linux/macOS
- Pygame 2.0+