1. 项目介绍与准备工作相信大家都玩过Chrome浏览器里那个经典的离线小恐龙游戏。当网络连接断开时这只可爱的小恐龙就会出现在屏幕上按空格键就能开始游戏。今天我们要用Python的pygame模块完整复刻这个经典游戏。为什么选择pygame它可以说是Python游戏开发的最佳入门选择。相比其他游戏引擎pygame轻量易上手对2D游戏支持完善社区资源丰富。我做过统计90%的Python游戏教程都会首选pygame作为教学工具。开发环境准备Python 3.6推荐3.8pygame模块最新稳定版代码编辑器VS Code/PyCharm等安装pygame只需要一行命令pip install pygame游戏素材准备恐龙精灵图站立、奔跑、下蹲三种状态仙人掌障碍物大小两种飞鸟障碍物背景图地面和云朵提示可以在Chrome源码中找到原始素材或者自己用绘图工具制作。建议图片尺寸不要超过100x100像素保持复古风格。2. 游戏核心类设计2.1 恐龙角色类恐龙是游戏的主角需要实现三种状态奔跑默认状态跳跃按上键下蹲按下键class Dinosaur: def __init__(self): self.run_img [pygame.image.load(dino_run1.png), pygame.image.load(dino_run2.png)] self.jump_img pygame.image.load(dino_jump.png) self.duck_img [pygame.image.load(dino_duck1.png), pygame.image.load(dino_duck2.png)] self.state RUN # RUN/JUMP/DUCK self.step_index 0 # 用于动画切换 self.jump_velocity 8 # 跳跃初速度 self.rect pygame.Rect(50, 300, 40, 60) # 碰撞检测矩形跳跃物理实现是关键。我参考了经典抛物线公式y y0 v0*t 0.5*a*t^2在代码中通过每帧减少y坐标模拟跳跃用重力加速度实现下落def jump(self): self.rect.y - self.jump_velocity self.jump_velocity - 0.5 # 重力加速度 if self.jump_velocity -8: # 落地判定 self.jump_velocity 8 self.state RUN2.2 障碍物系统障碍物分为两类仙人掌地面障碍飞鸟空中障碍使用面向对象的设计模式先定义基类class Obstacle: def __init__(self, image): self.image image self.rect self.image.get_rect() self.rect.x 800 # 从右侧屏幕外出现 def update(self): self.rect.x - game_speed # 随游戏速度左移 if self.rect.x -self.rect.width: # 移出屏幕后删除 obstacles.pop()然后实现具体障碍物类。这里有个技巧使用随机数控制障碍物生成频率和类型class Cactus(Obstacle): def __init__(self): rand_type random.randint(0, 2) super().__init__(cactus_imgs[rand_type]) self.rect.y 325 # 地面高度 class Bird(Obstacle): def __init__(self): super().__init__(bird_imgs[0]) self.rect.y random.choice([250, 290]) # 两个飞行高度 self.animation_index 0 def update(self): super().update() # 翅膀扇动动画 self.animation_index 1 self.image bird_imgs[self.animation_index % 2]3. 游戏主循环实现3.1 游戏状态管理我们需要管理几个核心状态游戏速度随时间递增增加难度分数计算碰撞检测游戏结束判断def main(): global game_speed, score clock pygame.time.Clock() player Dinosaur() obstacles [] game_speed 10 score 0 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 and not player.jumping: player.jump() # 游戏逻辑更新 player.update() if random.randint(0, 100) 2: # 2%概率生成障碍物 obstacles.append(random.choice([Cactus(), Bird()])) # 碰撞检测 for obstacle in obstacles: if player.rect.colliderect(obstacle.rect): game_over() # 渲染 draw_background() player.draw() for obstacle in obstacles: obstacle.draw() show_score(score) # 游戏加速 score 1 if score % 100 0: game_speed 0.5 clock.tick(30) # 30FPS3.2 无限滚动背景实现地面无限滚动的技巧是使用两张相同的背景图交替def draw_background(): global x_pos_bg image_width BG.get_width() screen.blit(BG, (x_pos_bg, 380)) screen.blit(BG, (image_width x_pos_bg, 380)) x_pos_bg - game_speed if x_pos_bg -image_width: x_pos_bg 0云朵的移动速度应该比地面慢营造景深效果class Cloud: def __init__(self): self.x random.randint(800, 1200) self.y random.randint(50, 150) self.speed random.uniform(0.5, 1.5) def update(self): self.x - self.speed if self.x -100: self.x random.randint(800, 1200)4. 高级功能扩展4.1 计分系统优化原始游戏只是简单计时我们可以增加跳跃加分连续躲避奖励最高分记录def show_score(score): font pygame.font.SysFont(None, 30) text font.render(fScore: {score}, True, (0,0,0)) screen.blit(text, (700, 20)) # 显示最高分 if score high_score: save_high_score(score) high_text font.render(fHigh: {high_score}, True, (0,0,0)) screen.blit(high_text, (700, 50))4.2 游戏难度曲线通过多种方式动态调整难度基础速度随时间增加障碍物生成频率提高出现双障碍物组合障碍物间距缩小def adjust_difficulty(): global game_speed, obstacle_frequency if score 500: obstacle_frequency 3 # 生成概率提高到3% if score 1000: game_speed min(20, game_speed) # 不超过20 if score 1500 and random.random() 0.3: spawn_double_obstacles() # 30%概率生成双障碍5. 常见问题解决在开发过程中我遇到过几个典型问题碰撞检测不准确解决方案为每个精灵设置精确的碰撞矩形调试技巧临时绘制碰撞框可视化检测区域动画卡顿原因图片加载耗时优化预加载所有素材到内存def load_images(): return [pygame.image.load(f) for f in glob.glob(assets/*.png)]游戏速度不稳定关键使用clock.tick()控制帧率注意所有移动计算应该基于帧时间而非固定值内存泄漏现象长时间运行后卡顿解决及时删除移出屏幕的障碍物对象这个项目虽然不大但涵盖了游戏开发的完整流程。从最初的200行代码原型经过多次迭代优化最终成品大约500行代码。建议大家可以先实现基础功能再逐步添加高级特性。