目录
二、环境搭建:3 步搞定 Pygame 开发环境(附避坑指南)
三、核心概念:用 “动画片” 理解 Pygame 的工作原理

class 卑微码农:
def __init__(self):
self.技能 = ['能读懂十年前祖传代码', '擅长用Ctrl+C/V搭建世界', '信奉"能跑就别动"的玄学']
self.发量 = 100 # 初始发量
self.咖啡因耐受度 = '极限'
def 修Bug(self, bug):
try:
# 试图用玄学解决问题
if bug.严重程度 == '离谱':
print("这一定是环境问题!")
else:
print("让我看看是谁又没写注释...哦,是我自己。")
except Exception as e:
# 如果try块都救不了,那就...
print("重启一下试试?")
self.发量 -= 1 # 每解决一个bug,头发-1
# 实例化一个我
我 = 卑微码农()
引言:让小白也可以写游戏
如果你小时候玩过《雷电》《1942》这类飞机射击游戏,可能会想:“这种看起来简单的 2D 游戏,自己能做出来吗?”

答案是肯定的。用 Python 的 Pygame 库,哪怕是编程新手,也能在一天内做出一个能玩的飞机大战 —— 不需要复杂的数学知识,不用懂 3D 建模,甚至不用会画画(免费素材网站能解决)。
今天这篇文章,我会带你从头到尾开发一个完整的飞机大战游戏,包含敌机生成、子弹发射、碰撞检测、得分系统和音效。全程用大白话解释,代码复制就能跑,每个步骤都有效果图,保证你看完就能上手。
一、为什么学 Pygame?新手做游戏的最佳选择

第一次用 Pygame 时,我惊讶于它的 “亲民”——一行代码就能弹出游戏窗口,十几行代码就能让图片动起来。
和 Unity、Unreal 这些专业游戏引擎比,Pygame 的优势对新手太友好了:
- 门槛低:纯 Python 语法,不用学新语言,几行代码就能看到效果;
- 轻量简单:核心功能就几个模块(绘图、事件、音效),不用记复杂的 API;
- 资源好找:2D 游戏素材(图片、音效)有很多免费网站,不用自己创作;
- 适合练手:从小游戏(贪吃蛇、飞机大战)到中等复杂度(RPG、解谜)都能做。
简单说:想体验 “从 0 做出一个能玩的游戏” 的成就感,Pygame 是最好的起点。
二、环境搭建:3 步搞定 Pygame 开发环境(附避坑指南)

开始写代码前,先把工具准备好。Pygame 支持 Windows、macOS、Linux,操作基本一致,这里以 “Windows 10+Python 3.9” 为例。
步骤 1:安装 Python(已安装可跳过)
Pygame 是 Python 库,首先得装 Python。去官网(https://www.python.org/)下载对应版本,安装时一定要勾选 “Add Python to PATH”(否则后面会报错 “python 不是内部命令”),然后一路 “Next” 完成安装。
验证是否安装成功:按下Win+R,输入cmd打开命令提示符,输入python --version,能看到 “Python 3.x.x” 就说明没问题。
步骤 2:创建虚拟环境(推荐但可选)
和开发其他 Python 项目一样,用虚拟环境隔离依赖更干净:
- 新建一个项目文件夹(比如
D:\plane_war); - 打开 cmd,用
cd命令进入这个文件夹:cd D:\plane_war; - 输入
python -m venv venv创建虚拟环境; - 激活虚拟环境:
- Windows:
venv\Scripts\activate(激活后命令行前会出现(venv)); - macOS/Linux:
source venv/bin/activate。
- Windows:
如果懒得搞虚拟环境,直接跳过这步也行,不影响后续开发。
步骤 3:安装 Pygame
在命令行输入pip install pygame==2.5.2(指定 2.5.2 版本,稳定且兼容性好)。
验证安装:输入python -m pygame.examples.aliens,如果弹出一个外星人射击的小游戏窗口,说明安装成功(关闭游戏窗口继续)。
常见坑点:
- 安装时报 “pip 不是内部命令”:没勾选 “Add Python to PATH”,重新安装并勾选即可;
- 运行示例游戏黑屏 / 闪退:可能是显卡驱动问题,尝试更新驱动或换一个 Python 版本(3.8/3.9 比较稳定)。
三、核心概念:用 “动画片” 理解 Pygame 的工作原理

在写代码前,先搞懂游戏运行的基本逻辑。其实游戏本质上是 “快速切换的图片”,就像动画片:
- 游戏窗口:相当于动画片的 “屏幕”,所有元素都在里面显示;
- 游戏循环:相当于 “播放帧”,每秒刷新几十次(比如 60 帧),让画面动起来;
- 精灵(Sprite):游戏中的角色(飞机、子弹、敌机),可以移动、碰撞;
- 事件处理:监听键盘 / 鼠标操作(比如按方向键移动飞机);
- 碰撞检测:判断两个精灵是否碰到一起(比如子弹打中小飞机)。
用一个简单的比喻:Pygame 就像一个 “动画制作工具”,你只需要告诉它 “每帧画什么、怎么动、响应用户什么操作”,它就会自动把这些帧连起来变成游戏。
四、实战:开发飞机大战游戏(分阶段实现,附完整代码)

我们的目标是做一个这样的飞机大战:
- 玩家控制一架飞机(上下左右移动);
- 按空格发射子弹;
- 屏幕上方不断出现敌机,碰到敌机或被敌机撞都会失败;
- 打中敌机得分,分数越高难度越大;
- 有背景音乐和音效。
全程分 5 个阶段,每个阶段都能独立运行,逐步增加功能。
阶段 1:创建游戏窗口和基本框架
先实现最基础的部分:弹出一个游戏窗口,显示标题和背景,能正常关闭。
步骤 1:编写基础代码
在plane_war文件夹下新建game.py,代码如下:
import pygame
import sys
# 初始化Pygame
pygame.init()
# 游戏窗口设置
SCREEN_WIDTH = 480 # 窗口宽度
SCREEN_HEIGHT = 700 # 窗口高度
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # 创建窗口
pygame.display.set_caption("飞机大战") # 设置窗口标题
# 颜色定义(RGB值)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
# 游戏主循环
running = True
while running:
# 1. 处理事件(比如关闭窗口、按键操作)
for event in pygame.event.get():
# 如果点击窗口关闭按钮,退出游戏
if event.type == pygame.QUIT:
running = False
# 2. 绘制画面(黑色背景)
screen.fill(BLACK)
# 3. 更新显示(刷新画面)
pygame.display.flip()
# 退出游戏
pygame.quit()
sys.exit()
步骤 2:运行代码,查看效果
在 cmd 中运行python game.py,会弹出一个黑色窗口,标题是 “飞机大战”,点击右上角关闭按钮能正常退出 —— 这就是游戏的基础框架。
代码说明:
pygame.init():初始化 Pygame 所有模块(必须放在最前面);pygame.display.set_mode():创建游戏窗口,参数是宽高的元组;- 游戏主循环:这是所有游戏的核心,每秒运行几十次,包含三个关键步骤:
- 处理事件(用户输入);
- 更新游戏状态(移动角色、检测碰撞等);
- 绘制画面并刷新。
阶段 2:添加玩家飞机和移动控制
接下来让玩家飞机显示在屏幕上,并能用方向键控制移动。
步骤 1:准备飞机图片(免费素材获取)
游戏需要用到图片,这里推荐几个免费无版权的素材网站:
- itch.io:搜索 “plane sprite”,很多开发者分享的免费飞机素材;
- pixabay:有大量免费图片,适合做背景;
- opengameart.org:专门的游戏素材网站。
我们用一张简单的玩家飞机图片(比如player_plane.png),放在项目文件夹下的images子文件夹里(先创建images文件夹)。
步骤 2:编写代码加载飞机并实现移动
修改game.py:
import pygame
import sys
pygame.init()
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("飞机大战")
# 加载玩家飞机图片
player_img = pygame.image.load("images/player_plane.png").convert_alpha() # 支持透明背景
# 获取飞机图片的矩形区域(用于定位和碰撞检测)
player_rect = player_img.get_rect()
# 设置飞机初始位置(屏幕底部中间)
player_rect.centerx = SCREEN_WIDTH // 2 # 水平居中
player_rect.bottom = SCREEN_HEIGHT - 10 # 距离底部10像素
# 飞机移动速度
player_speed = 5
# 游戏主循环
running = True
while running:
# 处理事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 持续按键检测(方向键控制)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and player_rect.left > 0: # 左移,不超过左边界
player_rect.x -= player_speed
if keys[pygame.K_RIGHT] and player_rect.right < SCREEN_WIDTH: # 右移,不超过右边界
player_rect.x += player_speed
if keys[pygame.K_UP] and player_rect.top > 0: # 上移,不超过上边界
player_rect.y -= player_speed
if keys[pygame.K_DOWN] and player_rect.bottom < SCREEN_HEIGHT: # 下移,不超过下边界
player_rect.y += player_speed
# 绘制背景(黑色)
screen.fill(BLACK)
# 绘制玩家飞机(将图片画在矩形位置)
screen.blit(player_img, player_rect)
# 刷新显示
pygame.display.flip()
pygame.quit()
sys.exit()
步骤 3:测试飞机移动
运行代码,现在屏幕底部中间会显示你的飞机,按方向键可以移动,而且不会移出窗口边界 —— 角色控制就实现了!
关键代码解析:
pygame.image.load():加载图片,convert_alpha()保留透明背景(飞机边缘不会有白边);get_rect():获取图片的矩形对象(x、y表示左上角坐标,centerx、bottom等是便捷定位属性);pygame.key.get_pressed():检测持续按键(比单次事件更适合移动控制);screen.blit(图片, 位置):将图片绘制到屏幕上。
阶段 3:添加子弹发射和敌机生成
现在让飞机能发射子弹,同时让敌机从屏幕上方飞下来。
步骤 1:准备子弹和敌机图片
同样在images文件夹下放入子弹图片(bullet.png)和敌机图片(enemy_plane.png)。
步骤 2:实现子弹发射功能
修改代码,添加子弹类和发射逻辑:
import pygame
import sys
import random # 用于随机生成敌机位置
pygame.init()
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("飞机大战")
# 加载素材
player_img = pygame.image.load("images/player_plane.png").convert_alpha()
bullet_img = pygame.image.load("images/bullet.png").convert_alpha()
enemy_img = pygame.image.load("images/enemy_plane.png").convert_alpha()
# 玩家飞机设置
player_rect = player_img.get_rect()
player_rect.centerx = SCREEN_WIDTH // 2
player_rect.bottom = SCREEN_HEIGHT - 10
player_speed = 5
# 子弹设置
bullet_speed = 10
bullets = [] # 存储所有子弹的列表
bullet_cooldown = 25 # 发射冷却(数值越大,射速越慢)
bullet_timer = 0 # 冷却计时器
# 敌机设置
enemy_speed = 3
enemies = [] # 存储所有敌机的列表
enemy_spawn_cooldown = 30 # 敌机生成间隔
enemy_spawn_timer = 0 # 生成计时器
# 游戏主循环
running = True
while running:
# 控制游戏帧率(每秒60帧)
pygame.time.Clock().tick(60)
# 处理事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 玩家移动
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and player_rect.left > 0:
player_rect.x -= player_speed
if keys[pygame.K_RIGHT] and player_rect.right < SCREEN_WIDTH:
player_rect.x += player_speed
if keys[pygame.K_UP] and player_rect.top > 0:
player_rect.y -= player_speed
if keys[pygame.K_DOWN] and player_rect.bottom < SCREEN_HEIGHT:
player_rect.y += player_speed
# 子弹发射(按空格键,带冷却)
bullet_timer += 1
if keys[pygame.K_SPACE] and bullet_timer >= bullet_cooldown:
# 创建子弹,位置在飞机顶部中间
bullet_rect = bullet_img.get_rect()
bullet_rect.centerx = player_rect.centerx
bullet_rect.bottom = player_rect.top # 子弹从飞机头部射出
bullets.append(bullet_rect)
bullet_timer = 0 # 重置冷却计时器
# 移动子弹,并移除出界的子弹
for bullet in bullets[:]: # 用切片遍历,避免修改列表时出错
bullet.y -= bullet_speed # 子弹向上飞
if bullet.bottom < 0: # 子弹飞出屏幕顶部
bullets.remove(bullet)
# 生成敌机(带间隔)
enemy_spawn_timer += 1
if enemy_spawn_timer >= enemy_spawn_cooldown:
# 随机生成敌机x坐标(确保在屏幕内)
enemy_x = random.randint(0, SCREEN_WIDTH - enemy_img.get_width())
enemy_rect = enemy_img.get_rect()
enemy_rect.x = enemy_x
enemy_rect.y = -enemy_img.get_height() # 从屏幕顶部外飞入
enemies.append(enemy_rect)
enemy_spawn_timer = 0 # 重置生成计时器
# 移动敌机,并移除出界的敌机
for enemy in enemies[:]:
enemy.y += enemy_speed # 敌机向下飞
if enemy.top > SCREEN_HEIGHT: # 敌机飞出屏幕底部
enemies.remove(enemy)
# 绘制画面
screen.fill(BLACK)
# 绘制玩家飞机
screen.blit(player_img, player_rect)
# 绘制所有子弹
for bullet in bullets:
screen.blit(bullet_img, bullet)
# 绘制所有敌机
for enemy in enemies:
screen.blit(enemy_img, enemy)
# 刷新显示
pygame.display.flip()
pygame.quit()
sys.exit()
步骤 3:测试子弹和敌机
运行代码,按空格键发射子弹(有冷却,不会一次性射出一堆),屏幕上方会不断有敌机飞下来 —— 战斗系统的雏形就有了!
核心逻辑:
- 子弹和敌机都用列表存储,方便批量处理;
- 用计时器(
bullet_timer、enemy_spawn_timer)控制发射和生成频率,避免太密集; - 定期移除出界的子弹和敌机,防止列表无限变大导致卡顿。
阶段 4:添加碰撞检测和得分系统
现在需要判断 “子弹是否打中敌机”“玩家是否撞到敌机”,并统计得分。
步骤 1:修改代码,添加碰撞检测和得分
更新game.py:
import pygame
import sys
import random
pygame.init()
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("飞机大战")
# 加载素材
player_img = pygame.image.load("images/player_plane.png").convert_alpha()
bullet_img = pygame.image.load("images/bullet.png").convert_alpha()
enemy_img = pygame.image.load("images/enemy_plane.png").convert_alpha()
# 玩家设置
player_rect = player_img.get_rect()
player_rect.centerx = SCREEN_WIDTH // 2
player_rect.bottom = SCREEN_HEIGHT - 10
player_speed = 5
player_alive = True # 玩家是否存活
# 子弹设置
bullet_speed = 10
bullets = []
bullet_cooldown = 25
bullet_timer = 0
# 敌机设置
enemy_speed = 3
enemies = []
enemy_spawn_cooldown = 30
enemy_spawn_timer = 0
# 得分系统
score = 0
# 初始化字体(显示得分)
pygame.font.init()
font = pygame.font.SysFont("SimHei", 30) # 用黑体显示中文,字号30
# 游戏主循环
running = True
while running:
pygame.time.Clock().tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if player_alive: # 玩家存活时才处理移动和发射
# 玩家移动(代码同上,略)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and player_rect.left > 0:
player_rect.x -= player_speed
# 省略右、上、下移动代码...
# 子弹发射(代码同上,略)
bullet_timer += 1
if keys[pygame.K_SPACE] and bullet_timer >= bullet_cooldown:
# 省略子弹生成代码...
# 子弹移动和移除(代码同上,略)
# 生成敌机(代码同上,略)
# 敌机移动和移除(代码同上,略)
# 碰撞检测:子弹打中敌机
for bullet in bullets[:]:
for enemy in enemies[:]:
if bullet.colliderect(enemy): # 检测两个矩形是否碰撞
bullets.remove(bullet)
enemies.remove(enemy)
score += 10 # 打中一架敌机得10分
# 得分越高,敌机生成越快(增加难度)
if score % 100 == 0 and enemy_spawn_cooldown > 10:
enemy_spawn_cooldown -= 2 # 每得100分,生成间隔减2
enemy_speed += 0.5 # 敌机速度增加
# 碰撞检测:玩家撞到敌机
for enemy in enemies[:]:
if player_rect.colliderect(enemy):
player_alive = False # 玩家死亡
enemies.remove(enemy)
# 绘制画面
screen.fill(BLACK)
# 绘制玩家飞机(存活时才显示)
if player_alive:
screen.blit(player_img, player_rect)
else:
# 玩家死亡时显示游戏结束文字
game_over_text = font.render("游戏结束!按R重启", True, WHITE)
screen.blit(game_over_text, (SCREEN_WIDTH//2 - 120, SCREEN_HEIGHT//2))
# 绘制子弹和敌机(代码同上,略)
for bullet in bullets:
screen.blit(bullet_img, bullet)
for enemy in enemies:
screen.blit(enemy_img, enemy)
# 绘制得分
score_text = font.render(f"得分:{score}", True, WHITE)
screen.blit(score_text, (10, 10)) # 显示在左上角
# 重启游戏(按R键)
if not player_alive and keys[pygame.K_r]:
# 重置游戏状态
player_alive = True
player_rect.centerx = SCREEN_WIDTH // 2
player_rect.bottom = SCREEN_HEIGHT - 10
bullets.clear()
enemies.clear()
score = 0
enemy_spawn_cooldown = 30
enemy_speed = 3
pygame.display.flip()
pygame.quit()
sys.exit()
步骤 2:测试碰撞和得分
运行代码,现在:
- 子弹打中敌机时,敌机消失,得分增加;
- 玩家撞到敌机后,飞机消失,显示 “游戏结束!按 R 重启”;
- 得分越高,敌机出现得越快、飞得越快(难度递增);
- 按 R 键可以重新开始游戏 —— 一个能玩的飞机大战基本成型了!
关键代码:
colliderect():Pygame 内置的矩形碰撞检测函数,判断两个rect是否重叠;pygame.font:用于显示文字(得分和游戏结束提示),SysFont("SimHei", 30)确保中文正常显示;- 难度递增逻辑:通过
score % 100 == 0判断得分里程碑,动态调整敌机生成速度和移动速度。
阶段 5:添加背景、音效和爆炸效果
最后一步,给游戏加背景图、发射 / 爆炸音效和击中动画,让体验更完整。
步骤 1:准备资源
- 背景图(
background.png):放在images文件夹; - 发射音效(
shoot.wav)、爆炸音效(explosion.wav):放在sound文件夹(新建); - 爆炸动画图片(
explosion1.png、explosion2.png...):放在images文件夹(可选,简单版可用一张图)。
步骤 2:添加背景和音效
修改代码,完整版本如下:
import pygame
import sys
import random
pygame.init()
# 初始化混音器(处理音效)
pygame.mixer.init()
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("飞机大战")
# 加载素材
# 背景图(两张一样的图,用于滚动效果)
bg_img1 = pygame.image.load("images/background.png").convert()
bg_img2 = pygame.image.load("images/background.png").convert()
bg_y1 = 0 # 第一张背景y坐标
bg_y2 = -SCREEN_HEIGHT # 第二张背景y坐标(初始在屏幕上方)
player_img = pygame.image.load("images/player_plane.png").convert_alpha()
bullet_img = pygame.image.load("images/bullet.png").convert_alpha()
enemy_img = pygame.image.load("images/enemy_plane.png").convert_alpha()
# 爆炸图片
explosion_img = pygame.image.load("images/explosion.png").convert_alpha()
# 加载音效
shoot_sound = pygame.mixer.Sound("sound/shoot.wav") # 发射音效
explosion_sound = pygame.mixer.Sound("sound/explosion.wav") # 爆炸音效
shoot_sound.set_volume(0.2) # 降低音量(0-1)
explosion_sound.set_volume(0.2)
# 玩家设置
player_rect = player_img.get_rect()
player_rect.centerx = SCREEN_WIDTH // 2
player_rect.bottom = SCREEN_HEIGHT - 10
player_speed = 5
player_alive = True
# 子弹设置
bullet_speed = 10
bullets = []
bullet_cooldown = 25
bullet_timer = 0
# 敌机设置
enemy_speed = 3
enemies = []
enemy_spawn_cooldown = 30
enemy_spawn_timer = 0
# 爆炸效果存储(位置和动画帧)
explosions = []
# 得分系统
score = 0
font = pygame.font.SysFont("SimHei", 30)
# 游戏主循环
running = True
while running:
pygame.time.Clock().tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 背景滚动(模拟飞机向前飞)
bg_y1 += 2
bg_y2 += 2
if bg_y1 >= SCREEN_HEIGHT:
bg_y1 = -SCREEN_HEIGHT # 第一张图滚出屏幕后,移到顶部
if bg_y2 >= SCREEN_HEIGHT:
bg_y2 = -SCREEN_HEIGHT # 第二张图同理
# 绘制背景(先画背景,再画角色,避免角色被遮挡)
screen.blit(bg_img1, (0, bg_y1))
screen.blit(bg_img2, (0, bg_y2))
if player_alive:
# 玩家移动
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and player_rect.left > 0:
player_rect.x -= player_speed
if keys[pygame.K_RIGHT] and player_rect.right < SCREEN_WIDTH:
player_rect.x += player_speed
if keys[pygame.K_UP] and player_rect.top > 0:
player_rect.y -= player_speed
if keys[pygame.K_DOWN] and player_rect.bottom < SCREEN_HEIGHT:
player_rect.y += player_speed
# 子弹发射(带音效)
bullet_timer += 1
if keys[pygame.K_SPACE] and bullet_timer >= bullet_cooldown:
bullet_rect = bullet_img.get_rect()
bullet_rect.centerx = player_rect.centerx
bullet_rect.bottom = player_rect.top
bullets.append(bullet_rect)
bullet_timer = 0
shoot_sound.play() # 播放发射音效
# 子弹移动和移除
for bullet in bullets[:]:
bullet.y -= bullet_speed
if bullet.bottom < 0:
bullets.remove(bullet)
# 生成敌机
enemy_spawn_timer += 1
if enemy_spawn_timer >= enemy_spawn_cooldown:
enemy_x = random.randint(0, SCREEN_WIDTH - enemy_img.get_width())
enemy_rect = enemy_img.get_rect()
enemy_rect.x = enemy_x
enemy_rect.y = -enemy_img.get_height()
enemies.append(enemy_rect)
enemy_spawn_timer = 0
# 敌机移动和移除
for enemy in enemies[:]:
enemy.y += enemy_speed
if enemy.top > SCREEN_HEIGHT:
enemies.remove(enemy)
# 子弹打敌机碰撞检测
for bullet in bullets[:]:
for enemy in enemies[:]:
if bullet.colliderect(enemy):
bullets.remove(bullet)
enemies.remove(enemy)
score += 10
# 记录爆炸位置
explosions.append({
"rect": pygame.Rect(enemy.x, enemy.y, enemy.width, enemy.height),
"frame": 0 # 动画帧(简单版用一张图,复杂版可循环切换)
})
explosion_sound.play() # 播放爆炸音效
# 难度递增
if score % 100 == 0 and enemy_spawn_cooldown > 10:
enemy_spawn_cooldown -= 2
enemy_speed += 0.5
# 玩家撞敌机碰撞检测
for enemy in enemies[:]:
if player_rect.colliderect(enemy):
player_alive = False
enemies.remove(enemy)
# 玩家爆炸效果
explosions.append({
"rect": pygame.Rect(player_rect.x, player_rect.y, player_rect.width, player_rect.height),
"frame": 0
})
explosion_sound.play()
# 处理爆炸动画(简单版显示10帧后消失)
for exp in explosions[:]:
exp["frame"] += 1
if exp["frame"] > 10: # 控制爆炸显示时间
explosions.remove(exp)
else:
# 绘制爆炸图片
screen.blit(explosion_img, exp["rect"])
# 绘制玩家飞机
if player_alive:
screen.blit(player_img, player_rect)
else:
game_over_text = font.render("游戏结束!按R重启", True, WHITE)
screen.blit(game_over_text, (SCREEN_WIDTH//2 - 120, SCREEN_HEIGHT//2))
# 绘制子弹和敌机
for bullet in bullets:
screen.blit(bullet_img, bullet)
for enemy in enemies:
screen.blit(enemy_img, enemy)
# 绘制得分
score_text = font.render(f"得分:{score}", True, WHITE)
screen.blit(score_text, (10, 10))
# 重启游戏
keys = pygame.key.get_pressed()
if not player_alive and keys[pygame.K_r]:
player_alive = True
player_rect.centerx = SCREEN_WIDTH // 2
player_rect.bottom = SCREEN_HEIGHT - 10
bullets.clear()
enemies.clear()
explosions.clear()
score = 0
enemy_spawn_cooldown = 30
enemy_speed = 3
pygame.display.flip()
pygame.quit()
sys.exit()
步骤 3:最终测试
现在运行游戏,你会看到:
- 背景图不断向下滚动,模拟飞行感;
- 发射子弹时有 “咻” 的音效,击中敌机有爆炸音效;
- 敌机和玩家被击中时会显示爆炸图片;
- 得分和难度动态变化,按 R 键可重启 —— 一个完整的飞机大战游戏就做好了!
五、常见问题与优化技巧(新手必看)

开发过程中难免遇到各种小问题,这里整理几个高频坑点和优化建议:
1. 图片加载失败或不显示
- 原因:路径错误(比如图片放在
images里,代码却写成"player_plane.png"); - 解决:用绝对路径调试(比如
"D:/plane_war/images/player.png"),确认路径正确后再改相对路径; - 技巧:用
os.path.join处理路径,兼容不同系统(Windows 用\,Linux 用/):
import os
# 正确的路径写法
image_path = os.path.join("images", "player_plane.png")
player_img = pygame.image.load(image_path).convert_alpha()
2. 中文显示乱码或方块
- 原因:Pygame 默认字体不支持中文;
- 解决:指定支持中文的字体,如
SimHei(黑体)、Microsoft YaHei(微软雅黑):
font = pygame.font.SysFont(["SimHei", "Microsoft YaHei"], 30) # 多个字体备选
3. 游戏卡顿或帧率不稳定
- 原因:没有控制帧率,或列表中存储了太多元素(比如没及时移除出界的子弹);
- 解决:
- 用
pygame.time.Clock().tick(60)固定每秒 60 帧; - 定期清理列表(如子弹、敌机),避免元素过多;
- 复杂游戏可使用
pygame.sprite.Sprite类管理角色,效率更高。
- 用
4. 音效无法播放或报错
- 原因:音效文件格式不对(Pygame 支持 wav、ogg 等,不支持 mp3);
- 解决:用格式转换工具(如格式工厂)将 mp3 转为 wav;
- 技巧:降低音效音量(
set_volume(0.2)),避免刺耳。
六、扩展功能:让你的游戏更丰富(练手建议)
学会基础版后,可以尝试添加这些功能,提升游戏复杂度:
- 多类型敌机:大型敌机(血厚、得分高)、小型敌机(速度快);
- 道具系统:随机掉落护盾(免伤)、双发子弹、减速等道具;
- 生命值和关卡:玩家有 3 条命,每过一关敌机难度提升;
- 排行榜:用文件存储最高分,显示历史最佳成绩;
- 动画优化:给飞机添加移动动画(多张图片切换),爆炸效果用多帧动画。
七、免费资源网站推荐(避免版权问题)
做游戏离不开素材,这些网站的资源可以免费商用,不用担心版权问题:
-
图片素材:
- itch.io:https://itch.io/game-assets/free (大量 2D 游戏角色、背景);
- opengameart.org:https://opengameart.org/ (分类清晰,支持筛选 “CC0 协议” 资源);
- pixabay:https://pixabay.com/ (通用图片,适合做背景)。
-
音效素材:
- freesound.org:https://freesound.org/ (需要注册,音效种类多);
- 魔王魂:https://maou.audio/ (日本免费音效站,有游戏专用音效);
- 爱给网:https://www.aigei.com/ (国内网站,部分免费音效适合新手)。
总结:从玩游戏到做游戏的成就感
回顾整个开发过程,我们从一个空白窗口,一步步添加了飞机移动、子弹发射、敌机生成、碰撞检测、音效背景,最终做出了一个能玩的飞机大战。这个过程中,你不仅学会了 Pygame 的用法,更理解了游戏开发的核心逻辑 —— 其实没那么神秘,就是 “循环刷新画面 + 响应用户操作”。
Pygame 的优势在于 “低门槛、高反馈”:哪怕是几行代码的修改(比如调整子弹速度、换一张敌机图片),都能立刻在游戏中看到效果,这种 “即时反馈” 正是学习编程的最佳动力。
如果你是编程新手,建议先照着本文的代码敲一遍,感受从 0 到 1 的过程;熟悉后再尝试修改参数(比如调整难度曲线),最后挑战添加新功能(如道具系统)。当你能独立完成一个小游戏时,不仅编程能力会提升,更能收获 “自己做的游戏真好玩” 的成就感。
祝你在游戏开发的路上,玩得开心,学得尽兴!
5231

被折叠的 条评论
为什么被折叠?



