用强化学习训练 AI 打砖块:我的项目设计思路
之前写了个 HTML5 的打砖块游戏(breakout.xingyao.info),最近在给它加 RL(强化学习)训练系统——让 AI 从零学会玩这个游戏。记录一下设计思路。
为什么选打砖块
打砖块是强化学习的经典实验场景,DeepMind 2013 年那篇开山之作就是用 DQN 打 Atari Breakout。不过原始的 Atari 实验用的是像素输入,我这个版本不一样:游戏是自己写的,所有内部状态都可以直接暴露给 AI,能做更多有趣的实验。
架构:浏览器游戏 + Python 训练
整体架构分两端:
浏览器(JS 游戏引擎) Python(RL 训练)
Game.js ←WebSocket→ ws_env.py
stepForAI() Gymnasium Env
getState() DQN / PPO / GRPO Agent
游戏跑在浏览器里,通过 WebSocket 暴露一个 Gym 风格的接口(reset() / step(action))。Python 端连上来后,每一步发一个动作,收到下一帧的状态和奖励。中间有个轻量的 WebSocket 中继服务器做转发。
为什么不把游戏逻辑搬到 Python? 因为游戏本身已经有完整的渲染、音效、50 个关卡——保持它在浏览器里运行意味着训练过程可以实时可视化,也能随时切换到人类手动玩。训练时关掉渲染,速度也够用。
观测空间:233 维向量
没有用图像输入,而是把游戏状态拍平成一个 233 维的 float32 向量:
| 区段 | 内容 | 维度 |
|---|---|---|
| 挡板 | x 坐标, 宽度 | 2 |
| 球 | x, y, vx, vy, 是否已发射 | 5 |
| 砖块网格 | 14×16 的 HP 值矩阵 | 224 |
| 元信息 | 剩余生命比例, 剩余砖块比例 | 2 |
所有值归一化到 [0, 1]。用固定 14×16 网格而不是变长砖块列表,是为了保持输入维度一致——不同关卡的砖块布局不同,但网格大小相同,空位填 0。
三个 Agent:DQN、PPO、GRPO
选了三个算法做对比实验,各有特点。
DQN:经典离散控制
动作空间 4 个离散值:左移、不动、右移、发球。
网络结构就是一个简单的 MLP(233→256→256→128→4),输出四个动作的 Q 值。用 ε-greedy 探索,经验回放缓冲区 10 万条,每 1000 步同步一次 target network。
DQN 的好处是稳定、好调试,坏处是只能做离散控制——挡板只有「全速左/不动/全速右」三个选项,没有中间态。
PPO:连续控制
PPO 用的是连续动作空间,输出一个 [-1, 1] 的浮点数表示挡板移动方向和力度。这比 DQN 的三档控制精细得多。
用了 Actor-Critic 架构,共享底层特征提取,Actor 输出 tanh 压缩的高斯分布,Critic 估算状态价值。GAE(λ=0.95)做优势估计,clip ratio 0.2。
GRPO:无 Critic 的策略优化
这是最有意思的一个。GRPO(Group Relative Policy Optimization)来自 DeepSeek-R1 的思路——不要 Critic,而是对同一个起始状态采样 G 条完整轨迹,用组内均值和标准差来归一化优势。
为什么在打砖块上试 GRPO?几个原因:
- 打砖块的单局不长(200-2000 步),采样 G 条完整轨迹是可行的
- 没有 Critic 意味着更少的参数和更简单的代码
- 组内相对基线天然适应奖励尺度的变化,不需要额外做 reward normalization
- 训练早期 agent 很少打到砖块(稀疏奖励),GRPO 在这种情况下理论上比需要精确 value estimation 的 PPO 更鲁棒
奖励设计
基础奖励来自游戏本身:
| 事件 | 奖励 |
|---|---|
| 击碎砖块 | +1 |
| 通关 | +50 |
| 丢球 | -5 |
此外提供了可选的 reward shaping(默认关闭,用 --reward-shaping 开启):
- 追球奖励:挡板越接近球的 X 坐标,给 +0.01 × (1 - |距离|)。鼓励 agent 学会移到球下方
- 球向上奖励:球向上运动时给微小正奖励(+0.001),抑制「让球掉下去」
- 超时惩罚:连续 600 步没打到砖块就截断,给 -1。防止 agent 学会无限弹跳但不打砖块
Reward shaping 默认关闭是为了对比实验的纯净性——开了 shaping 训练更快,但不代表算法本身更好。
训练流程
# 启动 WebSocket 中继
python ws_server.py
# 开浏览器打开游戏(连接 WS)
npm run dev
# 开始训练(以 DQN 为例)
python train.py --agent dqn --episodes 5000 --headless
# 评估
python evaluate.py --agent dqn --checkpoint checkpoints/dqn_best.pt
# 看 AI 打游戏
python play.py --agent dqn --checkpoint checkpoints/dqn_best.pt
--headless 会关掉浏览器端的渲染,配合 frame skip=4(每个决策重复 4 帧),训练速度提升不少。日志同时写 TensorBoard 和 W&B。
目前的状态和下一步
游戏本体(Phase 1)已经完成:50 关、三种道具(多球/分裂/加命)、多球系统、程序化音效和 BGM、移动端适配。
RL 训练(Phase 2)的代码框架已经搭好,正在调参和跑实验。接下来想做的:
- 三个算法的学习曲线对比
- 开/关 reward shaping 的效果对比
- 看 agent 能打到第几关
- 可能后续加 CNN + 图像输入的版本做更公平的对比
项目地址:breakout.xingyao.info,可以先去玩几把再说。