Day 088 - 图解 Pygame 核心概念
1. 游戏循环流程图
flowchart TD
A[游戏启动] --> B[pygame.init]
B --> C[创建窗口]
C --> D[游戏主循环开始]
D --> E[事件处理]
E --> E1{有事件?}
E1 -->|是| E2[处理事件]
E2 --> F[游戏更新]
E1 -->|否| F
F --> G[画面渲染]
G --> H[clock.tick 控制帧率]
H --> I{游戏结束?}
I -->|否| D
I -->|是| J[pygame.quit]
J --> K[程序退出]
flowchart TD
A[游戏启动] --> B[pygame.init]
B --> C[创建窗口]
C --> D[游戏主循环开始]
D --> E[事件处理]
E --> E1{有事件?}
E1 -->|是| E2[处理事件]
E2 --> F[游戏更新]
E1 -->|否| F
F --> G[画面渲染]
G --> H[clock.tick 控制帧率]
H --> I{游戏结束?}
I -->|否| D
I -->|是| J[pygame.quit]
J --> K[程序退出]
2. Pygame 坐标系
X 轴 (向右增大)
──────────────────────→
│
│ (0,0) ← 左上角原点
│ ┌──────────┐
│ │ rect │ (x, y)
│ │ ┌────┐ │
│ │ │● │ │ ← rect.center
│ │ └────┘ │
│ └──────────┘
│
│ Y 轴 (向下增大)
↓
3. 精灵系统架构
classDiagram
class Sprite {
+Surface image
+Rect rect
+update()
}
class Player {
+int speed
+update()
+shoot()
}
class Enemy {
+int speed
+update()
}
class Group {
+add(Sprite)
+remove(Sprite)
+update()
+draw(Surface)
}
Sprite <|-- Player
Sprite <|-- Enemy
Group o-- Sprite : contains
classDiagram
class Sprite {
+Surface image
+Rect rect
+update()
}
class Player {
+int speed
+update()
+shoot()
}
class Enemy {
+int speed
+update()
}
class Group {
+add(Sprite)
+remove(Sprite)
+update()
+draw(Surface)
}
Sprite <|-- Player
Sprite <|-- Enemy
Group o-- Sprite : contains
4. 碰撞检测类型
1. 矩形碰撞 (AABB)
┌────────┐
│ A │
│ ┌──┼────┐
└─────┼──┘ │
│ B │
└───────┘
两矩形有重叠区域 = 碰撞
2. 圆形碰撞
╭──╮
╭─┤A ├─╮
│ ╰──╯ │
│ ╭──╮ │
╰─┤B ├──╯
╰──╯
圆心距 < r1 + r2 = 碰撞
3. 像素级碰撞
需要逐像素检测,最精确但最慢
pygame.mask 模块提供此功能
5. 双缓冲渲染原理
┌─────────────────────────────────────────────┐
│ 显示器 │
│ ┌─────────────────────────────────────┐ │
│ │ 当前显示的画面(前缓冲区) │ │
│ │ 用户正在看到的内容 │ │
│ └─────────────────────────────────────┘ │
│ ↑ │
│ display.flip() │
│ ↓ │
│ ┌─────────────────────────────────────┐ │
│ │ 正在绘制的画面(后缓冲区) │ │
│ │ fill() + draw() 操作都在这里 │ │
│ └─────────────────────────────────────┘ │
│ 后台准备 │
└─────────────────────────────────────────────┘
为什么要用双缓冲? - 避免画面撕裂:如果直接在显示缓冲区绘制,用户可能看到"画了一半"的画面 - flip() 是原子操作:一次性替换整个画面,视觉上瞬间切换