Pygame 速查手册
引言
Pygame 是基于 Simple DirectMedia Layer (SDL) 的跨平台 Python 模块,专为编写视频游戏设计。它提供了图形、声音、输入处理等游戏开发所需的核心功能,非常适合初学者快速上手 2D 游戏开发,也足够灵活支持一些复杂的项目。
本文旨在作为 Pygame 的快速参考指南,覆盖从初始化到高级特性的主要知识点。每个部分都包含关键函数、简短示例以及实用评论,帮助你在实际开发中快速查阅。
1. 安装与初始化
安装
1 | pip install pygame |
验证安装:1
2import pygame
print(pygame.version.ver)
初始化
使用 pygame.init() 一次性初始化所有模块,或单独初始化所需模块(如 pygame.display.init())。
1 | import pygame |
评论:
pygame.init()会尝试初始化所有模块,如果某个模块失败(例如缺少音频硬件),仍会继续执行,但后续使用该模块可能出错。建议根据需求单独初始化。- 主循环中必须调用
pygame.event.get()来处理事件队列,否则窗口会无响应。 clock.tick(60)不仅控制帧率,还返回上一帧经过的时间(毫秒),可用于基于时间的运动。
2. 核心概念
表面(Surface)
Surface 是 Pygame 中表示图像的对象。屏幕(display)本身就是一个 Surface,你可以创建额外的 Surface 用于绘图或缓存。
1 | surf = pygame.Surface((50, 50)) # 创建一个 50x50 的透明表面 |
矩形(Rect)
Rect 对象存储矩形坐标和尺寸,提供许多便捷方法(碰撞检测、移动、合并等)。
1 | rect = pygame.Rect(10, 20, 100, 50) # x, y, width, height |
颜色(Color)
Pygame 使用 (R, G, B) 三元组或 (R, G, B, A) 四元组表示颜色。pygame.Color 对象提供颜色名称和转换。
1 | red = pygame.Color(255, 0, 0) |
时钟(Clock)
用于控制时间,限制帧率,获取时间间隔。
事件(Event)
所有输入(键盘、鼠标、窗口事件)都以事件形式放入队列,由 pygame.event.get() 获取。
评论:
- Surface 的
blit()是绘制图像的核心方法,理解它的工作机制(源 Surface 和目标位置)至关重要。 - Rect 对象的属性(如
x,y,top,left,center,size等)都是可读写的,极大简化了坐标计算。 - 事件处理通常放在主循环开头,避免累积导致输入延迟。
3. 图形绘制
Pygame 提供直接在 Surface 上绘制基本形状的函数(位于 pygame.draw 模块)。
1 | # 绘制矩形 |
评论:
- 实心形状通过省略线宽参数或设为 0 实现;线宽 >0 仅绘制边框。
- 抗锯齿函数位于
pygame.gfxdraw,但需要 SDL_gfx 库支持,通常预装。对于简单抗锯齿,也可使用pygame.draw.aaline和pygame.draw.aalines。 - 频繁绘制大量形状时性能可能下降,可考虑使用 Sprite 或预渲染表面优化。
4. 图像处理
加载和显示
1 | image = pygame.image.load("player.png") # 支持 PNG, JPG, GIF 等 |
变换
1 | # 缩放 |
像素访问
1 | pxarray = pygame.PixelArray(image) # 将 Surface 转为二维数组 |
评论:
convert()和convert_alpha()将图像转换为屏幕像素格式,提高 blit 速度。不调用时,每次 blit 都会进行转换,影响性能。- 旋转操作会改变图像尺寸(生成的新矩形可能变大),通常结合
get_rect(center=原中心)保持位置不变。 PixelArray锁定 Surface,操作完毕后必须释放,否则无法对该 Surface 进行其他操作。
5. 文字显示
初始化字体模块
1 | pygame.font.init() |
使用系统字体
1 | font = pygame.font.Font(None, 36) # None 表示默认字体,36 字号 |
加载自定义字体
1 | font = pygame.font.Font("myfont.ttf", 24) |
文字属性
1 | # 渲染模式:True 表示抗锯齿,背景色可选 |
评论:
- 字体渲染开销较大,建议将静态文字渲染一次并缓存 Surface,避免每帧渲染。
- 默认字体通常不支持中文,如需显示中文,需加载中文字体文件,并确保字符串为 Unicode(如
u"你好"或直接使用中文字符串)。 - 抗锯齿渲染效果更平滑,但背景色必须与最终 blit 的背景一致,否则会有黑边。
6. 音频
初始化混音器
1 | pygame.mixer.init(frequency=22050, size=-16, channels=2, buffer=512) |
音效(短音频)
1 | sound = pygame.mixer.Sound("explosion.wav") |
背景音乐(长音频,如 MP3)
1 | pygame.mixer.music.load("theme.mp3") |
评论:
- 音效使用 Sound 对象,适合短小、频繁触发的声音;背景音乐使用 Music 流式播放,占用内存小。
- 不同音频格式支持取决于 SDL 编译选项,一般 WAV、OGG 支持良好,MP3 可能受限。
- 音效过多可能混叠,可通过为每个 Sound 设置独立的
Channel进行管理。
7. 用户输入
事件处理(推荐)
1 | for event in pygame.event.get(): |
实时按键状态(连续响应)
1 | keys = pygame.key.get_pressed() |
评论:
- 事件处理适合单次触发动作(如跳跃、菜单选择);状态轮询适合持续移动(如按住方向键)。
- 键盘常量和鼠标按钮常量可在
pygame.locals中找到(但通常直接使用pygame.K_xxx即可,因为全局命名空间已导入)。 - 注意
pygame.event.get()会清空事件队列,如果需要同时处理事件和状态轮询,应先处理事件。
8. 精灵和组
Sprite 基类
1 | class Player(pygame.sprite.Sprite): |
精灵组
1 | all_sprites = pygame.sprite.Group() |
碰撞检测
1 | # 两个组之间的碰撞,返回字典 {精灵A: [精灵B, ...]} |
评论:
- Sprite 必须包含
image和rect属性,Group.draw()依赖它们。 - 精灵组提供了批量更新和绘制,极大简化代码。
- 碰撞检测默认基于 Rect 的矩形碰撞,如需更精确的像素级碰撞,可结合
pygame.sprite.collide_mask或自定义碰撞函数。
9. 时间和动画
基于时间的运动
1 | dt = clock.tick(60) / 1000.0 # 转换为秒 |
计时器与自定义事件
1 | pygame.time.set_timer(pygame.USEREVENT + 1, 1000) # 每秒触发一次事件 |
动画帧切换
1 | class AnimatedSprite(pygame.sprite.Sprite): |
评论:
- 使用
dt确保运动速度与帧率解耦,避免高帧率下速度过快。 - 自定义事件非常适合实现定时器、刷怪等周期性逻辑。
- 动画切换不依赖帧率,而是基于绝对时间,可保证动画速度一致。
10. 高级主题
全屏模式与分辨率切换
1 | screen = pygame.display.set_mode((0,0), pygame.FULLSCREEN) # 当前桌面分辨率 |
双缓冲与页面翻转
pygame.display.flip() 交换前后缓冲区,实现平滑渲染。pygame.display.update(rect_list) 可更新部分区域优化性能。
自定义事件
事件类型从 pygame.USEREVENT 开始递增。
混合模式与特殊效果
blit 可以指定特殊标志(如 BLEND_ADD、BLEND_ALPHA_SDL2)实现颜色混合。
OpenGL 支持
Pygame 支持创建 OpenGL 上下文:1
pygame.display.set_mode((800,600), pygame.OPENGL | pygame.DOUBLEBUF)
之后可使用 PyOpenGL 进行 3D 渲染,但此时 Pygame 的 2D 绘图函数无法使用。
评论:
- 全屏模式下注意分辨率和硬件加速标志,不同平台支持有差异。
- 混合模式可以实现简单的光照、遮罩效果,但性能开销较大,建议仅用于小区域。
- 结合 OpenGL 可获得 3D 能力,但学习曲线陡峭,适合需要 3D 或复杂特效的项目。
11. 优化和调试
性能优化技巧
- 使用
convert()/convert_alpha()转换图像。 - 尽量减少每帧的 Surface 创建,复用已有 Surface。
- 对于静态背景,可将其绘制在一个背景 Surface 上,每帧直接 blit 这个背景,而不是重绘所有元素。
- 使用 Dirty Rect 技术:仅更新变化的区域(
pygame.display.update(rects))。 - 将频繁绘制且不变的图形缓存在临时 Surface 上。
调试工具
pygame.display.set_caption(str(clock.get_fps()))在窗口标题显示帧率。- 使用
pygame.image.save(screen, "screenshot.png")保存屏幕截图。 - 异常处理:主循环中使用
try...except捕获错误,防止窗口突然关闭。
常见陷阱
- 事件队列阻塞:长时间运算不处理事件会导致窗口无响应,可适时调用
pygame.event.pump()保持响应。 - 图像格式不支持:某些 JPEG 可能无法加载,使用 PNG 格式更可靠。
- 内存泄漏:精灵组中删除精灵后需从组中移除,否则仍被引用。
- 音频格式问题:确保音频文件格式被 SDL 支持,必要时使用 OGG 或 WAV。
12. 资源和进一步学习
- 官方文档:https://www.pygame.org/docs/ — 最权威的参考资料。
- 示例代码:Pygame 安装包中自带 examples 目录,运行
python -m pygame.examples.aliens可体验经典游戏。 - 社区与教程:
- Pygame 教程 (英文)
- Kidscancode 系列视频
- 中文社区:CSDN、简书等平台有大量实战文章。
结语
Pygame 以其简洁的 API 和强大的功能,成为无数开发者踏入游戏开发领域的第一站。本文作为速查手册,涵盖了大多数常用模块,但真正的精进还需在项目中不断实践。希望这份指南能成为你开发路上的得力助手,快速解决常见问题,让你专注于创造有趣的游戏体验。
Happy Coding! 🎮