date
May 7, 2026
summary
Claude Code CLI + DeepSeek V4实现技术自由。用它“手搓”一个简版坦克大战游戏。
status
Published
tags
AI Agent
slug
claude-code-deepseek
icon
category
AI
type
Post
坦克大战(Battle City)游戏开发技术文档
目录
1. 项目概述
1.1 项目背景
经典 FC 游戏《坦克大战》(Battle City / 坦克1990)是无数玩家的童年回忆。本项目的目标是使用 Python + Pygame 从零实现一个精简版的坦克大战游戏,还原其核心玩法:玩家控制坦克,在砖墙构成的迷宫中与敌方坦克作战,保护己方基地。
1.2 技术选型
维度 | 选择 | 理由 |
语言 | Python 3.13 | 开发效率高,生态丰富 |
图形库 | Pygame 2.6.1 | 成熟的 2D 游戏框架,适合快速原型 |
项目位置 | /Users/zionli/tank-battle/ | 独立的项目目录 |
复杂度 | 精简版 | 核心玩法完整,去除过度复杂度 |
1.3 版本信息
- Python: 3.13.3
- Pygame: 2.6.1
- SDL: 2.28.4
- 平台: macOS (ARM64)
2. 前期设计
2.1 需求分析
在动手编码之前,进行了三方面的需求确认:
- 技术栈:选择 Python + Pygame(浏览器零依赖 vs 桌面图形化,用户选择了桌面版)
- 项目位置:在
/Users/zionli/下新建独立目录(而非在 LiteLLM 配置目录中)
- 复杂度:精简版,聚焦经典玩法核心循环,不做关卡编辑器或双人模式
2.2 核心玩法设计
精简版坦克大战的核心循环:
2.3 网格系统设计
游戏采用网格对齐的移动系统(grid-aligned movement),这是经典坦克大战的标志性设计:
参数 | 值 | 说明 |
Tile 尺寸 | 40×40 px | 最小地图单位 |
游戏网格 | 15×13 | 宽×高,共 195 个 tile |
坦克尺寸 | 2×2 tiles (80×80 px) | 坦克占据 4 个 tile |
游戏区 | 600×520 px | 纯游戏区域 |
侧边栏 | 200 px | 显示分数、生命等状态 |
窗口尺寸 | 800×520 px | 游戏区 + 侧边栏 |
网格对齐意味着坦克每次移动恰好一个 tile 步长(2 个网格单位),方向切换时自动对齐到最近的网格位置。这避免了像素级碰撞的模糊问题,使碰撞检测简洁可靠。
2.4 地图 Tile 类型
关卡数据定义为 13 行 × 15 列的二维数组,每格对应一个 tile 类型。
2.5 目录结构规划
3. 系统架构
3.1 整体架构图
3.2 类层次设计
3.3 Tank 基类设计
Tank 基类是游戏中最核心的类,封装了所有坦克共有的行为和属性:
移动逻辑
移动采用先检测、后执行模式。
can_move() 检查三个条件:- 边界检测:
new_col + TANK_SIZE > COLS等,确保不出界
- Tile 碰撞:检查目标位置的 2×2 区域内的每个 tile 是否 solid(砖墙/钢墙/水域)
- 坦克碰撞:用 AABB 矩形碰撞检测其他坦克
只有三个条件同时满足,
move_toward() 才执行移动,直接更新网格坐标并对齐像素位置。3.4 碰撞系统
碰撞系统作为独立的协调器(CollisionSystem),持有 Game 实例的引用,在每帧统一处理 4 种碰撞:
碰撞检测顺序重要:先处理子弹与环境的碰撞(墙),再处理与实体的碰撞(坦克、基地),最后处理子弹间的抵消。这确保了视觉和逻辑的一致性。
3.5 敌人 AI 设计
敌人 AI 采用简化的状态机,每个 EnemyTank 独立决策:
具体参数:
- 方向保持:默认向当前方向持续移动
- 换向间隔:60-180 帧(1-3 秒)随机换向
- 基地偏置:15%(初始)到 25%(后期)概率主动转向基地
- 射击概率:每帧 3% + 波次修正,冷却时间随波次递减
AI 限制:为避免敌人全部聚集在一处,生成点分布在左上、右上和中间三个位置,轮流生成。
3.6 波次生成系统
生成逻辑:
- 3 个固定生成点(行 0:列 0、6、12)
- 生成前 30 帧闪烁红色提示
- 若生成点被占据,等待 30 帧后重试
- 当前波次敌人全部阵亡后,60 帧延迟进入下一波
4. 实现过程与关键决策
4.1 开发顺序
项目按照依赖关系分为 6 个阶段实现,共 13 个步骤:
阶段 | 步骤 | 内容 | 依赖 |
Phase 1 | Step 1 | 项目骨架:目录、常量、main.py | 无 |
Phase 2 | Step 2 | 地图系统:TileMap、关卡数据 | Phase 1 |
Phase 3 | Step 3-4 | Tank 基类 + PlayerTank | Phase 2 |
Phase 4 | Step 5-7 | 子弹、碰撞、Enemy AI、生成系统 | Phase 3 |
Phase 5 | Step 8-10 | 基地、碰撞完善、Game 主循环 | Phase 4 |
Phase 6 | Step 11-13 | UI、特效、打磨 | Phase 5 |
4.2 关键实现决策
决策 1:网格对齐 vs 像素自由移动
采用网格对齐(grid-aligned),而非像素自由移动。
- 优点:碰撞检测简单可靠,坦克不会卡在墙缝里,行为可预测
- 代价:移动不够顺滑,但这对坦克大战不是问题(原版也是网格移动)
实现方式:
move_toward() 一步移动一整格(2 tile),snap_to_grid() 将像素坐标对齐到网格。坦克的状态用 tile_col/tile_row 表示,渲染时用 pixel_x/pixel_y。决策 2:碰撞检测采用先检测后执行
can_move() 在移动前预判所有碰撞条件,而不是移动后再解决穿透。避免了坦克卡入墙体或相互重叠的问题。决策 3:子弹坐标系重构
初始实现中,子弹的坐标系统与坦克的 tile 坐标混淆,导致子弹从坦克边缘而非中心射出。修复方案:
- Bullet 改用
cx/cy(center x/y)表示中心点
rect.center跟随cx/cy更新
- 坦克发射子弹时,从坦克中心加上方向偏移计算子弹初始位置
决策 4:模块拆分策略
将碰撞检测、生成系统独立为
systems/ 目录,而非放在 Game 类中:- CollisionSystem 负责全部碰撞逻辑(约 100 行)
- Spawner 负责生成与波次(约 110 行)
- Game 类负责编排而非实现
这使得 Game 主类的
update() 方法成为清晰的编排管线:决策 5:基地区域与关卡数据调整
实现过程中发现基地(2×2 tiles)放到底行(row 12)会被游戏区域截断 40px。修复:
- 将
BASE_TILE_Y从 12 改为 11(占据 rows 11-12)
- 调整关卡数据中基地周围的砖块布局
- 玩家出生点从 (4, 12) 改为 (4, 10),避免与基地重叠
4.3 途中修复的问题
问题 | 症状 | 修复 |
子弹偏移 | 子弹从坦克边缘而非中心飞出 | Bullet 改用 cx/cy 中心坐标系统 |
基地截断 | 基地底部 40px 被裁剪 | BASE_TILE_Y 从 12 改为 11 |
生成点重复检测 | Spawner 中同一循环写了两遍 | 合并为一次检测,改用距离判断 |
AI 全局列表修改 | random.shuffle 修改模块级 ALL_DIRS | 改为 list(ALL_DIRS) 复制后再 shuffle |
循环导入 | collision.py 底部延迟导入 Explosion | 移至文件顶部,确认无循环依赖 |
4.4 测试方法
每个阶段完成后进行自动化冒烟测试:
5. 游戏玩法
5.1 运行方式
5.2 操作说明
按键 | 功能 |
↑ ↓ ← → | 控制坦克移动 |
空格键 | 发射子弹 |
Enter | 开始游戏 / 重新开始 |
5.3 游戏规则
胜利条件:无明确胜利条件,游戏以无尽波次模式持续进行,直到失败。
失败条件(满足任一):
- 基地(屏幕底部的绿色旗帜)被敌方子弹击中
- 玩家生命耗尽(初始 3 条命)
计分规则:
- 每消灭一个敌人坦克 +100 分
- 显示在右侧面板的"分数"栏
5.4 游戏机制
波次系统:
- 每波敌人数量 = 4 + 波次数(第 1 波 5 个,第 2 波 6 个...)
- 敌人速度随波次递增(每次 +0.15 px/帧)
- 敌人射击频率和转向倾向随波次提高
砖墙机制:
- 砖墙阻挡坦克通行,但可被子弹摧毁
- 摧毁后该格变为空地,坦克可通行
基地保护:
- 基地周围初始有砖墙保护
- 玩家可以主动在基地周围移动阻挡敌人
- 一旦基地上方的砖墙被摧毁,基地直接暴露在敌人火力下
重生机制:
- 玩家被击中后,若还有剩余生命,在出生点重生
- 重生后有约 0.5 秒的无敌时间(闪烁效果)
5.5 关卡设计
第一关:对称布局,砖墙分布在左右两侧,中部有条状掩体,基地位于底部中央。
第二关:棋盘式布局,砖墙交错排列,掩体分布更分散。
5.6 界面说明
屏幕分为左右两部分:
- 左侧(600×520px):游戏区域,显示地图、坦克、子弹、爆炸特效
- 右侧(200×520px):信息面板
- "坦克大战" 标题
- 分数
- 生命(♥ 符号)
- 波次
- 剩余敌人数量
- 操作提示
6. 运行与构建
6.1 环境要求
- Python 3.10+
- Pygame 2.0+
6.2 安装步骤
6.3 项目文件清单
文件 | 行数 | 职责 |
main.py | 32 | 入口,Pygame 初始化,主循环 |
game.py | 199 | 游戏主类,状态管理,update/render 管线 |
constants.py | 98 | 所有常量和配置参数 |
entities/tank.py | 128 | Tank 基类(移动、碰撞检测、绘制) |
entities/player.py | 96 | 玩家坦克(键盘控制、生命、重生) |
entities/enemy.py | 105 | 敌方坦克(AI 状态机) |
entities/bullet.py | 42 | 子弹(飞行、出界检测) |
entities/base.py | 42 | 基地(绘制、被摧毁检测) |
map/tilemap.py | 81 | 地图(网格渲染、砖块管理) |
map/levels.py | 41 | 关卡数据(二维数组) |
systems/collision.py | 99 | 碰撞系统(4 种碰撞类型) |
systems/spawner.py | 109 | 生成与波次系统 |
ui/hud.py | 66 | 侧边栏信息显示 |
ui/menu.py | 82 | 菜单与 Game Over 界面 |
effects/explosion.py | 44 | 爆炸特效(帧动画) |
总计约 1300 行 Python 代码。
7. 未来扩展
7.1 短期可加功能
- 钢墙(Steel Wall):已在 tile 类型中预留,需要赋予其不可摧毁属性,增加地图策略性
- 道具系统:经典道具如加速、散弹、护盾、坦克升级等
- 音效:使用 Pygame mixer 添加射击、爆炸、背景音乐
7.2 中期扩展
- 关卡编辑器:可视化编辑关卡数据,即时保存加载
- 双人模式:第二个玩家使用 WASD + Tab 或手柄控制
- 更多敌人类型:高速型、装甲型(需多次命中)、侦查型(主动绕后)
7.3 架构可扩展性
当前架构对扩展的支持:
- 新实体:在
entities/下新建类,继承 Sprite,接入 collision 系统
- 新 tile 类型:在
constants.py添加类型,在TileMap的is_solid和draw中添加处理
- 新碰撞规则:在
CollisionSystem中添加 check 方法,在update()中注册
- 新关卡:在
levels.py中添加二维数组,修改LEVELS列表
8. 游戏试玩
有点抽象,不过只要舍得Token,继续提要求,应该可以完善。


- 作者:zion
- 链接:https://gendlee.github.io/claude-code-deepseek
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。






