Lazy loaded image
🎠0028 一人游戏公司启动:Claude Code CLI + DeepSeek V4 做个坦克大战吧!
字数 4566阅读时长 12 分钟
2026-5-7
2026-5-7
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. 系统架构
  1. 实现过程与关键决策
  1. 游戏玩法
  1. 运行与构建
  1. 未来扩展

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 需求分析

在动手编码之前,进行了三方面的需求确认:
  1. 技术栈:选择 Python + Pygame(浏览器零依赖 vs 桌面图形化,用户选择了桌面版)
  1. 项目位置:在 /Users/zionli/ 下新建独立目录(而非在 LiteLLM 配置目录中)
  1. 复杂度:精简版,聚焦经典玩法核心循环,不做关卡编辑器或双人模式

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() 检查三个条件:
  1. 边界检测new_col + TANK_SIZE > COLS 等,确保不出界
  1. Tile 碰撞:检查目标位置的 2×2 区域内的每个 tile 是否 solid(砖墙/钢墙/水域)
  1. 坦克碰撞:用 AABB 矩形碰撞检测其他坦克
只有三个条件同时满足,move_toward() 才执行移动,直接更新网格坐标并对齐像素位置。

3.4 碰撞系统

碰撞系统作为独立的协调器(CollisionSystem),持有 Game 实例的引用,在每帧统一处理 4 种碰撞:
碰撞检测顺序重要:先处理子弹与环境的碰撞(墙),再处理与实体的碰撞(坦克、基地),最后处理子弹间的抵消。这确保了视觉和逻辑的一致性。

3.5 敌人 AI 设计

敌人 AI 采用简化的状态机,每个 EnemyTank 独立决策:
具体参数:
  • 方向保持:默认向当前方向持续移动
  • 换向间隔:60-180 帧(1-3 秒)随机换向
  • 基地偏置:15%(初始)到 25%(后期)概率主动转向基地
  • 射击概率:每帧 3% + 波次修正,冷却时间随波次递减
AI 限制:为避免敌人全部聚集在一处,生成点分布在左上、右上和中间三个位置,轮流生成。

3.6 波次生成系统

生成逻辑:
  1. 3 个固定生成点(行 0:列 0、6、12)
  1. 生成前 30 帧闪烁红色提示
  1. 若生成点被占据,等待 30 帧后重试
  1. 当前波次敌人全部阵亡后,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 游戏规则

胜利条件:无明确胜利条件,游戏以无尽波次模式持续进行,直到失败。
失败条件(满足任一):
  1. 基地(屏幕底部的绿色旗帜)被敌方子弹击中
  1. 玩家生命耗尽(初始 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 添加类型,在 TileMapis_soliddraw 中添加处理
  • 新碰撞规则:在 CollisionSystem 中添加 check 方法,在 update() 中注册
  • 新关卡:在 levels.py 中添加二维数组,修改 LEVELS 列表

8. 游戏试玩

有点抽象,不过只要舍得Token,继续提要求,应该可以完善。
notion image
notion image