Initial commit
This commit is contained in:
256
docs/migration-plan-zh.md
Normal file
256
docs/migration-plan-zh.md
Normal file
@@ -0,0 +1,256 @@
|
||||
# ZP1 最小化迁移计划
|
||||
|
||||
## 目标
|
||||
将 zp1 重写为 zp2,仅保留:房间管理、地图加载、玩家移动、前端必要显示。技术栈不变(Java + Vite/Three.js),保留 ECS 架构和客户端预测。
|
||||
|
||||
## 范围
|
||||
- **保留**:房间系统、地图加载/渲染、玩家移动(WASD)、客户端预测、WebSocket 通信
|
||||
- **移除**:僵尸、武器/子弹、炮塔、火焰区域、掉落物、爆炸/特效、HUD、设置界面、地图编辑器、模板系统、对象池
|
||||
|
||||
---
|
||||
|
||||
## 阶段一:后端骨架
|
||||
|
||||
### 1.1 项目结构
|
||||
```
|
||||
zp2/backend/
|
||||
├── pom.xml
|
||||
└── src/main/java/com/zombie/game/
|
||||
├── GameServerMain.java # 入口,仅启动 WebSocket 服务器
|
||||
├── model/
|
||||
│ ├── Constants.java # 精简为:GRID_SIZE, TICK_RATE, PLAYER_SIZE, PLAYER_SPEED, MSG_*
|
||||
│ ├── Room.java # 保持原样
|
||||
│ ├── PlayerInfo.java # 保持原样
|
||||
│ ├── GameMap.java # 精简:移除流向场,仅保留 isWall/isWalkable
|
||||
│ ├── MapData.java # 保持,用于地图反序列化
|
||||
│ └── StaticWall.java # 仅保留静态墙
|
||||
├── server/
|
||||
│ ├── GameWebSocketServer.java # 精简:房间操作 + 玩家输入 + 状态广播
|
||||
│ ├── RoomManager.java # 保持原样
|
||||
│ ├── GameService.java # 精简:仅注册 PlayerInputSystem + StateSyncSystem
|
||||
│ ├── GameLoop.java # 保持原样(30 TPS)
|
||||
│ ├── MessageUtils.java # 保持原样
|
||||
│ └── MapStorage.java # 保留,用于加载地图文件
|
||||
├── ecs/
|
||||
│ ├── ECSWorld.java # 精简:仅管理 players,移除僵尸/子弹/掉落物/炮塔/火焰区域
|
||||
│ ├── System.java # 保持接口
|
||||
│ └── components/
|
||||
│ ├── Position.java # 保持
|
||||
│ ├── PlayerInput.java # 精简:移除手雷相关字段
|
||||
│ ├── Health.java # 精简
|
||||
│ ├── Collision.java # 保持
|
||||
│ └── RenderInfo.java # 精简
|
||||
└── systems/
|
||||
├── PlayerInputSystem.java # 保持:移动 + 碰撞 + 朝向
|
||||
└── StateSyncSystem.java # 精简:仅广播玩家位置
|
||||
```
|
||||
|
||||
### 1.2 关键变更
|
||||
|
||||
**Constants.java**
|
||||
- 保留:`GRID_SIZE=32`, `TICK_RATE=30`, `PLAYER_SIZE=0.8f`, `PLAYER_SPEED=5.0f`, `MSG_*` 消息类型常量
|
||||
- 移除:`ZOMBIE_SIZE`, `LOOT_*`, 武器常量
|
||||
|
||||
**GameMap.java**
|
||||
- 保留:`loadFromJson()`, `isWall()`, `isWalkable()`, `getCells()`, `getSpawnPoints()`
|
||||
- 移除:整个 `FlowField`,`updateFlowField()`, `getFlowDirection()`, `addNutWall()`, 坚果墙逻辑
|
||||
- 仅保留 `StaticWall`(移除 `NutWall`, `TurretWall`)
|
||||
|
||||
**ECSWorld.java**
|
||||
- 保留:`entities`, `players`, `playerIdToEntity`, `map`, `systems`, `lock`
|
||||
- 移除:`zombies`, `playerBullets`, `zombieBullets`, `loots`, `fireZones`, `turrets`, `wallEntities`
|
||||
- 移除:所有对象池
|
||||
- 移除:`createZombieEntity()`, `createBulletEntity()`, `createGrenadeEntity()`, `createMolotovEntity()`, `createLootEntity()`, `createFireZoneEntity()`, `createTurretEntity()`
|
||||
- 保留:`createPlayerEntity()`(精简版,无 WeaponState/RespawnState)
|
||||
- 保留:`update(dt)` — 清理临时数据,遍历系统执行
|
||||
|
||||
**GameService.java**
|
||||
- `startGame()`:仅注册 `PlayerInputSystem` 和 `StateSyncSystem`(移除其他10个系统)
|
||||
- 保留:`processPlayerInput()`, `stopGame()`
|
||||
|
||||
**PlayerInputSystem.java**
|
||||
- 保留:移动(dx/dy * speed)、逐轴墙壁碰撞、朝向计算
|
||||
- 移除:武器射击逻辑(如有)
|
||||
|
||||
**StateSyncSystem.java**
|
||||
- 精简广播为:`{players: [{id, x, y, angle, health}], gameTime}`
|
||||
- 移除:zombies, bullets, zombieBullets, loots, explosions, removedBullets, waveNumber, score
|
||||
|
||||
**Room.java / RoomManager.java / GameLoop.java / MessageUtils.java**
|
||||
- 保持原样(或微调清理)
|
||||
|
||||
**GameWebSocketServer.java**
|
||||
- 保留:`onMessage()` 分发、房间 CRUD 处理、`handlePlayerInput()`、`broadcastGameState()`
|
||||
- 可选移除:房间列表广播定时器(或保留用于大厅刷新)
|
||||
|
||||
### 1.3 地图数据
|
||||
- 保留 `maps/d540209a.json` 格式(walls + playerSpawns + zombieSpawns)
|
||||
- 复制一份到 `zp2/maps/`
|
||||
|
||||
---
|
||||
|
||||
## 阶段二:前端骨架
|
||||
|
||||
### 2.1 项目结构
|
||||
```
|
||||
zp2/frontend/
|
||||
├── package.json # 同样依赖(three, vite)
|
||||
├── vite.config.js # 同样代理配置
|
||||
├── index.html # 同样最小化外壳
|
||||
└── src/
|
||||
├── main.js # 精简:大厅 → 游戏切换
|
||||
├── style.css # 仅大厅 + 房间 + 画布样式
|
||||
├── game/
|
||||
│ ├── engine.js # 精简:仅玩家,无僵尸/子弹/战斗
|
||||
│ └── scene.js # 精简:仅地图 + 玩家,无特效
|
||||
├── network/
|
||||
│ └── client.js # 保持原样
|
||||
├── ui/
|
||||
│ └── lobby.js # 保持原样(房间管理 UI)
|
||||
└── utils/
|
||||
├── constants.js # 精简:仅地图 + 玩家 + 网络常量
|
||||
├── grid.js # 精简:仅 Grid 类 + generateDefaultMap
|
||||
└── input.js # 精简:仅移动 + 瞄准
|
||||
```
|
||||
|
||||
### 2.2 关键变更
|
||||
|
||||
**constants.js**
|
||||
- 保留:`GRID_SIZE`, `CELL_SIZE`, `PLAYER_SIZE`, `TICK_RATE`, `TICK_INTERVAL`
|
||||
- 保留:`PLAYER_CONFIG`(MAX_HEALTH, SPEED)
|
||||
- 保留:`MSG_TYPE`(所有房间 + 游戏消息类型)
|
||||
- 移除:`WEAPONS`, `WEAPON_CONFIG`, `ZOMBIE_CONFIG`, `ZOMBIE_SIZE`
|
||||
|
||||
**grid.js**
|
||||
- 保留:`Grid` 类的 `parseMap()`, `isWall()`, `worldToGrid()`, `gridToWorld()`, `isWalkable()`
|
||||
- 保留:`generateDefaultMap()`(备用默认地图)
|
||||
- 移除:`findPath()`, `getSpawnPoints()`, `isSpawnPoint()`
|
||||
|
||||
**input.js**
|
||||
- 保留:`attach()`, `detach()`, `getMovement()`, `buildInputState()`(仅移动 + 瞄准)
|
||||
- 移除:`getSelectedWeapon()`, 武器快捷键绑定
|
||||
- 精简 `buildInputState()` 返回 `{seq, dx, dy, aimX, aimY}`(无 firing, weaponIndex, grenade 字段)
|
||||
|
||||
**engine.js(约666→250行)**
|
||||
- 保留:`connect()`, `start()`, `stop()`, `_loop()`, `_tick()`
|
||||
- 保留:`_applyLocalPrediction()` — 带碰撞的移动预测
|
||||
- 保留:`_reconcileLocalPlayer()` — 服务器校正
|
||||
- 保留:`_initPlayers()`, `_addPlayer()`, `_removePlayer()`
|
||||
- 精简 `_processServerState()`:仅同步玩家位置,移除所有僵尸/子弹/掉落物/炮塔/特效处理
|
||||
- 移除:`_handleGrenadeCharge()`, `_checkBulletHit()`, 武器状态, 手雷状态
|
||||
- 移除:`zombies`, `bullets`, `zombieBullets`, `loots`, `turrets` 映射表
|
||||
|
||||
**scene.js(约1331→250行)**
|
||||
- 保留:构造函数(场景、相机、渲染器、灯光、窗口自适应)
|
||||
- 保留:`buildMap(mapData)` — 地板 + 墙壁
|
||||
- 保留:`createPlayerModel()`, `addPlayer()`, `removePlayer()`, `updatePlayer()`
|
||||
- 保留:`updateCamera()`, `getMouseGroundPos()`, `render()`
|
||||
- 移除:所有僵尸渲染(约180行)
|
||||
- 移除:所有子弹渲染(约230行)
|
||||
- 移除:所有特效(约250行)
|
||||
- 移除:炮塔、掉落物、坚果墙、手雷目标指示器(约215行)
|
||||
- 移除:`updateEffects()`(或简化为空)
|
||||
|
||||
**lobby.js** — 保持原样
|
||||
|
||||
**main.js**
|
||||
- 保留:App 类、大厅绑定、游戏开始切换
|
||||
- 移除:HUD 初始化、设置界面初始化
|
||||
- 移除:`_updateHUD()` 调用
|
||||
|
||||
**style.css**
|
||||
- 保留:大厅样式、房间样式、画布容器样式
|
||||
- 移除:HUD 样式、武器面板、手雷充能、击杀信息、设置弹窗
|
||||
|
||||
---
|
||||
|
||||
## 阶段三:清理与验证
|
||||
|
||||
### 3.1 消息协议验证
|
||||
确保以下消息端到端正常工作:
|
||||
- `CREATE_ROOM` / `JOIN_ROOM` / `LEAVE_ROOM` / `READY` / `START_GAME`
|
||||
- `ROOM_LIST` / `ROOM_STATE` / `GAME_STARTED` / `ERROR`
|
||||
- `PLAYER_INPUT`(仅移动:dx, dy, aimX, aimY, seq)
|
||||
- `GAME_STATE`(仅玩家数据)
|
||||
|
||||
### 3.2 测试流程
|
||||
1. 启动后端:`mvn package && java -jar target/*.jar`
|
||||
2. 启动前端:`npm run dev`
|
||||
3. 打开两个浏览器标签页
|
||||
4. 标签页1:创建房间 → 标签页2:加入房间 → 标签页1:开始游戏
|
||||
5. 两个玩家应能在 32x32 地图上互相看到对方移动
|
||||
6. WASD 移动响应流畅(客户端预测)
|
||||
7. 玩家与墙壁碰撞正确
|
||||
|
||||
---
|
||||
|
||||
## 待创建文件清单(共36个)
|
||||
|
||||
### 后端(23个文件)
|
||||
| 序号 | 文件 | 来源 |
|
||||
|------|------|------|
|
||||
| 1 | `backend/pom.xml` | 从 zp1 复制 |
|
||||
| 2 | `GameServerMain.java` | 精简版 |
|
||||
| 3 | `model/Constants.java` | 精简版 |
|
||||
| 4 | `model/Room.java` | 基本保持 |
|
||||
| 5 | `model/PlayerInfo.java` | 基本保持 |
|
||||
| 6 | `model/GameMap.java` | 精简版(无流向场) |
|
||||
| 7 | `model/MapData.java` | 基本保持 |
|
||||
| 8 | `model/StaticWall.java` | 基本保持 |
|
||||
| 9 | `ecs/System.java` | 保持 |
|
||||
| 10 | `ecs/ECSWorld.java` | 精简版 |
|
||||
| 11 | `ecs/components/Position.java` | 保持 |
|
||||
| 12 | `ecs/components/PlayerInput.java` | 精简版 |
|
||||
| 13 | `ecs/components/Health.java` | 精简版 |
|
||||
| 14 | `ecs/components/Collision.java` | 保持 |
|
||||
| 15 | `ecs/components/RenderInfo.java` | 精简版 |
|
||||
| 16 | `systems/PlayerInputSystem.java` | 基本保持 |
|
||||
| 17 | `systems/StateSyncSystem.java` | 精简版 |
|
||||
| 18 | `server/GameWebSocketServer.java` | 精简版 |
|
||||
| 19 | `server/RoomManager.java` | 基本保持 |
|
||||
| 20 | `server/GameService.java` | 精简版 |
|
||||
| 21 | `server/GameLoop.java` | 基本保持 |
|
||||
| 22 | `server/MessageUtils.java` | 保持 |
|
||||
| 23 | `server/MapStorage.java` | 基本保持 |
|
||||
|
||||
### 前端(12个文件)
|
||||
| 序号 | 文件 | 来源 |
|
||||
|------|------|------|
|
||||
| 24 | `frontend/package.json` | 保持 |
|
||||
| 25 | `frontend/vite.config.js` | 保持 |
|
||||
| 26 | `frontend/index.html` | 保持 |
|
||||
| 27 | `frontend/src/main.js` | 精简版 |
|
||||
| 28 | `frontend/src/style.css` | 精简版 |
|
||||
| 29 | `frontend/src/game/engine.js` | 精简版 |
|
||||
| 30 | `frontend/src/game/scene.js` | 精简版 |
|
||||
| 31 | `frontend/src/network/client.js` | 基本保持 |
|
||||
| 32 | `frontend/src/ui/lobby.js` | 保持 |
|
||||
| 33 | `frontend/src/utils/constants.js` | 精简版 |
|
||||
| 34 | `frontend/src/utils/grid.js` | 精简版 |
|
||||
| 35 | `frontend/src/utils/input.js` | 精简版 |
|
||||
|
||||
### 数据文件(1个)
|
||||
| 序号 | 文件 | 来源 |
|
||||
|------|------|------|
|
||||
| 36 | `maps/d540209a.json` | 从 zp1 复制 |
|
||||
|
||||
---
|
||||
|
||||
## 关键设计决策
|
||||
|
||||
| 决策 | 选择 | 原因 |
|
||||
|------|------|------|
|
||||
| 技术栈 | Java 17 + Vite + Three.js | 与 zp1 一致,迁移成本最低 |
|
||||
| ECS 架构 | 保留 | 结构清晰,便于后续扩展 |
|
||||
| 客户端预测 | 保留 | 移动手感更好,代码量不大 |
|
||||
| 流向场寻路 | 移除 | 仅僵尸 AI 需要 |
|
||||
| 地图格式 | 保持 JSON | 兼容现有地图文件 |
|
||||
| WebSocket 协议 | 保持相同消息类型 | 前后端保持同步 |
|
||||
| 大厅 UI | 保持原样 | 房间管理是核心功能 |
|
||||
| HUD/设置 | 移除 | 不在本次范围内 |
|
||||
| 地图编辑器 | 移除 | 不在本次范围内 |
|
||||
|
||||
## 风险点
|
||||
- **StateSyncSystem**:精简时需小心处理消息格式,确保前端能正确解析
|
||||
- **ECSWorld**:移除组件映射表后,需检查所有引用这些组件的系统
|
||||
- **客户端预测**:engine.js 中的校正逻辑引用了武器状态,需验证精简版是否正常工作
|
||||
Reference in New Issue
Block a user