
1. 项目概述从“武装飞船”到Python游戏开发实战最近在社区里看到不少朋友对“Python武装飞船”这个项目感兴趣这确实是一个经典且极具代表性的入门级游戏开发实战案例。它本质上是一个使用Python的Pygame库构建的2D射击游戏玩家控制一艘飞船在屏幕底部移动射击从屏幕顶部不断下落的敌机。别看它听起来简单这个项目几乎囊括了游戏开发的所有核心概念游戏循环、事件处理、精灵Sprite管理、碰撞检测、状态管理以及资源加载。对于想从“写脚本”迈向“做应用”的Python学习者来说这是一个绝佳的跳板。它能让你直观地理解面向对象编程OOP如何在实际项目中组织代码并亲手体验从零搭建一个可交互程序的完整流程。无论你是刚学完Python基础语法想找个项目练手还是对游戏开发有朦胧的兴趣这个“武装飞船”都能给你带来扎实的收获。2. 核心技术栈与工具选型解析2.1 为什么是Pygame在Python的游戏开发库中Pygame并非性能最强或功能最现代的但它对于初学者而言是近乎完美的选择。其核心优势在于“直接”和“透明”。它基于SDLSimple DirectMedia Layer库提供了一套访问多媒体组件如图形、声音的简单Python接口。你不用被复杂的游戏引擎编辑器所困扰每一行代码都直接对应着屏幕上的一个像素、一段声音或一次键盘事件。这种“所见即所得”的编程体验对于理解游戏底层运行机制至关重要。相比之下像Unity或Godot这样的引擎虽然强大但抽象层级高初学者容易迷失在编辑器和组件系统中而忽略了编程逻辑本身。Pygame让你专注于游戏逻辑的构建。注意Pygame的“过时”论调时常出现但对于学习核心概念而言它并不过时。它的API稳定社区资源丰富教程、问答、开源项目极多几乎你遇到的每一个问题都能在网上找到答案。先掌握Pygame再转向更高级的引擎你的基础会牢固得多。2.2 开发环境搭建要点一个顺畅的开发环境是高效编码的前提。对于这个项目我强烈推荐VSCode Python扩展的组合。Python版本确保安装Python 3.8或更高版本。在官网下载安装时务必勾选“Add Python to PATH”这是避免后续无数环境问题的最关键一步。安装完成后在命令行输入python --version验证。安装Pygame打开终端Windows的CMD或PowerShellmacOS/Linux的Terminal使用pip安装pip install pygame。如果速度慢可以使用国内镜像源例如pip install pygame -i https://pypi.tuna.tsinghua.edu.cn/simple。配置VSCode安装官方“Python”扩展。在项目文件夹下按CtrlShiftP输入“Python: Select Interpreter”选择你刚安装的Python解释器。创建一个.vscode/launch.json文件配置调试参数可以让你在VSCode中直接按F5运行和调试游戏打断点查看变量状态这对调试游戏逻辑异常方便。虚拟环境可选但推荐使用python -m venv venv在项目目录创建虚拟环境然后激活它。这能保证项目依赖的独立性避免不同项目间包版本的冲突。对于新手可以先跳过但养成这个好习惯对未来管理复杂项目大有裨益。3. 项目架构与核心模块设计一个结构清晰的代码架构是项目可维护、可扩展的基石。我们不能把所有代码都堆在一个文件里。对于“武装飞船”我建议采用如下模块化设计alien_invasion/ # 项目根目录 ├── main.py # 程序入口初始化游戏并启动主循环 ├── settings.py # 存储所有游戏设置屏幕尺寸、颜色、飞船速度、子弹速度等 ├── game_stats.py # 游戏统计信息得分、生命、等级 ├── ship.py # 飞船类封装飞船的属性和行为移动、绘制 ├── bullet.py # 子弹类封装子弹的属性和行为发射、移动、绘制 ├── alien.py # 外星人类封装外星人的属性和行为移动、绘制、编队 ├── button.py # 按钮类用于创建开始、暂停等UI按钮 ├── scoreboard.py # 记分牌类负责在屏幕上渲染得分、等级、剩余飞船数 └── assets/ # 资源目录 ├── images/ # 存放飞船、外星人、子弹的图片 └── sounds/ # 存放射击、爆炸、背景音乐等音效这种设计的核心思想是“单一职责”。每个类只负责管理一种游戏元素。settings.py集中管理所有配置项修改游戏难度只需调整这里的几个数字无需在代码中四处搜寻。game_stats.py跟踪游戏状态scoreboard.py只关心如何把这些状态漂亮地画出来。当你想增加一种新武器或新敌人时只需创建一个新的类文件然后在主逻辑中调用即可不会影响原有代码。3.1 游戏主循环心脏与脉搏游戏主循环是任何游戏程序的引擎。在main.py中它的伪代码逻辑如下def run_game(): # 初始化pygame、设置、屏幕对象 pygame.init() ai_settings Settings() screen pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height)) pygame.display.set_caption(Alien Invasion) # 创建游戏对象飞船、子弹编组、外星人编组、统计信息、记分牌、按钮 ship Ship(ai_settings, screen) bullets pygame.sprite.Group() aliens pygame.sprite.Group() stats GameStats(ai_settings) sb Scoreboard(ai_settings, screen, stats) play_button Button(ai_settings, screen, Play) # 创建外星人群 create_fleet(ai_settings, screen, ship, aliens) # 开始主循环 while True: # 1. 监听事件键盘、鼠标 check_events(ai_settings, screen, stats, sb, play_button, ship, aliens, bullets) if stats.game_active: # 2. 更新游戏对象状态如果游戏处于活动状态 ship.update() update_bullets(ai_settings, screen, stats, sb, ship, aliens, bullets) update_aliens(ai_settings, stats, screen, sb, ship, aliens, bullets) # 3. 绘制最新画面 update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets, play_button) # 4. 控制帧率通常60FPS clock.tick(60)这个循环每秒执行数十次。每次迭代它都做四件事处理输入、更新状态、渲染画面、控制节奏。理解这个循环就理解了实时应用程序的运作本质。clock.tick(60)确保了游戏以大致恒定的速度运行不会因为电脑性能差异而变得过快或过慢。4. 核心类实现与关键代码剖析4.1 Ship类玩家的化身ship.py中的Ship类是我们控制的核心。它的核心职责是响应键盘事件进行左右移动并将自己的图像绘制到屏幕上。import pygame from pygame.sprite import Sprite class Ship(Sprite): def __init__(self, ai_settings, screen): 初始化飞船并设置其初始位置 super(Ship, self).__init__() # Python 2/3兼容写法Python 3中可直接写 super().__init__() self.screen screen self.ai_settings ai_settings # 加载飞船图像并获取其外接矩形 self.image pygame.image.load(assets/images/ship.bmp) # 确保图片背景透明或与屏幕背景色一致 self.rect self.image.get_rect() self.screen_rect screen.get_rect() # 将每艘新飞船放在屏幕底部中央 self.rect.centerx self.screen_rect.centerx self.rect.bottom self.screen_rect.bottom # 在飞船的属性center中存储小数值以实现更平滑的移动 self.center float(self.rect.centerx) # 移动标志 self.moving_right False self.moving_left False def update(self): 根据移动标志调整飞船的位置 # 更新飞船的center值而不是rect if self.moving_right and self.rect.right self.screen_rect.right: self.center self.ai_settings.ship_speed_factor if self.moving_left and self.rect.left 0: self.center - self.ai_settings.ship_speed_factor # 根据self.center更新rect对象 self.rect.centerx self.center def blitme(self): 在指定位置绘制飞船 self.screen.blit(self.image, self.rect) def center_ship(self): 让飞船在屏幕上居中 self.center self.screen_rect.centerx关键点解析继承Sprite让飞船成为精灵便于后续使用Pygame的精灵组进行高效的碰撞检测和批量绘制。使用self.center存储浮点数rect的属性如centerx只能是整数。如果直接用整数速度更新在低速下比如每次移动0.5像素会因取整而无法移动。用浮点数self.center累加速度再赋值给rect.centerx可以实现平滑移动。边界检测在update()中检查self.rect.right self.screen_rect.right和self.rect.left 0防止飞船移出屏幕。图像处理ship.bmp最好使用背景透明的图片格式如PNG或者确保其背景色与游戏背景色一致。BMP格式不支持透明通常需要手动处理。4.2 Bullet类火力单元bullet.py中的Bullet类代表子弹。子弹的行为很简单向上移动飞出屏幕后自动消失。import pygame from pygame.sprite import Sprite class Bullet(Sprite): 一个对飞船发射的子弹进行管理的类 def __init__(self, ai_settings, screen, ship): 在飞船所处的位置创建一个子弹对象 super(Bullet, self).__init__() self.screen screen # 在(0,0)处创建一个表示子弹的矩形再设置正确的位置 self.rect pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height) self.rect.centerx ship.rect.centerx self.rect.top ship.rect.top # 存储用小数表示的子弹位置 self.y float(self.rect.y) self.color ai_settings.bullet_color self.speed_factor ai_settings.bullet_speed_factor def update(self): 向上移动子弹 # 更新表示子弹位置的小数值 self.y - self.speed_factor # 更新表示子弹的rect的位置 self.rect.y self.y def draw_bullet(self): 在屏幕上绘制子弹 pygame.draw.rect(self.screen, self.color, self.rect)关键点解析使用pygame.Rect创建图形对于简单的几何图形如矩形子弹直接使用pygame.draw.rect比加载图片更高效。子弹位置子弹的初始centerx与飞船一致top与飞船的top一致这样看起来就像是从飞船头部发射的。精灵组管理在主程序中我们将所有子弹对象添加到一个pygame.sprite.Group()中。主循环里调用bullets.update()会自动调用组内每个子弹的update()方法调用bullets.draw(screen)会自动绘制所有子弹前提是精灵类有image和rect属性我们这里用了自定义的draw_bullet所以需要遍历组手动绘制。精灵组极大地简化了多个同类对象的管理。4.3 Alien类与编队算法敌人的智慧alien.py定义了单个外星人而如何让一群外星人整齐地移动并触及边界后下移、转向是项目的难点和亮点。import pygame from pygame.sprite import Sprite class Alien(Sprite): 表示单个外星人的类 def __init__(self, ai_settings, screen): 初始化外星人并设置其起始位置 super(Alien, self).__init__() self.screen screen self.ai_settings ai_settings # 加载外星人图像并设置其rect属性 self.image pygame.image.load(assets/images/alien.bmp) self.rect self.image.get_rect() # 每个外星人最初都在屏幕左上角附近 self.rect.x self.rect.width self.rect.y self.rect.height # 存储外星人的准确位置 self.x float(self.rect.x) def blitme(self): 在指定位置绘制外星人 self.screen.blit(self.image, self.rect) def update(self): 向左或向右移动外星人 self.x (self.ai_settings.alien_speed_factor * self.ai_settings.fleet_direction) self.rect.x self.x def check_edges(self): 如果外星人位于屏幕边缘就返回True screen_rect self.screen.get_rect() if self.rect.right screen_rect.right: return True elif self.rect.left 0: return True return False外星人群的创建和更新逻辑通常在主程序或一个工具函数中def create_fleet(ai_settings, screen, ship, aliens): 创建外星人群 # 创建一个外星人并计算一行可容纳多少个外星人 # 外星人间距为外星人宽度 alien Alien(ai_settings, screen) alien_width alien.rect.width number_aliens_x get_number_aliens_x(ai_settings, alien_width) number_rows get_number_rows(ai_settings, ship.rect.height, alien.rect.height) # 创建外星人群 for row_number in range(number_rows): for alien_number in range(number_aliens_x): create_alien(ai_settings, screen, aliens, alien_number, row_number) def get_number_aliens_x(ai_settings, alien_width): 计算每行可容纳多少个外星人 available_space_x ai_settings.screen_width - 2 * alien_width number_aliens_x int(available_space_x / (2 * alien_width)) return number_aliens_x def get_number_rows(ai_settings, ship_height, alien_height): 计算屏幕可容纳多少行外星人 available_space_y (ai_settings.screen_height - (3 * alien_height) - ship_height) number_rows int(available_space_y / (2 * alien_height)) return number_rows def create_alien(ai_settings, screen, aliens, alien_number, row_number): 创建一个外星人并将其放在当前行 alien Alien(ai_settings, screen) alien_width alien.rect.width alien.x alien_width 2 * alien_width * alien_number alien.rect.x alien.x alien.rect.y alien.rect.height 2 * alien.rect.height * row_number aliens.add(alien) def update_aliens(ai_settings, stats, screen, sb, ship, aliens, bullets): 检查是否有外星人位于屏幕边缘并更新整群外星人的位置 check_fleet_edges(ai_settings, aliens) aliens.update() # 检测外星人和飞船之间的碰撞 if pygame.sprite.spritecollideany(ship, aliens): ship_hit(ai_settings, stats, screen, sb, ship, aliens, bullets) # 检查是否有外星人到达了屏幕底端 check_aliens_bottom(ai_settings, stats, screen, sb, ship, aliens, bullets) def check_fleet_edges(ai_settings, aliens): 有外星人到达边缘时采取相应的措施 for alien in aliens.sprites(): if alien.check_edges(): change_fleet_direction(ai_settings, aliens) break def change_fleet_direction(ai_settings, aliens): 将整群外星人下移并改变它们的方向 for alien in aliens.sprites(): alien.rect.y ai_settings.fleet_drop_speed ai_settings.fleet_direction * -1编队算法精要动态计算行列数get_number_aliens_x和get_number_rows函数根据屏幕尺寸、飞船预留空间和外星人尺寸动态计算能放下多少行、多少列外星人。这使得游戏能适配不同的屏幕分辨率。fleet_direction巧用正负在settings.py中设置fleet_direction 11表示右移-1表示左移。在Alien.update()中移动距离是速度 * 方向。当任何外星人触边时change_fleet_direction被调用将所有外星人下移一段距离并将fleet_direction乘以 -1从而实现整体转向。这种用单个变量控制整个编队方向的方法非常简洁优雅。碰撞检测pygame.sprite.spritecollideany(ship, aliens)用于检测飞船是否与任何外星人相撞。pygame.sprite.groupcollide(bullets, aliens, True, True)用于检测子弹和外星人群的碰撞并同时删除发生碰撞的子弹和外星人。Pygame的精灵组碰撞方法效率很高。5. 游戏状态管理与用户体验增强5.1 游戏统计与记分牌GameStats类跟踪游戏动态数据Scoreboard类负责将其渲染到屏幕上。# game_stats.py class GameStats: 跟踪游戏的统计信息 def __init__(self, ai_settings): 初始化统计信息 self.ai_settings ai_settings self.reset_stats() # 游戏刚启动时处于非活动状态 self.game_active False # 在任何情况下都不应重置最高得分 self.high_score 0 def reset_stats(self): 初始化在游戏运行期间可能变化的统计信息 self.ships_left self.ai_settings.ship_limit self.score 0 self.level 1 # scoreboard.py import pygame.font from pygame.sprite import Group class Scoreboard: 显示得分信息的类 def __init__(self, ai_settings, screen, stats): self.screen screen self.screen_rect screen.get_rect() self.ai_settings ai_settings self.stats stats # 显示得分信息时使用的字体设置 self.text_color (30, 30, 30) self.font pygame.font.SysFont(None, 48) # 准备初始得分图像、最高得分图像、等级图像和剩余飞船图像 self.prep_score() self.prep_high_score() self.prep_level() self.prep_ships() def prep_score(self): 将得分转换为一幅渲染的图像 rounded_score int(round(self.stats.score, -1)) # 圆整到10的倍数 score_str {:,}.format(rounded_score) # 千位分隔符格式化 self.score_image self.font.render(score_str, True, self.text_color, self.ai_settings.bg_color) # 将得分放在屏幕右上角 self.score_rect self.score_image.get_rect() self.score_rect.right self.screen_rect.right - 20 self.score_rect.top 20 def prep_high_score(self): 将最高得分转换为渲染的图像 high_score int(round(self.stats.high_score, -1)) high_score_str {:,}.format(high_score) self.high_score_image self.font.render(high_score_str, True, self.text_color, self.ai_settings.bg_color) # 将最高得分放在屏幕顶部中央 self.high_score_rect self.high_score_image.get_rect() self.high_score_rect.centerx self.screen_rect.centerx self.high_score_rect.top self.score_rect.top def prep_level(self): 将等级转换为渲染的图像 self.level_image self.font.render(str(self.stats.level), True, self.text_color, self.ai_settings.bg_color) # 将等级放在得分下方 self.level_rect self.level_image.get_rect() self.level_rect.right self.score_rect.right self.level_rect.top self.score_rect.bottom 10 def prep_ships(self): 显示还余下多少艘飞船 self.ships Group() for ship_number in range(self.stats.ships_left): ship Ship(self.ai_settings, self.screen) ship.rect.x 10 ship_number * ship.rect.width ship.rect.y 10 self.ships.add(ship) def show_score(self): 在屏幕上显示得分、最高分、等级和剩余飞船 self.screen.blit(self.score_image, self.score_rect) self.screen.blit(self.high_score_image, self.high_score_rect) self.screen.blit(self.level_image, self.level_rect) self.ships.draw(self.screen)核心技巧得分格式化{:,}.format(score)可以给数字添加千位分隔符让大数字更易读。得分圆整round(score, -1)将得分圆整到最近的10的倍数避免因击落不同外星人获得不同分数而导致得分频繁跳动视觉上更舒服。用精灵组显示生命值prep_ships方法巧妙地创建了一个由小飞船图标组成的精灵组self.ships用来表示剩余生命。通过self.ships.draw(self.screen)一次性绘制管理起来非常方便。最高分持久化目前的high_score存储在内存中游戏关闭后会丢失。一个常见的增强功能是将其写入一个文本文件如high_score.txt或简单的数据库游戏启动时读取。5.2 游戏流程控制开始、结束与难度递增游戏状态game_active是整个流程的开关。当game_active为False时显示“Play”按钮游戏对象不更新。当玩家点击按钮game_active变为True游戏开始。难度递增机制通常在外星人群被全部消灭后触发。在update_bullets函数中检测到aliens精灵组为空时并非简单地创建一群新外星人而是提升游戏等级stats.level 1。根据等级提高外星人速度、子弹速度等例如ai_settings.alien_speed_factor * 1.1。清空现有子弹创建一群新的、移动更快的外星人。调用sb.prep_level()更新等级显示。游戏结束条件飞船被撞在update_aliens中检测到碰撞后调用ship_hit函数。该函数将ships_left减1更新记分牌清空屏幕上的外星人和子弹将飞船重新居中并暂停一小段时间pygame.time.delay(500)让玩家反应。如果ships_left为0则将game_active设为False。外星人抵达屏幕底端在update_aliens中调用check_aliens_bottom检查是否有外星人的rect.bottom screen_rect.bottom。如果有则视同飞船被撞同样调用ship_hit处理。6. 项目扩展与性能优化思路完成基础版本后你可以通过以下方式让游戏更具挑战性和趣味性这也是提升编程能力的绝佳练习6.1 功能扩展建议添加音效和背景音乐使用pygame.mixer.Sound()加载WAV文件在子弹发射、外星人爆炸、飞船被撞等事件发生时播放。背景音乐可以使用pygame.mixer.music.load()和pygame.mixer.music.play(-1)循环播放。实现多种武器系统创建LaserBullet、Missile等子类继承自Bullet基类拥有不同的速度、伤害和图像。为飞船添加一个weapon_type属性和切换武器的按键如数字键1、2、3。设计不同类型的敌人创建StrongAlien需要击中多次、FastAlien移动速度快、BossAlien体积大、有特定攻击模式等类继承或组合Alien类。可以设置不同的分数和出现波次。添加障碍物或掩体创建Barrier类用多个小矩形块组合而成。子弹和外星人撞到掩体会损坏掩体改变颜色或消失一部分增加战术深度。实现关卡和Boss战将游戏流程结构化。例如完成3波普通外星人后进入Boss关。Boss有独立的生命条和攻击模式。集成粒子系统为爆炸效果添加简单的粒子。当外星人或飞船被摧毁时在其位置生成多个小的、随机方向运动的彩色矩形或图片持续几帧后消失。6.2 性能优化与代码质量图像与声音资源优化转换与缩放对于图片使用convert()或convert_alpha()方法可以显著提高Pygame的绘制速度。例如self.image pygame.image.load(ship.png).convert_alpha()。重用Surface对于不变的游戏元素如背景、UI元素加载一次后存储在变量中避免在每一帧都重新加载或创建。声音格式音效使用较小的WAV文件背景音乐可以使用MP3或OGG但注意播放兼容性。精灵组管理优化及时清理对于已经飞出屏幕或应该被销毁的精灵如子弹务必将其从精灵组中remove()或使用kill()方法。积累大量不可见精灵会严重拖慢碰撞检测和绘制。分层绘制如果游戏元素很多可以考虑使用pygame.sprite.LayeredUpdates替代普通的Group来控制绘制顺序例如子弹在飞船之上UI在一切之上。事件处理优化事件过滤在复杂的游戏中可以使用pygame.event.set_allowed()来限制Pygame队列只接收你关心的事件类型如KEYDOWN,KEYUP,MOUSEBUTTONDOWN,QUIT减少不必要的处理开销。代码结构优化配置文件将更多的游戏参数如各种速度、生命值、得分规则放入settings.py甚至外部的JSON/YAML文件中使游戏平衡性调整无需修改代码。状态机当游戏状态变得复杂如开始菜单、游戏进行中、暂停、游戏结束、关卡过渡可以考虑引入一个简单的状态机来管理使逻辑更清晰。7. 常见问题与调试技巧实录在开发过程中你几乎一定会遇到下面这些问题。这里是我踩过坑后总结的排查思路。7.1 画面闪烁或撕裂现象游戏画面快速更新时出现闪烁或横向撕裂线。原因与解决这是典型的“屏幕重绘”问题。Pygame默认是单缓冲在绘制过程中屏幕会显示中间状态。解决方案在初始化屏幕后使用双缓冲。创建屏幕对象时加上pygame.DOUBLEBUF标志并在每帧绘制完成后调用pygame.display.flip()。screen pygame.display.set_mode((width, height), pygame.DOUBLEBUF) # ... 在主循环的绘制部分最后 ... pygame.display.flip()7.2 精灵图像背景为黑色方块现象加载的PNG图片显示出来但周围有黑色背景。原因与解决Pygame对透明通道的支持需要正确的方法。解决方案使用convert_alpha()方法加载带透明度的图片。self.image pygame.image.load(ship.png).convert_alpha()如果图片本身是BMP等不支持透明的格式需要手动设置颜色键colorkey将某种颜色设为透明self.image pygame.image.load(ship.bmp).convert() self.image.set_colorkey((0, 0, 0)) # 将黑色设为透明7.3 键盘响应不灵敏或“粘键”现象按住方向键移动飞船感觉有延迟或卡顿有时松开键后飞船还继续移动。原因与解决事件处理逻辑错误确保在事件循环 (pygame.event.get()) 中正确处理KEYDOWN和KEYUP事件准确设置和重置moving_right这类移动标志。帧率不稳定主循环没有使用clock.tick(fps)进行帧率控制导致更新速度不可预测。确保在主循环末尾调用它。系统按键重复有些操作系统会为长按的键生成重复的KEYDOWN事件可能会干扰逻辑。Pygame的KEYDOWN事件有一个event.key属性可以检查event.mod或使用pygame.key.get_pressed()来获取持续的按键状态后者通常更适用于游戏中的连续移动控制。7.4 碰撞检测不准确或无效现象子弹明明穿过了外星人却没有发生碰撞或者碰撞区域和图像显示不匹配。原因与解决Rect区域不匹配pygame.sprite.collide_rect默认使用精灵的rect属性进行矩形碰撞检测。确保你的精灵图片的rect大小和位置准确代表了它的视觉轮廓。对于非矩形轮廓可以使用pygame.sprite.collide_circle圆形检测或collide_mask基于像素的精确检测性能开销大。更新顺序问题碰撞检测必须在所有相关精灵的update()方法被调用之后进行。确保你的主循环中先bullets.update()和aliens.update()再调用pygame.sprite.groupcollide()。精灵组为空检查你的碰撞检测代码是否在正确的精灵组上调用。确保子弹和外星人确实被添加到了对应的精灵组中。7.5 游戏运行越来越卡现象游戏运行一段时间后帧率明显下降。原因与解决这是内存泄漏或资源未释放的典型表现。精灵未销毁这是最常见的原因。子弹飞出屏幕后必须从bullets组中移除 (kill())。外星人被击中后也要移除。使用print(len(bullets))在循环中打印数量观察是否持续增长。Surface未释放如果你在每一帧都创建新的Surface例如每次都在update_screen里用pygame.font.render创建文字Surface旧的Surface没有被垃圾回收会导致内存占用上升。对于需要频繁更新的文字如得分应该在分数改变时才重新渲染 (prep_score)而不是每帧渲染。音效未管理大量播放短音效而不加限制也可能导致问题。确保音效文件不要太大且同一音效不要同时播放太多实例。调试Pygame程序一个最朴素也最有效的方法就是使用print()语句。在怀疑出问题的位置如碰撞检测函数、更新函数打印关键变量的值如精灵位置、精灵组长度、游戏状态可以快速定位逻辑错误。当程序复杂后学会使用VSCode的调试器设置断点、单步执行、查看变量状态效率会高得多。