创建新工程

This commit is contained in:
moyin
2025-12-05 19:00:14 +08:00
commit ff4fa5fffd
227 changed files with 32804 additions and 0 deletions

View File

@@ -0,0 +1,711 @@
# 设计文档
## 概述
本项目是一款基于 Godot 4.x 引擎开发的 2D 多人在线 AI 小镇游戏,采用客户端-服务器架构。游戏的核心特性是持久化的多人世界,玩家创建的角色在玩家离线时会作为 NPC 继续存在于游戏世界中。游戏优先支持网页端HTML5 导出),并预留移动端适配接口。
### 技术栈
- **游戏引擎**: Godot 4.x
- **编程语言**: GDScript
- **网络协议**: WebSocket (用于实时通信)
- **数据格式**: JSON (用于数据序列化)
- **导出平台**: HTML5 (Web), 预留 Android/iOS 支持
- **后端服务**: 简单的 WebSocket 服务器 (可使用 Node.js + ws 或 Python + websockets)
## 架构
### 整体架构
游戏采用客户端-服务器架构,分为以下主要层次:
```
┌─────────────────────────────────────────┐
│ 客户端 (Godot HTML5) │
├─────────────────────────────────────────┤
│ 表现层 (UI/Rendering) │
│ ├─ 场景渲染 │
│ ├─ UI 界面 │
│ └─ 动画系统 │
├─────────────────────────────────────────┤
│ 游戏逻辑层 │
│ ├─ 角色控制器 │
│ ├─ 对话系统 │
│ ├─ 输入处理 │
│ └─ 状态管理 │
├─────────────────────────────────────────┤
│ 网络层 │
│ ├─ WebSocket 客户端 │
│ ├─ 消息序列化/反序列化 │
│ └─ 状态同步 │
└─────────────────────────────────────────┘
↕ WebSocket
┌─────────────────────────────────────────┐
│ 服务器 (WebSocket Server) │
├─────────────────────────────────────────┤
│ 连接管理 │
│ ├─ 客户端连接池 │
│ ├─ 身份验证 │
│ └─ 心跳检测 │
├─────────────────────────────────────────┤
│ 游戏状态管理 │
│ ├─ 世界状态 │
│ ├─ 角色状态 │
│ └─ 消息广播 │
├─────────────────────────────────────────┤
│ 数据持久化 │
│ ├─ 角色数据存储 │
│ ├─ 世界状态存储 │
│ └─ JSON 文件系统 │
└─────────────────────────────────────────┘
```
### 客户端架构
客户端采用 Godot 的场景树结构,主要节点组织如下:
```
Main (Node)
├─ NetworkManager (Node) - 网络连接管理
├─ GameStateManager (Node) - 游戏状态管理
├─ UILayer (CanvasLayer) - UI 层
│ ├─ LoginScreen (Control) - 登录界面
│ ├─ CharacterCreation (Control) - 角色创建界面
│ ├─ HUD (Control) - 游戏内 UI
│ └─ DialogueBox (Control) - 对话框
└─ GameWorld (Node2D) - 游戏世界
├─ TileMap (TileMap) - 场景地图
├─ Characters (Node2D) - 角色容器
│ ├─ PlayerCharacter (CharacterBody2D) - 本地玩家
│ └─ RemoteCharacter (CharacterBody2D) - 其他角色
└─ Camera (Camera2D) - 摄像机
```
### 服务器架构
服务器采用事件驱动架构,主要模块包括:
- **ConnectionManager**: 管理 WebSocket 连接
- **AuthenticationService**: 处理玩家身份验证
- **WorldState**: 维护游戏世界状态
- **CharacterManager**: 管理所有角色(在线/离线)
- **MessageRouter**: 路由和广播消息
- **PersistenceService**: 数据持久化服务
## 组件和接口
### 1. 网络管理器 (NetworkManager)
**职责**: 管理客户端与服务器的 WebSocket 连接
**接口**:
```gdscript
class_name NetworkManager extends Node
signal connected_to_server()
signal disconnected_from_server()
signal connection_error(error: String)
signal message_received(message: Dictionary)
func connect_to_server(url: String) -> void
func disconnect_from_server() -> void
func send_message(message: Dictionary) -> void
func is_connected() -> bool
```
**消息协议**:
所有消息使用 JSON 格式,包含以下字段:
```json
{
"type": "message_type",
"data": {},
"timestamp": 1234567890
}
```
消息类型包括:
- `auth_request`: 身份验证请求
- `auth_response`: 身份验证响应
- `character_create`: 创建角色
- `character_move`: 角色移动
- `character_state`: 角色状态更新
- `dialogue_send`: 发送对话
- `world_state`: 世界状态同步
### 2. 角色控制器 (CharacterController)
**职责**: 处理角色的移动、动画和状态
**接口**:
```gdscript
class_name CharacterController extends CharacterBody2D
var character_id: String
var character_name: String
var is_online: bool
var move_speed: float = 200.0
func move_to(direction: Vector2) -> void
func set_position_smooth(target_pos: Vector2) -> void
func play_animation(anim_name: String) -> void
func set_online_status(online: bool) -> void
```
**状态**:
- `idle`: 静止状态
- `walking`: 行走状态
- `talking`: 对话状态
### 3. 对话系统 (DialogueSystem)
**职责**: 管理角色之间的对话交互
**接口**:
```gdscript
class_name DialogueSystem extends Node
signal dialogue_started(character_id: String)
signal dialogue_ended()
signal message_received(sender: String, message: String)
func start_dialogue(target_character_id: String) -> void
func send_message(message: String) -> void
func end_dialogue() -> void
func show_bubble(character_id: String, message: String, duration: float) -> void
```
**对话模式**:
- **直接对话**: 玩家与另一个角色一对一对话
- **气泡对话**: 附近角色的对话以气泡形式显示
### 4. 输入处理器 (InputHandler)
**职责**: 处理多平台输入(键盘、触摸、虚拟摇杆)
**接口**:
```gdscript
class_name InputHandler extends Node
signal move_input(direction: Vector2)
signal interact_input()
signal ui_input(action: String)
func get_move_direction() -> Vector2
func is_interact_pressed() -> bool
func setup_virtual_controls() -> void
```
**输入映射**:
- **桌面端**: WASD/方向键移动E 键交互
- **移动端**: 虚拟摇杆移动,交互按钮
### 5. 游戏状态管理器 (GameStateManager)
**职责**: 管理游戏的全局状态和场景切换
**接口**:
```gdscript
class_name GameStateManager extends Node
enum GameState {
LOGIN,
CHARACTER_CREATION,
IN_GAME,
DISCONNECTED
}
var current_state: GameState
var player_data: Dictionary
func change_state(new_state: GameState) -> void
func save_player_data() -> void
func load_player_data() -> Dictionary
```
### 6. 世界管理器 (WorldManager)
**职责**: 管理游戏世界中的所有角色和对象
**接口**:
```gdscript
class_name WorldManager extends Node
var characters: Dictionary = {} # character_id -> CharacterController
func spawn_character(character_data: Dictionary) -> void
func remove_character(character_id: String) -> void
func update_character_state(character_id: String, state: Dictionary) -> void
func get_nearby_characters(position: Vector2, radius: float) -> Array
```
## 数据模型
### 角色数据 (Character Data)
```gdscript
{
"id": "unique_character_id",
"name": "角色名称",
"owner_id": "player_account_id",
"position": {
"x": 100.0,
"y": 200.0
},
"is_online": true,
"appearance": {
"sprite": "character_01",
"color": "#FFFFFF"
},
"created_at": 1234567890,
"last_seen": 1234567890
}
```
### 世界状态 (World State)
```gdscript
{
"scene_id": "datawhale_office",
"characters": [
//
],
"timestamp": 1234567890
}
```
### 对话消息 (Dialogue Message)
```gdscript
{
"sender_id": "character_id",
"receiver_id": "character_id", // 广
"message": "对话内容",
"timestamp": 1234567890
}
```
## 正确性属性
*属性是一个特征或行为,应该在系统的所有有效执行中保持为真——本质上是关于系统应该做什么的正式陈述。属性作为人类可读规范和机器可验证正确性保证之间的桥梁。*
### 属性 1: 角色创建唯一性
*对于任意*两个成功创建的角色,它们的角色 ID 应该是唯一的,不会发生冲突
**验证需求: 1.5**
### 属性 2: 角色移动能力
*对于任意*创建或加载到场景的角色,该角色应该具有基础移动能力(可以响应移动指令)
**验证需求: 2.1**
### 属性 3: 位置更新同步
*对于任意*角色的移动操作,执行移动后角色的位置坐标应该被更新,并且该更新应该同步到所有连接的客户端
**验证需求: 2.2**
### 属性 4: 碰撞检测
*对于任意*角色和障碍物,当角色尝试移动到障碍物位置时,系统应该阻止该移动,角色位置保持不变
**验证需求: 2.4**
### 属性 5: 并发移动独立性
*对于任意*多个同时移动的角色,每个角色的移动应该独立处理,一个角色的移动不应影响其他角色的移动逻辑
**验证需求: 2.5**
### 属性 6: 对话触发
*对于任意*两个角色,当一个角色接近另一个角色并触发交互时,系统应该显示对话界面
**验证需求: 3.1**
### 属性 7: 消息传递完整性
*对于任意*对话消息,当玩家发送消息时,该消息应该被传递给接收方,并在发送方和接收方的界面上都正确显示
**验证需求: 3.3**
### 属性 8: 对话状态恢复
*对于任意*进行中的对话,当对话结束时,系统应该关闭对话界面并将游戏状态恢复到对话前的正常状态
**验证需求: 3.4**
### 属性 9: 对话可见性
*对于任意*两个角色之间的对话,附近的其他角色应该能够看到对话气泡显示在对话角色上方
**验证需求: 3.5**
### 属性 10: 场景碰撞检测
*对于任意*玩家角色和场景元素(如桌椅、墙壁),当玩家尝试移动到场景元素位置时,系统应该正确处理碰撞并阻止穿透
**验证需求: 4.5**
### 属性 11: 键盘输入响应
*对于任意*有效的键盘移动输入(方向键或 WASD系统应该将玩家角色移动到相应方向并将移动数据同步到服务器
**验证需求: 5.1**
### 属性 12: 触摸输入响应
*对于任意*有效的触摸移动输入(虚拟摇杆),系统应该将玩家角色移动到指定方向,并将移动数据同步到服务器
**验证需求: 5.2**
### 属性 13: 移动动画同步
*对于任意*角色的移动操作,系统应该播放相应的移动动画,并在所有客户端同步显示该动画
**验证需求: 5.5**
### 属性 14: 响应式布局适配
*对于任意*不同分辨率的浏览器窗口,游戏画面应该自动调整尺寸以适应窗口大小,保持可玩性
**验证需求: 6.3, 7.2**
### 属性 15: 窗口动态调整
*对于任意*浏览器窗口大小的改变,游戏系统应该动态调整游戏画面比例,保持界面元素的可访问性
**验证需求: 6.4**
### 属性 16: 数据序列化往返
*对于任意*游戏数据对象,序列化为 JSON 后再反序列化应该得到等价的对象(往返一致性)
**验证需求: 7.3, 9.5**
### 属性 17: 设备类型检测
*对于任意*设备类型(桌面或移动),系统应该正确检测设备类型并应用相应的控制方案(键盘或触摸)
**验证需求: 7.5**
### 属性 18: 角色数据持久化
*对于任意*创建的角色,角色数据应该被保存到服务器,后续登录时应该能够恢复相同的角色数据
**验证需求: 9.1, 9.2**
### 属性 19: 状态同步
*对于任意*角色位置或状态的改变,系统应该将更新同步到服务器,确保数据一致性
**验证需求: 9.4**
### 属性 20: 移动设备 UI 适配
*对于任意*在移动设备上运行的游戏UI 元素大小应该调整以适应触摸操作(按钮足够大,间距合理)
**验证需求: 10.4**
### 属性 21: 错误提示显示
*对于任意*操作失败的情况,系统应该显示明确的错误提示信息,告知用户失败原因
**验证需求: 10.5**
### 属性 22: 在线角色显示
*对于任意*玩家进入游戏场景时,系统应该显示所有当前在线玩家的角色
**验证需求: 11.1**
### 属性 23: 离线角色显示
*对于任意*玩家进入游戏场景时,系统应该显示所有离线玩家的角色作为 NPC
**验证需求: 11.2**
### 属性 24: 上线状态切换
*对于任意*玩家上线事件,系统应该在场景中显示该玩家的角色,并将其标记为在线状态
**验证需求: 11.3**
### 属性 25: 下线状态切换
*对于任意*玩家下线事件,系统应该将该玩家的角色转换为离线 NPC 状态,但角色继续存在于场景中
**验证需求: 11.4**
### 属性 26: 角色状态视觉区分
*对于任意*显示的角色,系统应该通过视觉标识(如颜色、图标)区分在线玩家和离线角色
**验证需求: 11.5**
### 属性 27: 网络连接建立
*对于任意*玩家登录操作,系统应该尝试建立与服务器的网络连接
**验证需求: 12.1**
### 属性 28: 断线重连
*对于任意*网络连接中断事件,系统应该显示断线提示并自动尝试重新连接到服务器
**验证需求: 12.3**
### 属性 29: 操作确认
*对于任意*玩家执行的操作,系统应该将操作数据发送到服务器并等待接收确认响应
**验证需求: 12.4**
### 属性 30: 服务器更新同步
*对于任意*服务器推送的更新消息,客户端应该实时更新本地游戏状态以反映服务器的变化
**验证需求: 12.5**
## 错误处理
### 网络错误处理
**连接失败**:
- 显示友好的错误提示
- 提供重试按钮
- 记录错误日志用于调试
**连接中断**:
- 自动尝试重连(最多 3 次)
- 显示断线状态指示器
- 缓存未发送的操作,重连后重新发送
**消息发送失败**:
- 重试机制(指数退避)
- 超时后通知用户
- 保持本地状态一致性
### 数据验证错误
**角色创建验证**:
- 名称长度限制2-20 字符)
- 禁止特殊字符和空白字符
- 检查名称唯一性
**输入验证**:
- 对话消息长度限制1-500 字符)
- 过滤恶意输入
- 防止注入攻击
### 状态不一致处理
**客户端-服务器状态不一致**:
- 定期同步状态(每 5 秒)
- 服务器状态为权威状态
- 客户端预测 + 服务器校正
**角色位置冲突**:
- 服务器检测位置冲突
- 强制回退到有效位置
- 通知客户端更新
## 测试策略
### 单元测试
使用 Godot 的 GUT (Godot Unit Test) 框架进行单元测试。
**测试覆盖范围**:
- 数据模型的序列化/反序列化
- 输入处理逻辑
- 状态管理器的状态转换
- 消息协议的编码/解码
**示例测试**:
```gdscript
# test_character_data.gd
extends GutTest
func test_character_serialization():
var character = {
"id": "test_123",
"name": "测试角色",
"position": {"x": 100.0, "y": 200.0}
}
var json_str = JSON.stringify(character)
var parsed = JSON.parse_string(json_str)
assert_eq(parsed["id"], character["id"])
assert_eq(parsed["name"], character["name"])
```
### 属性基础测试
使用 GDScript 实现简单的属性测试框架,或使用社区提供的属性测试库。
**测试库**: 自定义实现或使用 Godot 社区的属性测试工具
**测试配置**: 每个属性测试至少运行 100 次迭代
**测试标注格式**: `# Feature: godot-ai-town-game, Property X: [属性描述]`
**属性测试覆盖**:
1. **属性 1: 角色创建唯一性**
- 生成多个随机角色
- 验证所有角色 ID 唯一
2. **属性 2: 角色移动能力**
- 生成随机角色
- 验证角色可以响应移动指令
3. **属性 3: 位置更新同步**
- 生成随机移动操作
- 验证位置正确更新
4. **属性 4: 碰撞检测**
- 生成随机障碍物和移动路径
- 验证碰撞正确阻止移动
5. **属性 16: 数据序列化往返**
- 生成随机游戏数据对象
- 验证序列化后反序列化得到等价对象
6. **属性 18: 角色数据持久化**
- 生成随机角色数据
- 验证保存后加载得到相同数据
**示例属性测试**:
```gdscript
# test_properties.gd
extends GutTest
# Feature: godot-ai-town-game, Property 16: 数据序列化往返
func test_property_serialization_roundtrip():
for i in range(100):
var random_data = generate_random_character_data()
var serialized = JSON.stringify(random_data)
var deserialized = JSON.parse_string(serialized)
assert_eq_deep(deserialized, random_data,
"序列化往返应该保持数据一致性")
func generate_random_character_data() -> Dictionary:
return {
"id": "char_" + str(randi()),
"name": "角色" + str(randi() % 1000),
"position": {
"x": randf_range(0, 1000),
"y": randf_range(0, 1000)
},
"is_online": randi() % 2 == 0
}
```
### 集成测试
**场景加载测试**:
- 测试 Datawhale 办公室场景正确加载
- 验证所有必需的节点存在
- 检查碰撞层设置正确
**网络集成测试**:
- 启动测试服务器
- 测试客户端连接流程
- 验证消息收发正确
**多客户端测试**:
- 模拟多个客户端连接
- 测试状态同步
- 验证角色互动
### 性能测试
**帧率测试**:
- 测试不同数量角色时的帧率
- 目标: 30+ FPS (10 个角色)
**网络延迟测试**:
- 测试不同网络条件下的响应时间
- 目标: 操作响应 < 200ms
**内存使用测试**:
- 监控长时间运行的内存使用
- 检测内存泄漏
### 跨平台测试
**浏览器兼容性**:
- Chrome (最新版本)
- Firefox (最新版本)
- Safari (最新版本)
- Edge (最新版本)
**设备测试**:
- 桌面 (1920x1080, 1366x768)
- 平板 (iPad, Android 平板)
- 手机 (iOS, Android)
**输入测试**:
- 键盘输入
- 鼠标输入
- 触摸输入
- 虚拟摇杆
## 场景设计
### Datawhale 办公室场景
**场景尺寸**: 2000x1500 像素
**主要区域**:
1. **入口区域**: 门、欢迎标识
2. **工作区**: 办公桌、电脑、椅子
3. **会议区**: 会议桌、白板
4. **休息区**: 沙发、茶水间
5. **展示区**: Datawhale logo、成就墙
**碰撞层设置**:
- Layer 1: 墙壁和固定障碍物
- Layer 2: 家具(可选择性碰撞)
- Layer 3: 角色
- Layer 4: 交互区域
**视觉风格**:
- 2D 俯视角45度等距视角可选
- 简洁的像素艺术或矢量风格
- Datawhale 品牌色: 蓝色系为主
### 资源需求
**图像资源**:
- 角色精灵图4 方向行走动画)
- 场景瓦片集(地板、墙壁、家具)
- UI 元素(按钮、对话框、图标)
- Datawhale logo 和品牌元素
**音频资源** (可选):
- 背景音乐
- 脚步声
- UI 交互音效
- 对话提示音
## 部署和构建
### Web 导出配置
**Godot 导出设置**:
- 目标平台: HTML5
- 导出模板: Godot 4.x Web
- 线程支持: 启用(如果浏览器支持)
- VRAM 压缩: 启用
**Web 服务器要求**:
- 支持 WebSocket
- HTTPS (用于生产环境)
- CORS 配置正确
### 服务器部署
**推荐部署方案**:
- 静态文件: Nginx/Apache 或 CDN
- WebSocket 服务器: Node.js 或 Python
- 数据存储: JSON 文件或轻量级数据库
**环境变量**:
- `SERVER_URL`: WebSocket 服务器地址
- `PORT`: 服务器端口
- `DATA_DIR`: 数据存储目录
### 移动端预留
**响应式设计**:
- 使用 Godot 的 Viewport 缩放
- UI 元素使用相对定位
- 字体大小动态调整
**输入抽象**:
- 统一的输入接口
- 自动检测输入设备
- 虚拟控制器自动显示/隐藏
**跨端数据同步**:
- 统一的数据格式
- 服务器端状态管理
- 客户端无状态设计
## 扩展性考虑
### 未来功能预留
**AI 对话系统**:
- 预留 AI 接口(如 OpenAI API
- 对话历史记录
- 角色个性设置
**更多场景**:
- 场景管理器支持多场景
- 场景切换机制
- 场景间传送
**社交功能**:
- 好友系统
- 私聊功能
- 角色关系网络
### 性能优化预留
**对象池**:
- 角色对象复用
- UI 元素复用
- 减少内存分配
**网络优化**:
- 消息批处理
- 状态差异同步
- 区域兴趣管理AOI
**渲染优化**:
- 视锥剔除
- LOD (细节层次)
- 纹理压缩