行业资讯

Python游戏开发实战:从零构建飞机大战游戏,掌握Pygame核心机制

发布时间:2026/8/4 12:22:33
Python游戏开发实战:从零构建飞机大战游戏,掌握Pygame核心机制 1. 项目概述从零到一用Python构建你的第一款射击游戏“飞机大战”这个名字对于很多80后、90后的朋友来说几乎就是童年电脑课的代名词。在那个像素风的年代控制一架小飞机在屏幕上穿梭躲避弹幕击落敌机是无数人的编程启蒙。今天我们不用再去翻找那些古老的BASIC代码而是用当下最流行、也最适合入门的Python语言亲手把这个经典游戏复刻出来。这不仅仅是一个怀旧项目。对于正在学习Python的你来说它是一个绝佳的实战演练场。你会接触到游戏循环、事件处理、碰撞检测、精灵动画、音效播放等游戏开发的核心概念。整个过程就像搭积木从绘制第一架静止的飞机到让它动起来再到加入敌机和子弹最后配上音效和分数每一步都有明确的反馈成就感十足。无论你是刚学完Python基础语法想找个项目练手的新手还是有一定经验想了解Pygame这类2D游戏库的开发者这个项目都能让你在动手的乐趣中巩固循环、条件判断、列表、类与对象等知识点并直观地看到代码如何创造出交互的乐趣。我们将使用一个名为Pygame的第三方库。别被“第三方库”吓到它本质上就是一群前辈写好的、专门用来做游戏的工具包我们直接调用就行省去了从零绘制像素、处理底层声音的麻烦。整个项目代码量适中结构清晰我将会带你一步步拆解并分享我在实现过程中踩过的坑和总结的技巧确保你能跟着做出来并且理解每一步为什么要这么做。2. 开发环境搭建与核心工具选型工欲善其事必先利其器。在开始写游戏代码之前我们需要把“厨房”收拾好。2.1 Python解释器与Pygame库安装首先确保你的电脑上安装了Python。我强烈推荐使用Python 3.7或以上的版本它们在性能和库的兼容性上更好。如果你还没安装可以去Python官网下载安装包记得在安装时勾选“Add Python to PATH”这个选项这能让你在命令行中直接使用python命令。安装好Python后我们就要请出今天的“主角”——Pygame库。安装它非常简单只需要打开你的命令行Windows上是CMD或PowerShellMac/Linux上是终端输入以下命令并回车pip install pygame如果下载速度慢可以临时使用国内的镜像源加速比如清华的源pip install pygame -i https://pypi.tuna.tsinghua.edu.cn/simple看到“Successfully installed pygame-xx.x.x”的字样就说明安装成功了。为了验证安装是否真的没问题我建议你不要直接相信提示而是跑一个简单的测试脚本。新建一个test_pygame.py文件写入下面三行代码import pygame pygame.init() print(“Pygame初始化成功”)然后在命令行运行它python test_pygame.py。如果终端打印出了成功信息并且没有报错特别是没有关于音频或视频驱动的错误那么你的环境就妥了。注意有些同学在这一步可能会遇到关于SDL2库的错误。这通常是系统缺少某些底层多媒体依赖导致的。在Windows上可以尝试安装最新的Visual C Redistributable在Mac上用Homebrew安装sdl2等相关库brew install sdl2 sdl2_image sdl2_mixer sdl2_ttf在Linux上使用包管理器安装libsdl2系列开发包。绝大多数情况下pip install pygame会自动处理好这些依赖但了解这个背景有助于你未来排查更复杂的问题。2.2 代码编辑器与项目结构规划写代码需要一个顺手的编辑器。对于Python开发VSCode和PyCharm是两大主流选择。VSCode轻量、插件丰富配置Python环境也很方便PyCharm是专为Python设计的IDE功能更强大开箱即用。你可以根据喜好任选其一。我个人在写这种中小型项目时更偏爱VSCode因为它启动快对硬件要求低。在开始疯狂编码前花几分钟规划一下项目结构能让你后续的维护轻松十倍。我建议在硬盘上新建一个名为plane_war的文件夹然后在里面创建如下结构的文件和子文件夹plane_war/ ├── main.py # 游戏主程序入口 ├── game/ │ ├── __init__.py │ ├── plane.py # 玩家飞机类 │ ├── enemy.py # 敌机类 │ ├── bullet.py # 子弹类 │ └── settings.py # 游戏全局设置如屏幕大小、颜色、速度等 ├── assets/ │ ├── images/ # 存放所有图片素材背景、飞机、爆炸效果等 │ └── sounds/ # 存放所有音效素材射击、爆炸、背景音乐等 └── README.md # 项目说明文档可选但好习惯这种模块化的结构把不同的功能划分到不同的文件中。settings.py集中管理所有可调节的参数比如你想调快游戏节奏只需要去这一个文件里修改几个数字而不是在成千上万行代码里大海捞针。assets文件夹集中存放图片和声音方便管理和引用。这是从“写得出代码”到“写得好代码”的关键一步。3. 游戏核心架构与主循环剖析任何一款游戏其底层都有一个不断运转的“心脏”我们称之为游戏主循环。理解了这个循环你就理解了游戏运行的基本原理。3.1 事件处理、更新与渲染游戏的三部曲主循环每一帧可以简单理解为每秒几十次都重复做三件事事件处理检查有没有发生什么事情比如玩家按下了键盘、移动了鼠标、点击了关闭按钮。Pygame会把这些外部输入收集成“事件”我们需要检查并处理它们。状态更新根据发生的事件和游戏逻辑更新所有游戏对象的状态。比如如果检测到按下了“左箭头键”那么玩家飞机的x坐标就应该减少敌机应该向下移动检查子弹是否击中了敌机如果击中敌机状态应变为“爆炸”玩家分数增加。渲染绘制把当前所有游戏对象的状态画到屏幕上去。包括背景图、飞机、子弹、分数文字等。这一帧画完屏幕更新玩家就看到了一幅新的画面。紧接着循环立刻开始下一帧。这个过程周而复始直到游戏结束。用Pygame实现的基础骨架代码如下我把它放在main.py里import pygame import sys from game.settings import * # 初始化pygame和字体模块 pygame.init() pygame.font.init() screen pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption(“Python飞机大战”) clock pygame.time.Clock() # 创建一个时钟对象用于控制帧率 # 游戏主循环标志 running True while running: # 1. 事件处理 for event in pygame.event.get(): if event.type pygame.QUIT: # 点击窗口关闭按钮 running False # 后续会在这里添加键盘按下/松开的事件处理 # 2. 状态更新 (目前还是空的后续会把飞机、敌机的更新逻辑放在这里) # 例如player.update() enemy_group.update() # 3. 渲染绘制 screen.fill(BLACK) # 用黑色填充整个屏幕相当于清屏 # 后续会在这里绘制背景、飞机、子弹等 # 例如screen.blit(background_img, (0, 0)) # player.draw(screen) pygame.display.flip() # 将绘制好的内容更新到屏幕上 clock.tick(60) # 控制循环每秒最多运行60次即帧率为60 FPS pygame.quit() sys.exit()这段代码虽然现在什么都做不了屏幕只是一片黑但它搭建了一个坚固的舞台。clock.tick(60)是性能关键它确保循环不会跑得太快耗尽CPU也不会太慢导致游戏卡顿稳定在60帧每秒提供流畅的视觉体验。3.2 游戏精灵与精灵组面向对象的设计在2D游戏中所有能动的、能画出来的东西飞机、子弹、敌机、爆炸动画我们都可以抽象为“精灵”。Pygame提供了一个pygame.sprite.Sprite基类。我们的核心设计思想是为每一种游戏对象创建一个继承自Sprite的类。这样做的好处太多了封装每个类管理自己的数据位置、图像、速度和行为移动、绘制、碰撞检测。复用创建多个敌机实例就是创建多个Enemy类的对象。高效管理Pygame的pygame.sprite.Group类可以高效管理一群精灵。比如把所有敌机放在一个enemy_group里一句enemy_group.update()就能更新所有敌机的位置一句enemy_group.draw(screen)就能把所有敌机画出来。这就是我们在game/文件夹下创建plane.py,enemy.py,bullet.py的原因。接下来我们就从玩家飞机开始把这些精灵一个个实现。4. 核心游戏对象实现详解让我们把游戏中的角色一个个请上台赋予它们生命。4.1 玩家飞机操控与边界限制玩家飞机是我们控制的主角。在game/plane.py中我们定义PlayerPlane类。import pygame from pygame.sprite import Sprite from game.settings import * class PlayerPlane(Sprite): def __init__(self): super().__init__() # 初始化父类Sprite # 加载飞机图像convert_alpha()用于支持透明背景PNG图片 self.image pygame.image.load(“assets/images/player.png”).convert_alpha() # 获取图像的矩形区域用于定位和碰撞检测 self.rect self.image.get_rect() # 设置飞机的初始位置屏幕底部居中 self.rect.centerx SCREEN_WIDTH // 2 self.rect.bottom SCREEN_HEIGHT - 10 # 设置水平移动速度 self.speed PLAYER_SPEED # 一个标志用于记录当前按下的方向键实现持续移动 self.moving_left False self.moving_right False # 子弹冷却相关属性控制发射频率 self.bullet_cooldown 0 self.bullet_cooldown_time PLAYER_SHOOT_COOLDOWN # 单位帧 def update(self): 更新飞机状态每帧调用一次 # 处理左右移动 if self.moving_left and self.rect.left 0: self.rect.x - self.speed if self.moving_right and self.rect.right SCREEN_WIDTH: self.rect.x self.speed # 处理子弹冷却 if self.bullet_cooldown 0: self.bullet_cooldown - 1 def start_move(self, direction): 开始向某个方向移动 if direction ‘left’: self.moving_left True elif direction ‘right’: self.moving_right True def stop_move(self, direction): 停止向某个方向移动 if direction ‘left’: self.moving_left False elif direction ‘right’: self.moving_right False def shoot(self, bullet_group): 发射子弹如果冷却完毕则创建子弹并加入子弹组 if self.bullet_cooldown 0: # 创建子弹位置在飞机顶部中央 bullet Bullet(self.rect.centerx, self.rect.top) bullet_group.add(bullet) # 播放射击音效后续添加 # shoot_sound.play() # 重置冷却时间 self.bullet_cooldown self.bullet_cooldown_time return True return False这里有几个关键点图像与矩形self.image是显示的样子self.rect是它在屏幕上的位置和碰撞区域。所有位置判断、碰撞检测都基于rect。平滑移动我们没有在事件处理中直接修改rect的位置而是通过设置moving_left和moving_right标志位。在update()方法里根据标志位来持续改变位置。这样做的优点是移动更平滑并且可以同时处理多个键位虽然这里只有左右。边界限制在update的移动逻辑中加了条件判断self.rect.left 0和self.rect.right SCREEN_WIDTH确保飞机不会飞出屏幕外。子弹冷却通过一个计数器bullet_cooldown实现。每次发射后重置为冷却时间例如10帧每帧减1减到0才能再次发射。这是防止玩家“泼水”式射击让游戏更有节奏感的基础。4.2 敌机自动生成、移动与类型分化敌机是游戏的挑战来源。在game/enemy.py中我们实现Enemy类。为了让游戏更有趣我们可以设计多种敌机。import pygame from pygame.sprite import Sprite import random from game.settings import * class Enemy(Sprite): def __init__(self, enemy_type‘small’): super().__init__() self.type enemy_type # 根据类型加载不同图像和属性 if enemy_type ‘small’: self.image pygame.image.load(“assets/images/enemy_small.png”).convert_alpha() self.speed ENEMY_SMALL_SPEED self.health ENEMY_SMALL_HEALTH self.score ENEMY_SMALL_SCORE elif enemy_type ‘medium’: self.image pygame.image.load(“assets/images/enemy_medium.png”).convert_alpha() self.speed ENEMY_MEDIUM_SPEED self.health ENEMY_MEDIUM_HEALTH self.score ENEMY_MEDIUM_SCORE else: # large self.image pygame.image.load(“assets/images/enemy_large.png”).convert_alpha() self.speed ENEMY_LARGE_SPEED self.health ENEMY_LARGE_HEALTH self.score ENEMY_LARGE_SCORE self.rect self.image.get_rect() # 敌机从屏幕顶部随机水平位置出现 self.rect.x random.randint(0, SCREEN_WIDTH - self.rect.width) self.rect.y random.randint(-100, -40) # 从屏幕上方之外开始出现 # 可以给大型敌机添加一个横向移动的摆动 self.direction 1 if random.random() 0.5 else -1 def update(self): 敌机向下移动大型敌机可能伴有横向摆动 self.rect.y self.speed if self.type ‘large’: self.rect.x self.direction * 1 # 缓慢横向移动 # 碰到屏幕边缘则反弹 if self.rect.left 0 or self.rect.right SCREEN_WIDTH: self.direction * -1 # 如果敌机完全飞出屏幕底部则将其删除以释放内存 if self.rect.top SCREEN_HEIGHT: self.kill() def hit(self, damage): 被子弹击中减少生命值返回是否被摧毁 self.health - damage if self.health 0: # 播放爆炸音效和动画后续添加 return True return False敌机的设计体现了游戏的“生产者-消费者”模式。我们会在主循环中定时生成敌机实例并加入enemy_group。它们自己负责向下移动update并在移出屏幕后自我销毁kill()。hit方法处理伤害为后续实现不同威力的子弹或敌机血量差异留出接口。区分敌机类型小、中、大能显著增加游戏策略性和视觉层次。4.3 子弹飞行轨迹与碰撞使命子弹是玩家与敌机交互的媒介。在game/bullet.py中实现Bullet类。import pygame from pygame.sprite import Sprite from game.settings import * class Bullet(Sprite): def __init__(self, x, y): super().__init__() # 子弹可以很简单就是一个矩形或者小图片 self.image pygame.Surface((BULLET_WIDTH, BULLET_HEIGHT)) self.image.fill(BULLET_COLOR) # 比如黄色子弹 # 也可以加载子弹图片 # self.image pygame.image.load(“assets/images/bullet.png”).convert_alpha() self.rect self.image.get_rect() self.rect.centerx x self.rect.centery y self.speed BULLET_SPEED def update(self): 子弹向上飞行 self.rect.y - self.speed # 如果子弹飞出屏幕顶部则销毁以节省资源 if self.rect.bottom 0: self.kill()子弹的逻辑非常简单诞生于飞机头部以固定速度向上飞行飞出屏幕即销毁。它的核心使命是在update过程中由游戏主逻辑检测其rect是否与任何敌机的rect发生重叠碰撞如果发生则触发命中逻辑。5. 游戏逻辑整合与高级功能实现现在演员精灵都已就位我们需要一个导演主程序来编排它们并搭建更复杂的舞台效果。5.1 碰撞检测、分数计算与生命值系统碰撞检测是射击游戏的灵魂。Pygame提供了非常方便的精灵组碰撞检测方法。我们在主循环的“状态更新”阶段加入这些逻辑。首先在主程序main.py中初始化精灵和精灵组# ... 初始化pygame ... from game.plane import PlayerPlane from game.bullet import Bullet from game.enemy import Enemy # 创建精灵组 all_sprites pygame.sprite.Group() # 包含所有需要绘制的精灵 enemies pygame.sprite.Group() player_bullets pygame.sprite.Group() # 创建玩家 player PlayerPlane() all_sprites.add(player) # 分数和生命值 score 0 lives PLAYER_INITIAL_LIVES font pygame.font.SysFont(None, 36) # 创建字体对象用于显示分数然后在主循环的“状态更新”部分加入敌机生成、碰撞检测和游戏状态更新的代码# 游戏主循环 while running: # --- 事件处理 --- for event in pygame.event.get(): if event.type pygame.QUIT: running False # 键盘按下事件 elif event.type pygame.KEYDOWN: if event.key pygame.K_LEFT: player.start_move(‘left’) elif event.key pygame.K_RIGHT: player.start_move(‘right’) elif event.key pygame.K_SPACE: player.shoot(player_bullets) # 按下空格发射子弹 # 键盘松开事件 elif event.type pygame.KEYUP: if event.key pygame.K_LEFT: player.stop_move(‘left’) elif event.key pygame.K_RIGHT: player.stop_move(‘right’) # --- 状态更新 --- # 1. 更新所有精灵 (玩家、子弹、敌机) all_sprites.update() # 2. 随机生成敌机 (控制生成频率) if random.randint(1, ENEMY_SPAWN_RATE) 1: # 例如 ENEMY_SPAWN_RATE60则平均每秒生成一个 enemy_type random.choices([‘small’, ‘medium’, ‘large’], weights[70, 25, 5])[0] new_enemy Enemy(enemy_type) all_sprites.add(new_enemy) enemies.add(new_enemy) # 3. 子弹与敌机的碰撞检测 # pygame.sprite.groupcollide 返回一个字典记录哪些子弹击中了哪些敌机 hits pygame.sprite.groupcollide(enemies, player_bullets, False, True) # 敌机不立即删除子弹删除 for enemy, bullets_hit in hits.items(): for bullet in bullets_hit: # 实际上一颗子弹击中一个敌机后就被删除了这里循环是严谨写法 if enemy.hit(BULLET_DAMAGE): # 如果敌机被击中后生命值归零 score enemy.score enemy.kill() # 敌机销毁 # 这里可以触发爆炸效果 # 4. 敌机与玩家的碰撞检测 (游戏失败条件) if pygame.sprite.spritecollideany(player, enemies): lives - 1 # 发生碰撞后可以有一个短暂的无敌时间并清屏所有敌机 if lives 0: running False # 游戏结束 else: # 重置玩家位置并清空当前敌机 player.rect.centerx SCREEN_WIDTH // 2 for enemy in enemies: enemy.kill() # --- 渲染绘制 --- screen.fill(BLACK) # 绘制所有精灵 all_sprites.draw(screen) # 绘制分数和生命值文本 score_text font.render(f‘Score: {score}’, True, WHITE) lives_text font.render(f‘Lives: {lives}’, True, WHITE) screen.blit(score_text, (10, 10)) screen.blit(lives_text, (SCREEN_WIDTH - 100, 10)) pygame.display.flip() clock.tick(60)这段代码整合了游戏的核心逻辑敌机生成使用random模块控制生成频率和类型权重让小型敌机最常见大型敌机稀有。碰撞检测pygame.sprite.groupcollide用于检测两组精灵之间的所有碰撞参数False, True表示碰撞后敌机不立即删除因为要调用hit方法判断血量子弹立即删除。pygame.sprite.spritecollideany用于检测单个精灵玩家与一个精灵组敌机组是否发生碰撞。游戏状态管理通过score和lives变量跟踪游戏进程。碰撞后减少生命生命为0则游戏结束。5.2 音效、背景与粒子效果增强一个只有图形和逻辑的游戏是沉默的。接下来我们为游戏注入声音和视觉活力。添加音效和背景音乐在settings.py中定义音效文件路径然后在游戏初始化时加载# settings.py BG_MUSIC “assets/sounds/background.ogg” SHOOT_SOUND “assets/sounds/shoot.wav” EXPLOSION_SOUND “assets/sounds/explosion.wav”在main.py初始化部分加载# 加载音效 pygame.mixer.init() try: shoot_sound pygame.mixer.Sound(SHOOT_SOUND) explosion_sound pygame.mixer.Sound(EXPLOSION_SOUND) # 设置音量 shoot_sound.set_volume(0.3) explosion_sound.set_volume(0.5) # 播放背景音乐 (-1表示循环播放) pygame.mixer.music.load(BG_MUSIC) pygame.mixer.music.set_volume(0.2) pygame.mixer.music.play(-1) except pygame.error as e: print(f“无法加载音效或音乐: {e}“) # 即使没有音效游戏也应能继续运行 shoot_sound None explosion_sound None然后在player.shoot()和enemy.hit()当敌机被摧毁时的相应位置播放音效。添加滚动背景静态背景太枯燥一个缓慢滚动的星空背景能极大增强沉浸感。我们可以准备一张高度是屏幕两倍以上的背景图通过不断改变其绘制位置来实现循环滚动。# 在main.py初始化部分 background_img pygame.image.load(“assets/images/background.png”).convert() background_y1 0 background_y2 -SCREEN_HEIGHT # 第二张背景图紧接在第一张上方 # 在主循环的渲染部分替换 screen.fill(BLACK) background_y1 1 # 背景滚动速度 background_y2 1 if background_y1 SCREEN_HEIGHT: background_y1 -SCREEN_HEIGHT if background_y2 SCREEN_HEIGHT: background_y2 -SCREEN_HEIGHT screen.blit(background_img, (0, background_y1)) screen.blit(background_img, (0, background_y2))简单的粒子爆炸效果当敌机被击毁时除了播放音效还可以生成一些简单的粒子来模拟爆炸。我们可以创建一个简单的Particle类在爆炸位置生成一些随机方向运动、逐渐缩小并消失的小矩形或小图片。class Particle(Sprite): def __init__(self, x, y, color): super().__init__() self.radius random.randint(2, 5) self.image pygame.Surface((self.radius*2, self.radius*2), pygame.SRCALPHA) pygame.draw.circle(self.image, color, (self.radius, self.radius), self.radius) self.rect self.image.get_rect(center(x, y)) self.velocity [random.uniform(-2, 2), random.uniform(-2, 2)] self.lifetime random.randint(20, 40) # 粒子存活的帧数 def update(self): self.rect.x self.velocity[0] self.rect.y self.velocity[1] self.lifetime - 1 if self.lifetime 0: self.kill()在敌机被摧毁的位置生成一批这样的粒子并加入all_sprites组它们就会自动被更新和绘制形成短暂的爆炸效果。6. 性能优化、调试与发布打包游戏基本功能完成后我们还需要关注它的流畅度、健壮性以及如何分享给别人。6.1 性能优化技巧与常见问题排查随着屏幕上精灵数量的增多比如满屏子弹和敌机游戏可能会变卡。以下是一些立竿见影的优化手段图像优化使用convert()和convert_alpha()这是最重要的优化。对于不透明图片如背景加载后立即调用image.convert()对于带透明通道的图片如飞机、特效使用image.convert_alpha()。这会将图片转换成与当前屏幕显示格式一致的内部格式大幅提升blit绘制速度。统一图像尺寸和格式尽量使用PNG无损压缩支持透明或JPG有损压缩文件小。避免在游戏运行时缩放图片尽量使用原尺寸或预先缩放好的尺寸。精灵组管理及时销毁确保飞出屏幕的子弹、被击毁的敌机及时调用kill()方法将它们从精灵组中移除。内存中堆积大量不可见的精灵是性能杀手。分层绘制如果游戏复杂可以考虑使用pygame.sprite.LayeredUpdates替代普通的Group将背景、敌机、子弹、UI等分到不同层避免不必要的重绘。控制帧率与计算量clock.tick(60)已经帮我们限定了最大帧率。对于不那么需要高帧率的游戏可以降低到30或45帧能显著降低CPU占用。复杂的碰撞检测如像素级精确检测collide_mask非常耗资源。在飞机大战中矩形碰撞collide_rect完全够用且速度快得多。调试心得使用print大法在关键位置如碰撞发生时、敌机生成时打印变量状态是定位逻辑错误最简单有效的方法。可视化调试可以临时在update或draw方法中用pygame.draw.rect(screen, RED, self.rect, 1)把精灵的碰撞矩形画出来直观地看碰撞框是否准确。性能分析如果感觉卡顿可以在主循环里打印clock.get_fps()查看实际帧率。如果帧率远低于设定值说明有一处或多处代码成了性能瓶颈。6.2 游戏状态管理与发布为可执行文件一个完整的游戏应该有开始界面、游戏进行中、暂停、结束界面等不同状态。我们可以用一个简单的状态机来管理class GameState: MENU 1 PLAYING 2 GAME_OVER 3 current_state GameState.MENU在主循环中根据current_state的值执行不同的事件处理、更新和渲染逻辑。例如在MENU状态检测鼠标点击“开始”按钮在PLAYING状态运行我们上面写的所有游戏逻辑在GAME_OVER状态显示最终分数和“重新开始”按钮。最后如果你想将游戏分享给没有安装Python的朋友可以使用PyInstaller将其打包成独立的可执行文件.exe。首先安装PyInstallerpip install pyinstaller然后在项目根目录plane_war/下执行pyinstaller --onefile --windowed --add-data “assets;assets” main.py--onefile打包成单个exe文件。--windowed运行时不显示命令行窗口。--add-data “assets;assets”将assets文件夹内的资源一起打包进去Windows用分号;分隔Mac/Linux用冒号:。打包完成后在dist文件夹里就能找到你的游戏exe文件了。记得在不同的电脑上测试一下确保资源路径都能正确访问。从一行行代码到一架架翱翔的飞机从寂静无声到子弹呼啸、敌机爆炸你用Python亲手构建了一个充满活力的小世界。这个过程里你实践了面向对象编程理解了游戏循环处理了用户输入实现了碰撞逻辑还优化了性能。这远不止是一个“飞机大战”游戏它是一个完整的、可扩展的2D游戏原型。你可以基于它轻松地更换素材、设计新的敌机攻击模式、添加道具系统、甚至引入Boss战。编程最大的乐趣莫过于此——创造并掌控。希望这个项目能成为你Python学习路上一个坚实的里程碑更希望它能点燃你对游戏开发更深厚的兴趣。