Initial commit

This commit is contained in:
wfz
2026-07-26 14:41:36 +08:00
commit f741a0c8e8
90 changed files with 10774 additions and 0 deletions

256
docs/migration-plan-zh.md Normal file
View 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 中的校正逻辑引用了武器状态,需验证精简版是否正常工作