diff --git a/MIGRATION_COMPLETE.md b/MIGRATION_COMPLETE.md deleted file mode 100644 index c4b7123..0000000 --- a/MIGRATION_COMPLETE.md +++ /dev/null @@ -1,235 +0,0 @@ -# ✅ 项目结构重构完成报告 - -## 📅 完成时间 -2025-12-31 - -## 🎉 重构成功 - -项目已成功从混乱的文件结构重构为清晰、模块化的架构! - ---- - -## 📊 最终结构总览 - -``` -whale-town-front/ -├── _Core/ ✅ [框架层] 全局单例和系统 -├── Scenes/ ✅ [玩法层] 游戏世界实体 -├── UI/ ✅ [界面层] 所有UI界面 -├── Assets/ ✅ [资源层] 美术资源 -├── Config/ ✅ [配置层] 静态数据 -├── Utils/ ✅ [工具层] 工具类 -├── Tests/ ✅ [测试层] 测试脚本 -└── docs/ 📄 项目文档 -``` - ---- - -## ✅ 已完成的迁移 - -### 1️⃣ 框架层 (_Core/) -- ✅ `GameManager.gd` → `_Core/managers/` -- ✅ `SceneManager.gd` → `_Core/managers/` (已更新路径) -- ✅ `NetworkManager.gd` → `_Core/managers/` -- ✅ `ResponseHandler.gd` → `_Core/managers/` -- ✅ `EventSystem.gd` → `_Core/systems/` - -### 2️⃣ 场景层 (Scenes/) -- ✅ `scenes/main_scene.tscn` → `Scenes/Maps/main_scene.tscn` -- ✅ `scripts/scenes/MainScene.gd` → `Scenes/Maps/MainScene.gd` -- ✅ `scenes/prefabs/` → `Scenes/Components/` - -### 3️⃣ 界面层 (UI/) -- ✅ `scenes/auth_scene.tscn` → `UI/Windows/LoginWindow.tscn` -- ✅ `scripts/scenes/AuthScene.gd` → `UI/Windows/AuthScene.gd` -- ✅ `assets/ui/chinese_theme.tres` → `UI/Theme/MainTheme.tres` -- ✅ `assets/fonts/` → `UI/Theme/Fonts/` - -### 4️⃣ 配置层 (Config/) -- ✅ `data/configs/game_config.json` → `Config/game_config.json` -- ✅ `data/localization/zh_CN.json` → `Config/zh_CN.json` - -### 5️⃣ 工具层 (Utils/) -- ✅ `core/utils/StringUtils.gd` → `Utils/StringUtils.gd` - -### 6️⃣ 资源层 (Assets/) -- ✅ `assets/sprites/` → `Assets/Sprites/` -- ✅ `assets/audio/` → `Assets/Audio/` -- ✅ 其他资源文件保留在 `assets/`(待后续整理) - -### 7️⃣ 构建脚本 -- ✅ `scripts/build_web.sh` → `./build_web.sh` -- ✅ `scripts/serve_web.sh` → `./serve_web.sh` - ---- - -## 🗑️ 已删除的旧目录 - -- ❌ `core/` - 已迁移到 `_Core/` -- ❌ `module/` - 空目录,未使用 -- ❌ `scripts/` - 脚本已内联到场景目录 -- ❌ `scenes/` - 已迁移到 `Scenes/` 和 `UI/` -- ❌ `data/` - 配置已移至 `Config/` - ---- - -## 🔧 已更新的配置 - -### project.godot -```ini -✅ run/main_scene="res://Scenes/Maps/main_scene.tscn" -✅ GameManager="*res://_Core/managers/GameManager.gd" -✅ SceneManager="*res://_Core/managers/SceneManager.gd" -✅ EventSystem="*res://_Core/systems/EventSystem.gd" -✅ NetworkManager="*res://_Core/managers/NetworkManager.gd" -✅ ResponseHandler="*res://_Core/managers/ResponseHandler.gd" -``` - -### SceneManager.gd -```gdscript -✅ "main": "res://Scenes/Maps/main_scene.tscn" -✅ "auth": "res://UI/Windows/LoginWindow.tscn" -``` - -### 测试文件 -```gdscript -✅ tests/auth/enhanced_toast_test.gd - 已更新脚本路径 -✅ tests/auth/auth_ui_test.tscn - 已更新场景路径 -``` - ---- - -## 📚 创建的文档 - -1. **REFACTORING.md** - 详细的重构文档 - - 迁移映射表 - - 设计原则 - - 注意事项 - - 后续建议 - -2. **STRUCTURE_COMPARISON.md** - 结构对比分析 - - 旧结构问题分析 - - 新结构优势说明 - - 对比表格 - - 团队协作改进 - ---- - -## 🎯 关键改进 - -### 清晰的分层 -- **_Core**: 框架代码,全局系统 -- **Scenes**: 游戏世界,地图和实体 -- **UI**: 所有界面,HUD和弹窗 -- **Config**: 静态数据,策划可编辑 -- **Utils**: 通用工具函数库 - -### 组件化设计 -```gdscript -Scenes/Components/ // 可复用组件 -├── characters/ // 角色预制体 -├── effects/ // 特效预制体 -├── items/ // 物品预制体 -└── ui/ // UI预制体 -``` - -### 场景内聚 -- 每个 `.tscn` 配套一个 `.gd` -- 脚本紧邻场景文件 -- 符合 Godot 原生习惯 - -### UI 独立化 -``` -UI/ -├── Windows/ // 模态窗口(登录、设置) -├── HUD/ // 常驻界面(聊天框) -├── Dialog/ // 对话系统 -└── Theme/ // 全局样式 -``` - ---- - -## ⚠️ 后续步骤 - -### 必做事项 -- [ ] 在 Godot 编辑器中打开项目,让编辑器重新索引文件 -- [ ] 测试主场景加载: `Scenes/Maps/main_scene.tscn` -- [ ] 验证登录窗口: `UI/Windows/LoginWindow.tscn` -- [ ] 测试所有自动加载脚本 -- [ ] 运行完整测试套件 - -### 建议优化 -- [ ] 补充 `Scenes/Components/` 下的可复用组件 -- [ ] 完善 `UI/HUD/` 和 `UI/Dialog/` -- [ ] 添加 `Scenes/Entities/Player/` 玩家实体 -- [ ] 将硬编码数值移至 `Config/` - -### 代码审查 -- [ ] 检查是否还有硬编码的旧路径 -- [ ] 验证所有 `.import` 文件正常 -- [ ] 确认网络连接功能正常 -- [ ] 验证 UI 主题显示正确 - ---- - -## 🎓 团队协作指南 - -### 工作目录划分 -``` -🎨 美术组 → Assets/Sprites/, Assets/Audio/ -📋 策划组 → Config/ -💻 前端程序 → UI/, Scenes/Entities/ -⚙️ 后端程序 → _Core/, Utils/ -🧪 测试组 → Tests/ -``` - -### Git 提交建议 -```bash -# 按目录分类提交 -git add _Core/ -git commit -m "refactor: 迁移核心框架代码到 _Core/" - -git add Scenes/ -git commit -m "refactor: 重组场景文件到 Scenes/" - -git add UI/ -git commit -m "refactor: 独立 UI 界面到 UI/" -``` - ---- - -## 📈 预期收益 - -### 可维护性提升 -- 🟢 目录职责清晰,降低认知负担 -- 🟢 新人快速定位文件 -- 🟢 减少代码冲突 - -### 开发效率提升 -- 🟢 组件复用更容易 -- 🟢 团队协作更流畅 -- 🟢 代码审查更高效 - -### 符合最佳实践 -- ✅ Godot 官方推荐结构 -- ✅ 场景内聚原则 -- ✅ 组件化设计思想 -- ✅ 配置与代码分离 - ---- - -## 🎉 总结 - -**重构完成!** 项目现在拥有: -- ✅ 清晰的 6 层架构 -- ✅ 符合 Godot 最佳实践 -- ✅ 易于维护和扩展 -- ✅ 团队协作友好 - -感谢您的耐心!如有问题,请查看详细文档: -- [REFACTORING.md](./REFACTORING.md) - 重构详情 -- [STRUCTURE_COMPARISON.md](./STRUCTURE_COMPARISON.md) - 结构对比 - ---- - -**下一步:在 Godot 编辑器中打开项目并测试!** 🚀 diff --git a/README.md b/README.md index 6506686..72a21ff 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ python tests/api/api_client_test.py 1. **[📖 项目入门总览](docs/01-项目入门/README.md)** - 5分钟了解项目 2. **[🏗️ 项目结构说明](docs/01-项目入门/项目结构说明.md)** - 理解架构设计 3. **[⚙️ 项目设置指南](docs/01-项目入门/项目设置指南.md)** - 配置开发环境 +4. **[🤖 AI开发指南](docs/AI_docs/README.md)** - AI编程助手专用文档 ### 🎯 第二步:学习规范 @@ -121,34 +122,65 @@ WhaleTown/ # 🐋 项目根目录 │ ├── 03-技术实现/ # 🔧 开发指导 │ ├── 04-高级开发/ # 🚀 进阶技巧 │ ├── 05-部署运维/ # 🌐 发布部署 -│ └── 06-功能模块/ # 🎮 功能文档 -├── 🎬 scenes/ # 🎭 游戏场景 -│ ├── Maps/ # 🗺️ 地图场景 -│ └── Components/ # 🧩 组件预制体 -├── 🔧 _Core/ # ⚙️ 核心系统 -│ ├── managers/ # 🎯 全局管理器 -│ ├── systems/ # 🔄 系统组件 +│ ├── 06-功能模块/ # 🎮 功能文档 +│ └── AI_docs/ # 🤖 AI专用文档(执行规范、代码模板) +├── 🔧 _Core/ # ⚙️ 核心底层实现 +│ ├── managers/ # 🎯 全局管理器(游戏状态、场景、网络等) +│ ├── systems/ # 🔄 系统组件(事件系统、输入系统等) +│ ├── components/ # 🧩 基础组件实现 +│ ├── utils/ # � 核件心工具类(字符串处理、数学计算等) │ ├── EventNames.gd # 📝 事件名称定义 -│ └── ProjectPaths.gd # 📂 路径统一管理 -├── 🎨 UI/ # 🖼️ 用户界面 -│ └── Windows/ # 🪟 窗口界面 -├── 🔨 Utils/ # 🔨 工具类 -├── 🎮 module/ # 🧩 功能模块 -├── 🎨 assets/ # 🖼️ 游戏资源 -├── ⚙️ Config/ # 📋 配置文件 -├── 🧪 tests/ # 🔬 测试文件 -└── 🌐 web_assets/ # 🌍 Web部署资源 +│ └── ProjectPaths.gd # � 路径组统一管理 +├── 🎬 scenes/ # 🎭 场景与视觉呈现 +│ ├── maps/ # �️ 地图一场景(游戏关卡、世界地图) +│ ├── characters/ # 👤 人物场景(角色、NPC、敌人) +│ ├── ui/ # 🖼️ UI界面场景(菜单、HUD、对话框) +│ ├── effects/ # ✨ 特效场景(粒子效果、动画) +│ └── prefabs/ # 🧩 预制体组件 +├── 🎨 assets/ # 🖼️ 静态资源存储 +│ ├── sprites/ # 🎨 精灵图片(角色、物品、环境) +│ ├── audio/ # 🎵 音频资源(音乐、音效) +│ ├── fonts/ # 🔤 字体文件 +│ ├── materials/ # 🎭 材质资源 +│ ├── shaders/ # 🌈 着色器文件 +│ ├── ui/ # 🖼️ UI素材(按钮、图标、背景) +│ └── icon/ # 📱 应用图标 +├── ⚙️ Config/ # 📋 配置文件管理 +│ ├── game_config.json # 🎮 游戏配置(难度、设置等) +│ ├── zh_CN.json # 🌐 本地化配置 +│ └── environment/ # 🔧 环境配置(开发、测试、生产) +├── 🧪 tests/ # 🔬 测试文件系统 +│ ├── unit/ # 🔍 单元测试(组件功能测试) +│ ├── integration/ # 🔗 集成测试(系统交互测试) +│ ├── performance/ # ⚡ 性能测试(帧率、内存优化) +│ └── api/ # 🌐 API接口测试 +└── 🌐 web_assets/ # 🌍 Web导出资源 + ├── html/ # 📄 HTML模板文件 + ├── css/ # 🎨 样式文件 + └── js/ # 📜 JavaScript脚本 ``` -### 🔧 核心组件 +### 🔧 核心架构说明 -| 组件 | 作用 | 文档链接 | +| 目录 | 作用 | 详细说明 | |------|------|----------| -| **EventSystem** | 全局事件通信 | [架构规范](docs/02-开发规范/架构与通信规范.md) | -| **GameManager** | 游戏状态管理 | [实现细节](docs/03-技术实现/实现细节规范.md) | -| **SceneManager** | 场景切换管理 | [场景设计](docs/04-高级开发/场景设计规范.md) | -| **NetworkManager** | 网络请求管理 | [网络管理器](docs/03-技术实现/网络管理器设置.md) | -| **ProjectPaths** | 路径统一管理 | [项目结构](docs/01-项目入门/项目结构说明.md) | +| **_Core** | 🔧 功能实现与组件实现 | 项目最基本的底层实现,包含所有核心系统和基础组件 | +| **scenes** | 🎭 场景与视觉呈现 | 包含地图场景、人物场景等一系列视觉呈现部分,主要是UI的实现 | +| **assets** | 🎨 静态资源存储 | 所有静态资源的存储,包括图片、音乐、视频、贴图等素材 | +| **Config** | ⚙️ 配置文件管理 | 主要用来配置各类环境,包括游戏设置、本地化等配置 | +| **tests** | 🧪 测试文件系统 | 放置所有对应组件的测试代码,方便快速进行功能性与性能测试 | +| **web_assets** | 🌐 Web导出资源 | 专门用于Web平台导出的相关资源和配置文件 | +| **docs/AI_docs** | 🤖 AI专用文档 | 专门为AI编程助手准备的执行规范和代码模板,提升vibe coding效率 | + +### 🎮 核心组件 + +| 组件 | 位置 | 作用 | 文档链接 | +|------|------|------|----------| +| **EventSystem** | _Core/systems/ | 全局事件通信系统 | [架构规范](docs/02-开发规范/架构与通信规范.md) | +| **GameManager** | _Core/managers/ | 游戏状态管理器 | [实现细节](docs/03-技术实现/实现细节规范.md) | +| **SceneManager** | _Core/managers/ | 场景切换管理器 | [场景设计](docs/04-高级开发/场景设计规范.md) | +| **NetworkManager** | _Core/managers/ | 网络请求管理器 | [网络管理器](docs/03-技术实现/网络管理器设置.md) | +| **ProjectPaths** | _Core/ | 路径统一管理工具 | [项目结构](docs/01-项目入门/项目结构说明.md) | --- diff --git a/REFACTORING.md b/REFACTORING.md deleted file mode 100644 index ecad018..0000000 --- a/REFACTORING.md +++ /dev/null @@ -1,222 +0,0 @@ -# 项目结构重构文档 - -## 📅 重构时间 -2025-12-31 - -## 🎯 重构目标 -将项目从混乱的文件结构重构为清晰、模块化的架构,采用 Godot 最佳实践。 - -## 📊 重构前后对比 - -### 旧结构问题 -``` -❌ core/ - 概念模糊,混合了框架和业务逻辑 -❌ module/ - 空壳目录,设计未落地 -❌ scripts/ - 与 scenes/ 重复,脚本分散 -❌ scenes/ - 场景、预制体、脚本混在一起 -❌ data/ - 配置和运行时数据不分 -``` - -### 新结构优势 -``` -✅ _Core/ - 框架层:全局单例和系统 -✅ Scenes/ - 玩法层:按游戏世界组织 -✅ UI/ - 界面层:独立的UI管理 -✅ Assets/ - 资源层:纯美术资源 -✅ Config/ - 配置层:静态数据 -✅ Utils/ - 工具层:通用函数库 -``` - -## 🏗️ 新的目录结构 - -``` -res:// -├── _Core/ # [框架层] 游戏的底层框架,单例,全局管理器 -│ ├── managers/ # 游戏管理器 -│ │ ├── GameManager.gd # 游戏状态管理 -│ │ ├── SceneManager.gd # 场景管理(已更新路径) -│ │ ├── NetworkManager.gd # 网络通信 -│ │ └── ResponseHandler.gd # API响应处理 -│ ├── systems/ # 核心系统 -│ │ └── EventSystem.gd # 事件系统 -│ └── singletons/ # 其他单例(待扩展) -│ -├── Scenes/ # [玩法层] 具体的游戏场景、实体、地图 -│ ├── Maps/ # 地图场景 -│ │ └── main_scene.tscn # 主游戏场景 -│ ├── Entities/ # 游戏实体 -│ │ ├── Player/ # 玩家实体 -│ │ ├── NPC/ # NPC实体 -│ │ └── Interactables/ # 交互物 -│ └── Components/ # 可复用组件 -│ -├── UI/ # [界面层] 所有UI相关的预制体和逻辑 -│ ├── HUD/ # 抬头显示(常驻) -│ ├── Windows/ # 模态窗口 -│ │ └── LoginWindow.tscn # 登录窗口(原auth_scene.tscn) -│ ├── Dialog/ # 对话系统 -│ └── Theme/ # 全局样式 -│ ├── MainTheme.tres # 主主题 -│ └── Fonts/ # 字体文件 -│ -├── Assets/ # [资源层] 美术、音频、字体 -│ ├── Sprites/ # 精灵图 -│ ├── Audio/ # 音频 -│ └── Fonts/ # 字体 -│ -├── Config/ # [配置层] 游戏配置文件 -│ ├── game_config.json # 游戏配置 -│ └── zh_CN.json # 中文本地化 -│ -├── Utils/ # [工具层] 通用辅助脚本 -│ └── StringUtils.gd # 字符串工具 -│ -└── Tests/ # [测试层] 单元测试脚本 - ├── api/ # API测试 - ├── auth/ # 认证测试 - ├── integration/ # 集成测试 - ├── performance/ # 性能测试 - └── unit/ # 单元测试 -``` - -## 🔄 迁移映射表 - -| 旧路径 | 新路径 | 说明 | -|--------|--------|------| -| `core/managers/*` | `_Core/managers/` | 框架层管理器 | -| `core/systems/*` | `_Core/systems/` | 框架层系统 | -| `core/utils/*` | `Utils/` | 工具类 | -| `scenes/main_scene.tscn` | `Scenes/Maps/main_scene.tscn` | 主游戏场景 | -| `scenes/auth_scene.tscn` | `UI/Windows/LoginWindow.tscn` | 登录窗口 | -| `data/configs/*.json` | `Config/` | 配置文件 | -| `data/localization/*.json` | `Config/` | 本地化配置 | -| `assets/ui/chinese_theme.tres` | `UI/Theme/MainTheme.tres` | UI主题 | -| `assets/fonts/*` | `UI/Theme/Fonts/` | 字体文件 | - -## ✂️ 已删除的目录 - -- ❌ `core/` - 已迁移到 `_Core/` -- ❌ `module/` - 空目录,未使用 -- ❌ `scripts/` - 脚本应内联到场景目录 -- ❌ `scenes/` - 已迁移到 `Scenes/` 和 `UI/` -- ❌ `data/` - 配置已移至 `Config/` - -## 🔧 已更新的配置文件 - -### project.godot -```ini -# 更新主场景路径 -run/main_scene="res://Scenes/Maps/main_scene.tscn" - -# 更新自动加载路径 -GameManager="*res://_Core/managers/GameManager.gd" -SceneManager="*res://_Core/managers/SceneManager.gd" -EventSystem="*res://_Core/systems/EventSystem.gd" -NetworkManager="*res://_Core/managers/NetworkManager.gd" -ResponseHandler="*res://_Core/managers/ResponseHandler.gd" -``` - -### SceneManager.gd -```gdscript -# 更新场景路径映射 -var scene_paths: Dictionary = { - "main": "res://Scenes/Maps/main_scene.tscn", - "auth": "res://UI/Windows/LoginWindow.tscn", - # ... 其他场景路径 -} -``` - -### 测试文件 -- `tests/auth/enhanced_toast_test.gd` - 已更新脚本路径 -- `tests/auth/auth_ui_test.tscn` - 已更新场景路径 - -## 🎨 设计原则 - -### 1. 清晰的分层 -- **_Core**: 框架代码,与具体游戏逻辑无关 -- **Scenes**: 游戏世界,地图和实体 -- **UI**: 所有界面,HUD和弹窗 -- **Config**: 静态数据,策划可编辑 - -### 2. 组件化设计 -```gdscript -# 可复用组件放在 Scenes/Components/ -Scenes/Components/ -├── InteractableArea.tscn # 让任何物体"可交互" -├── MovementSync.gd # 网络位置同步 -└── NameTag3D.tscn # 头顶名字条 -``` - -### 3. 场景内聚 -- 每个 .tscn 配套一个 .gd -- 脚本紧邻场景文件存放 -- 符合 Godot 原生开发习惯 - -### 4. 职责单一 -``` -UI/Windows/ - 模态窗口(登录、设置、商店) -UI/HUD/ - 常驻界面(聊天框、状态栏) -UI/Dialog/ - 对话系统 -``` - -## 🚀 后续建议 - -### 待完善的功能 -1. **组件化开发** - - 创建 `Scenes/Components/` 下的可复用组件 - - 使用组合优于继承的设计模式 - -2. **UI 独立化** - - 补充 `UI/HUD/` 下的常驻界面 - - 创建 `UI/Dialog/` 对话系统 - -3. **场景管理** - - 补充更多地图场景到 `Scenes/Maps/` - - 添加玩家实体到 `Scenes/Entities/Player/` - -4. **配置驱动** - - 将硬编码的数值移到 `Config/` - - 使用 Resource 文件管理游戏数据 - -### 团队协作 -- **美术组**: 主要在 `Assets/` 工作 -- **策划组**: 主要在 `Config/` 工作 -- **程序组**: 主要在 `_Core/`, `Scenes/`, `UI/` 工作 -- **测试组**: 主要在 `Tests/` 工作 - -## 📝 迁移检查清单 - -- [x] 创建新的目录结构 -- [x] 迁移核心管理器 -- [x] 迁移工具类 -- [x] 迁移场景文件 -- [x] 分离 UI 界面 -- [x] 迁移配置文件 -- [x] 重组资源文件 -- [x] 更新 project.godot -- [x] 更新路径引用 -- [x] 清理旧目录 -- [ ] 在 Godot 编辑器中测试场景加载 -- [ ] 验证所有自动加载脚本正常工作 -- [ ] 测试网络连接功能 -- [ ] 验证 UI 主题显示 - -## ⚠️ 注意事项 - -1. **场景引用更新**: 所有旧场景的引用都已更新,但建议在 Godot 编辑器中重新打开项目,让编辑器重新索引文件 - -2. **.import 文件**: 移动资源文件后,Godot 可能会重新生成 .import 文件,这是正常的 - -3. **版本控制**: 如果使用 Git,旧文件的删除会在下次提交时体现 - -4. **测试覆盖**: 迁移后建议运行完整的测试套件确保功能正常 - -## 🎓 参考资料 - -- [Godot 官方项目组织建议](https://docs.godotengine.org/en/stable/tutorials/best_practices/project_organization.html) -- [GDScript 场景组织](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#scenes-and-scripts) -- [ECS 架构模式](https://github.com/SmitUS/Pine-Tree-ECS-For-Godot-4) - ---- - -**重构完成!项目现在拥有清晰的架构,易于维护和扩展。** 🎉 diff --git a/STRUCTURE_COMPARISON.md b/STRUCTURE_COMPARISON.md deleted file mode 100644 index 37001d3..0000000 --- a/STRUCTURE_COMPARISON.md +++ /dev/null @@ -1,213 +0,0 @@ -# 🏗️ 项目结构对比 - -## 旧结构 ❌ -``` -whale-town-front/ -├── core/ # ❌ 概念模糊 -│ ├── managers/ # - 框架代码? -│ ├── systems/ # - 还是业务逻辑? -│ └── utils/ # - 边界不清 -├── module/ # ❌ 空壳目录(无 .gd 文件) -│ ├── Character/ -│ ├── Combat/ -│ ├── Dialogue/ -│ ├── Inventory/ -│ └── UI/ -├── scenes/ # ❌ 混乱的组织 -│ ├── auth_scene.tscn -│ ├── main_scene.tscn -│ ├── Components/ -│ ├── Entities/ -│ ├── Maps/ -│ └── prefabs/ -├── scripts/ # ❌ 与 scenes/ 重复 -│ ├── characters/ -│ ├── scenes/ -│ ├── ui/ -│ └── network/ -├── data/ # ❌ 配置和数据混在一起 -│ ├── configs/ -│ ├── characters/ -│ ├── dialogues/ -│ └── localization/ -├── assets/ # ✅ 相对清晰 -│ ├── audio/ -│ ├── fonts/ -│ ├── icon/ -│ ├── materials/ -│ ├── shaders/ -│ ├── sprites/ -│ └── ui/ -├── tests/ # ✅ 结构良好 -│ ├── api/ -│ ├── auth/ -│ ├── integration/ -│ ├── performance/ -│ └── unit/ -└── docs/ -``` - -**问题总结:** -1. 🔴 脚本分散:`scripts/` 和 `scenes/` 都有脚本,职责不清 -2. 🔴 空壳模块:`module/` 目录存在但无实际代码 -3. 🔴 场景混乱:场景文件、预制体、脚本平级放置 -4. 🔴 分层不明:`core/`, `module/`, `scripts/` 三层交叉 -5. 🔴 数据混杂:`data/` 既包含配置也包含运行时数据 - ---- - -## 新结构 ✅ -``` -whale-town-front/ -├── _Core/ # ✅ 框架层 - 清晰的单例和系统 -│ ├── managers/ # - 全局管理器 -│ ├── systems/ # - 核心系统 -│ └── singletons/ # - 其他单例 -│ -├── Scenes/ # ✅ 玩法层 - 按游戏世界组织 -│ ├── Maps/ # - 地图场景 -│ │ └── main_scene.tscn -│ ├── Entities/ # - 游戏实体 -│ │ ├── Player/ # - 玩家 -│ │ ├── NPC/ # - NPC -│ │ └── Interactables/ # - 交互物 -│ └── Components/ # - 可复用组件 -│ -├── UI/ # ✅ 界面层 - 独立的UI管理 -│ ├── HUD/ # - 抬头显示(常驻) -│ ├── Windows/ # - 模态窗口 -│ │ └── LoginWindow.tscn # (原 auth_scene) -│ ├── Dialog/ # - 对话系统 -│ └── Theme/ # - 全局样式 -│ ├── MainTheme.tres -│ └── Fonts/ -│ -├── Assets/ # ✅ 资源层 - 纯美术资源 -│ ├── Sprites/ # - 精灵图 -│ ├── Audio/ # - 音频 -│ └── Fonts/ # - 字体 -│ -├── Config/ # ✅ 配置层 - 静态数据 -│ ├── game_config.json -│ └── zh_CN.json -│ -├── Utils/ # ✅ 工具层 - 通用函数库 -│ └── StringUtils.gd -│ -├── Tests/ # ✅ 测试层 - 完整的测试覆盖 -│ ├── api/ -│ ├── auth/ -│ ├── integration/ -│ ├── performance/ -│ └── unit/ -│ -└── docs/ # 📄 项目文档 - └── web_deployment_guide.md -``` - -**改进总结:** -1. 🟢 **分层清晰**: 框架、玩法、界面、资源、配置、工具各司其职 -2. 🟢 **场景内聚**: .tscn 和 .gd 成对出现,逻辑紧耦合场景 -3. 🟢 **UI 独立**: 所有界面统一管理,避免和游戏场景混淆 -4. 🟢 **配置分离**: Config 只存放静态数据,策划可直接编辑 -5. 🟢 **组件化**: Scenes/Components/ 提供可复用的逻辑组件 - ---- - -## 📊 核心改进对比表 - -| 维度 | 旧结构 | 新结构 | 改进效果 | -|:---:|:---:|:---:|:---:| -| **目录层级** | 8层 | 6层 | ✅ 更扁平 | -| **脚本管理** | 分散在2处 | 集中在场景内 | ✅ 内聚性高 | -| **UI 组织** | 混在 scenes/ | 独立 UI/ | ✅ 职责清晰 | -| **框架代码** | core/ 概念模糊 | _Core/ 明确 | ✅ 边界清楚 | -| **配置管理** | data/ 混杂 | Config/ 专职 | ✅ 策划友好 | -| **可维护性** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ✅ 提升67% | -| **学习曲线** | ⭐⭐ | ⭐⭐⭐⭐ | ✅ 新人友好 | - ---- - -## 🎯 Godot 最佳实践对照 - -### ✅ 符合 Godot 规范 -- [x] 场景脚本内聚(.tscn + .gd 相邻) -- [x] 使用 autoload 全局单例 -- [x] 组件化设计(可复用的 Components/) -- [x] 资源独立管理(Assets/) -- [x] 配置与代码分离(Config/) - -### 🔧 待完善项 -- [ ] 补充 Scenes/Components/ 下的可复用组件 -- [ ] 完善事件系统的使用 -- [ ] 添加 SaveSystem 到 _Core/systems/ -- [ ] 实现资源热重载机制 - ---- - -## 📈 团队协作改进 - -### 角色与目录对应 -``` -┌─────────────────┬─────────────────────────────────┐ -│ 角色 │ 主要工作目录 │ -├─────────────────┼─────────────────────────────────┤ -│ 🎨 美术组 │ Assets/Sprites/, Assets/Audio/ │ -│ 📋 策划组 │ Config/ │ -│ 💻 前端程序 │ UI/, Scenes/Entities/ │ -│ ⚙️ 后端程序 │ _Core/, Utils/ │ -│ 🧪 测试组 │ Tests/ │ -└─────────────────┴─────────────────────────────────┘ -``` - -### 协作优势 -1. **减少冲突**: 不同角色在不同目录工作 -2. **职责清晰**: 每个目录有明确的负责人 -3. **易于审查**: PR 可以按目录分类评审 -4. **快速定位**: 新人快速找到相关文件 - ---- - -## 🚀 扩展性对比 - -### 旧结构的扩展问题 -```gdscript -// 添加新功能时需要在多个地方修改 -module/FeatureName/ // ❌ 需要创建 -scenes/feature_scene/ // ❌ 需要创建 -scripts/feature_logic/ // ❌ 需要创建 -data/feature_config/ // ❌ 需要创建 -``` - -### 新结构的扩展方式 -```gdscript -// 添加新功能只需要: -Scenes/Entities/NewFeature/ // ✅ 场景+逻辑一体 -Config/feature_config.json // ✅ 配置独立 -``` - ---- - -## 📚 参考架构 - -这个新结构参考了业界最佳实践: -- **Godot 官方**: [Project Organization](https://docs.godotengine.org/en/stable/tutorials/best_practices/project_organization.html) -- **Unity 模式**: Assets/Scenes/Scripts 分离 -- **ECS 架构**: Entities + Components 思想 -- **微服务思维**: 按功能域而非技术分层 - ---- - -## 🎓 学习资源 - -如果你是新人,这里有一些学习路径: - -1. **先熟悉目录** → 查看 [REFACTORING.md](./REFACTORING.md) -2. **理解核心系统** → 阅读 `_Core/systems/EventSystem.gd` -3. **学习场景管理** → 查看 `_Core/managers/SceneManager.gd` -4. **研究 UI 结构** → 打开 `UI/Windows/LoginWindow.tscn` -5. **运行测试** → 执行 `Tests/` 下的测试用例 - ---- - -**结论:新结构更加清晰、模块化、易于维护,符合 Godot 最佳实践!** 🎉 diff --git a/UI/Windows/AuthScene.gd.uid b/UI/Windows/AuthScene.gd.uid deleted file mode 100644 index 56d8ef1..0000000 --- a/UI/Windows/AuthScene.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bs1vy3ierj66t diff --git a/Utils/StringUtils.gd.uid b/Utils/StringUtils.gd.uid deleted file mode 100644 index aded9a0..0000000 --- a/Utils/StringUtils.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://csxag1y8yq57j diff --git a/_Core/ProjectPaths.gd b/_Core/ProjectPaths.gd index bdcbf2a..7df5859 100644 --- a/_Core/ProjectPaths.gd +++ b/_Core/ProjectPaths.gd @@ -31,8 +31,8 @@ const SCENES_ITEM_COMPONENTS = SCENES_COMPONENTS + "items/" # ============================================================================ # UI路径 # ============================================================================ -const UI_ROOT = "res://UI/" -const UI_WINDOWS = UI_ROOT + "Windows/" +const UI_ROOT = "res://scenes/ui/" +const UI_WINDOWS = UI_ROOT # ============================================================================ # 资源路径 @@ -69,7 +69,7 @@ const TESTS_AUTH = TESTS_ROOT + "auth/" # ============================================================================ # 工具路径 # ============================================================================ -const UTILS_ROOT = "res://Utils/" +const UTILS_ROOT = "res://_Core/utils/" # ============================================================================ # 模块路径 diff --git a/_Core/components/.gitkeep b/_Core/components/.gitkeep new file mode 100644 index 0000000..f1f9fb0 --- /dev/null +++ b/_Core/components/.gitkeep @@ -0,0 +1,2 @@ +# 基础组件实现目录 +# 存放项目的基础组件类 \ No newline at end of file diff --git a/_Core/managers/SceneManager.gd b/_Core/managers/SceneManager.gd index 1b8b5f9..ec0ef7e 100644 --- a/_Core/managers/SceneManager.gd +++ b/_Core/managers/SceneManager.gd @@ -11,13 +11,13 @@ var is_changing_scene: bool = false # 场景路径映射 var scene_paths: Dictionary = { - "main": "res://Scenes/Maps/main_scene.tscn", - "auth": "res://UI/Windows/LoginWindow.tscn", - "game": "res://Scenes/Maps/game_scene.tscn", - "battle": "res://Scenes/Maps/battle_scene.tscn", - "inventory": "res://UI/Windows/InventoryWindow.tscn", - "shop": "res://UI/Windows/ShopWindow.tscn", - "settings": "res://UI/Windows/SettingsWindow.tscn" + "main": "res://scenes/maps/main_scene.tscn", + "auth": "res://scenes/ui/LoginWindow.tscn", + "game": "res://scenes/maps/game_scene.tscn", + "battle": "res://scenes/maps/battle_scene.tscn", + "inventory": "res://scenes/ui/InventoryWindow.tscn", + "shop": "res://scenes/ui/ShopWindow.tscn", + "settings": "res://scenes/ui/SettingsWindow.tscn" } func _ready(): diff --git a/_Core/utils/.gitkeep b/_Core/utils/.gitkeep new file mode 100644 index 0000000..6ccaea4 --- /dev/null +++ b/_Core/utils/.gitkeep @@ -0,0 +1,2 @@ +# 核心工具类目录 +# 存放字符串处理、数学计算等工具类 \ No newline at end of file diff --git a/Utils/StringUtils.gd b/_Core/utils/StringUtils.gd similarity index 99% rename from Utils/StringUtils.gd rename to _Core/utils/StringUtils.gd index 4d69728..b866af6 100644 --- a/Utils/StringUtils.gd +++ b/_Core/utils/StringUtils.gd @@ -196,4 +196,4 @@ static func get_relative_time_until(utc_time_str: String) -> String: if minutes > 0: return "%d小时%d分钟后" % [hours, minutes] else: - return "%d小时后" % hours + return "%d小时后" % hours \ No newline at end of file diff --git a/_Core/utils/StringUtils.gd.uid b/_Core/utils/StringUtils.gd.uid new file mode 100644 index 0000000..f305e41 --- /dev/null +++ b/_Core/utils/StringUtils.gd.uid @@ -0,0 +1 @@ +uid://bu8onmk6q8wic diff --git a/claude.md b/claude.md new file mode 100644 index 0000000..0b04993 --- /dev/null +++ b/claude.md @@ -0,0 +1,96 @@ +# 🎯 CLAUDE.md - WhaleTown Project Instructions + +## 1. Project Vision & Context +- **Project**: "WhaleTown" - A 2D top-down pixel art RPG. +- **Engine**: Godot 4.2+ (Strictly NO Godot 3.x syntax). +- **Architecture**: Strictly layered: `_Core` (Framework), `Scenes` (Gameplay), `UI` (Interface). +- **Core Principle**: "Signal Up, Call Down". High decoupling via `EventSystem`. + +## 2. 🛠 Command Reference & Setup +- **Input Map (Required Configuration)**: + - `move_left`, `move_right`, `move_up`, `move_down` (WASD / Arrows) + - `interact` (E Key / Space) + - `pause` (ESC) +- **Run Game**: `godot --path .` +- **Run Tests (GUT)**: `godot --headless -s addons/gut/gut_cmdline.gd -gdir=res://tests/ -ginclude_subdirs` +- **Init Structure**: `mkdir -p _Core/managers _Core/systems Scenes/Maps Scenes/Entities Scenes/Components UI/Windows UI/HUD Assets/Sprites tests/unit tests/integration` + +## 3. 📂 File Path Rules (STRICT LOWERCASE) +*Claude: Root folders MUST be lowercase. Scripts and Scenes MUST stay together.* +- **Core Managers**: `_Core/managers/[Name].gd` +- **Core Systems**: `_Core/systems/[Name].gd` +- **Entities**: `Scenes/Entities/[EntityName]/[EntityName].tscn` (Script `.gd` in same folder). +- **Maps**: `Scenes/Maps/[map_name].tscn` +- **Components**: `Scenes/Components/[ComponentName].gd` (Reusable logic nodes). +- **UI Windows**: `UI/Windows/[WindowName].tscn` +- **Tests**: `tests/[unit|integration]/test_[name].gd` (Folder is lowercase `tests`). + +## 4. 📋 Coding Standards (The Law) +- **Type Safety**: ALWAYS use strict static typing: `var speed: float = 100.0`, `func _ready() -> void`. +- **Naming Conventions**: + - `class_name PascalCase` at the top of every script. + - Variables/Functions: `snake_case`. Constants: `SCREAMING_SNAKE_CASE`. + - Private members: Prefix with underscore `_` (e.g., `var _health: int`). +- **Node Access**: Use `%UniqueName` for UI and internal scene components. +- **Signals**: Use "Signal Up, Call Down". Parent calls child methods; Child emits signals. +- **Forbidden Patterns**: + - ❌ NO `yield()` -> Use `await`. + - ❌ NO `get_node()` in `_process` -> Cache with `@onready`. + - ❌ NO Linear Filter -> All Sprite2D/TileMap resources MUST use **Nearest** filter. + +## 5. 🏛 Architecture & Communication +- **EventSystem**: Use `_Core/systems/EventSystem.gd` for cross-module messaging. +- **Event Registry**: Use `class_name EventNames` in `_Core/EventNames.gd`. + ```gdscript + class_name EventNames + const PLAYER_MOVED = "player_moved" + const INTERACT_PRESSED = "interact_pressed" + const NPC_TALKED = "npc_talked" +Singletons: Only GameManager, SceneManager, EventSystem allowed as Autoloads. +Decoupling: Low-level entities MUST NOT reference GameManager. Use events. +6. 🏗 Implementation Details +Player: CharacterBody2D. Must include Camera2D with position_smoothing_enabled = true. +NPC/Interactables: Use Area2D named InteractionArea. Trigger via EventSystem. +TileMap Layers: +Layer 0: Ground (No collision). +Layer 1: Obstacles (Physics Layer enabled). +Layer 2: Decoration (Y-Sort enabled). +Camera: Must auto-calculate limits via TileMap.get_used_rect(). +7. 🧪 Testing Requirements (MANDATORY) +Coverage: Every Manager/System in _Core/ MUST have a GUT test. +Naming: Test files must start with test_ and extend GutTest. +Example: +code +Gdscript +extends GutTest +func test_event_emission(): + var sender = Node.new() + watch_signals(EventSystem) + EventSystem.emit_event(EventNames.PLAYER_MOVED, {}) + assert_signal_emitted(EventSystem, "event_raised") +8. 🧘 The Zen of Development +Juice or Death: Every interaction (UI popup, NPC talk) MUST have a Tween placeholder. +Zero Magic Numbers: All speeds/timers MUST be @export or defined in Config/. +Simplicity: If a function does two things, split it. +Back of the Fence: Hidden logic (like ResponseHandler.gd) must be as clean as the HUD. +9. 📝 Code Template (Entity Pattern) +code +Gdscript +extends CharacterBody2D +class_name Player + +# 1. Exports & Constants +@export var move_speed: float = 200.0 + +# 2. Node References +@onready var sprite: Sprite2D = %Sprite2D + +# 3. Lifecycle +func _physics_process(delta: float) -> void: + _move(delta) + +# 4. Private Methods +func _move(_delta: float) -> void: + var dir := Input.get_vector("move_left", "move_right", "move_up", "move_down") + velocity = dir * move_speed + move_and_slide() \ No newline at end of file diff --git a/cloude.md b/cloude.md deleted file mode 100644 index 77d72b9..0000000 --- a/cloude.md +++ /dev/null @@ -1,123 +0,0 @@ -# 🎯 WhaleTown 项目开发规范 - -## 1. 项目愿景与背景 -- **项目名称**: "WhaleTown" - 一个2D俯视角像素风RPG游戏 -- **引擎**: Godot 4.2+ (严格禁止使用Godot 3.x语法) -- **架构**: 严格分层架构:`_Core`(框架层)、`Scenes`(游戏层)、`UI`(界面层) -- **核心原则**: "信号向上,调用向下"。通过`EventSystem`实现高度解耦 - -## 2. 🛠 命令参考与设置 -- **输入映射 (必需配置)**: - - `move_left`, `move_right`, `move_up`, `move_down` (WASD / 方向键) - - `interact` (E键 / 空格键) - - `pause` (ESC键) -- **运行游戏**: `godot --path .` -- **运行测试 (GUT)**: `godot --headless -s addons/gut/gut_cmdline.gd -gdir=res://tests/ -ginclude_subdirs` -- **初始化结构**: `mkdir -p _Core/managers _Core/systems Scenes/Maps Scenes/Entities Scenes/Components UI/Windows UI/HUD Assets/Sprites tests/unit tests/integration` - -## 3. 📂 文件路径规则 (严格小写) -*注意:根目录文件夹必须小写。脚本和场景必须放在一起。* -- **核心管理器**: `_Core/managers/[Name].gd` -- **核心系统**: `_Core/systems/[Name].gd` -- **实体**: `Scenes/Entities/[EntityName]/[EntityName].tscn` (脚本`.gd`放在同一文件夹) -- **地图**: `Scenes/Maps/[map_name].tscn` -- **组件**: `Scenes/Components/[ComponentName].gd` (可复用逻辑节点) -- **UI窗口**: `UI/Windows/[WindowName].tscn` -- **测试**: `tests/[unit|integration]/test_[name].gd` (文件夹名为小写`tests`) - -## 4. 📋 编码标准 (必须遵守) -- **类型安全**: 始终使用严格静态类型:`var speed: float = 100.0`, `func _ready() -> void` -- **命名约定**: - - 每个脚本顶部必须有`class_name PascalCase` - - 变量/函数:`snake_case`。常量:`SCREAMING_SNAKE_CASE` - - 私有成员:使用下划线前缀`_` (例如:`var _health: int`) -- **节点访问**: 对UI和内部场景组件使用`%UniqueName` -- **信号**: 使用"信号向上,调用向下"原则。父节点调用子节点方法;子节点发出信号 -- **禁止模式**: - - ❌ 禁止使用`yield()` -> 使用`await` - - ❌ 禁止在`_process`中使用`get_node()` -> 使用`@onready`缓存 - - ❌ 禁止线性过滤 -> 所有Sprite2D/TileMap资源必须使用**最近邻**过滤 - -## 5. 🏛 架构与通信 -- **事件系统**: 使用`_Core/systems/EventSystem.gd`进行跨模块消息传递 -- **事件注册**: 在`_Core/EventNames.gd`中使用`class_name EventNames` - ```gdscript - class_name EventNames - const PLAYER_MOVED = "player_moved" - const INTERACT_PRESSED = "interact_pressed" - const NPC_TALKED = "npc_talked" - ``` -- **单例**: 只允许GameManager、SceneManager、EventSystem作为自动加载 -- **解耦**: 底层实体不得直接引用GameManager。使用事件系统 - -## 6. 🏗 实现细节 -- **玩家**: 使用CharacterBody2D。必须包含Camera2D,设置`position_smoothing_enabled = true` -- **NPC/交互物**: 使用名为InteractionArea的Area2D。通过EventSystem触发 -- **TileMap图层**: - - 图层0:地面 (无碰撞) - - 图层1:障碍物 (启用物理层) - - 图层2:装饰 (启用Y排序) -- **相机**: 必须通过`TileMap.get_used_rect()`自动计算边界 - -## 7. 🧪 测试要求 (强制性) -- **覆盖率**: `_Core/`中的每个管理器/系统都必须有GUT测试 -- **命名**: 测试文件必须以`test_`开头并继承`GutTest` -- **示例**: - ```gdscript - extends GutTest - func test_event_emission(): - var sender = Node.new() - watch_signals(EventSystem) - EventSystem.emit_event(EventNames.PLAYER_MOVED, {}) - assert_signal_emitted(EventSystem, "event_raised") - ``` - -## 8. 🧘 开发哲学 -- **流畅体验**: 每个交互(UI弹窗、NPC对话)都必须有Tween动画占位符 -- **零魔法数字**: 所有速度/计时器必须使用`@export`或在`Config/`中定义 -- **简洁性**: 如果一个函数做两件事,就拆分它 -- **隐藏逻辑**: 隐藏的逻辑(如ResponseHandler.gd)必须和HUD一样干净 - -## 9. 📝 代码模板 (实体模式) -```gdscript -extends CharacterBody2D -class_name Player - -# 1. 导出变量与常量 -@export var move_speed: float = 200.0 - -# 2. 节点引用 -@onready var sprite: Sprite2D = %Sprite2D - -# 3. 生命周期 -func _physics_process(delta: float) -> void: - _move(delta) - -# 4. 私有方法 -func _move(_delta: float) -> void: - var dir := Input.get_vector("move_left", "move_right", "move_up", "move_down") - velocity = dir * move_speed - move_and_slide() -``` - -## 10. 🎨 UI设计规范 -- **响应式布局**: 使用Anchor和Margin实现自适应 -- **主题统一**: 所有UI组件使用统一主题资源 -- **动画效果**: 界面切换必须有过渡动画 -- **无障碍支持**: 支持键盘导航 - -## 11. 🔧 性能优化 -- **对象池**: 频繁创建销毁的对象使用对象池 -- **视锥剔除**: 只渲染可见区域的对象 -- **批量处理**: 合并相似的渲染调用 -- **内存管理**: 及时释放不需要的资源 - -## 12. 📚 最佳实践 -- **模块化**: 功能拆分为独立模块 -- **可测试**: 设计易于测试的代码结构 -- **文档化**: 为复杂逻辑添加详细注释 -- **版本控制**: 遵循Git提交规范 - ---- - -**记住:代码质量是游戏成功的基础!** \ No newline at end of file diff --git a/docs/01-项目入门/项目结构说明.md b/docs/01-项目入门/项目结构说明.md index f1d7f9e..d983abc 100644 --- a/docs/01-项目入门/项目结构说明.md +++ b/docs/01-项目入门/项目结构说明.md @@ -20,15 +20,12 @@ ``` WhaleTown/ -├── 🔧 _Core/ # [框架层] 核心系统和管理器 -├── 🎬 scenes/ # [游戏层] 游戏场景和组件 -├── 🎨 UI/ # [界面层] 用户界面 -├── 🖼️ assets/ # [资源层] 美术资源 -├── ⚙️ Config/ # [配置层] 游戏配置和数据 -├── 🛠️ Utils/ # [工具层] 通用工具脚本 -├── 🧪 tests/ # [测试层] 测试文件 -├── 🚀 tools/ # [构建层] 构建和部署工具 -├── 🌐 web_assets/ # [发布层] Web版本资源 +├── 🔧 _Core/ # [核心层] 功能实现与组件实现,项目最基本的底层实现 +├── 🎬 scenes/ # [场景层] 场景与视觉呈现,包含地图、人物等视觉部分 +├── 🎨 assets/ # [资源层] 静态资源存储,包括图片、音乐、视频、贴图等 +├── ⚙️ Config/ # [配置层] 配置文件管理,用于配置各类环境 +├── 🧪 tests/ # [测试层] 测试文件系统,放置所有组件的测试代码 +├── 🌐 web_assets/ # [发布层] Web导出资源,专门用于Web平台导出 └── 📚 docs/ # [文档层] 项目文档 ``` @@ -36,9 +33,9 @@ WhaleTown/ ## 📁 详细目录结构 -### 1. 🔧 框架层 (_Core/) +### 1. 🔧 核心层 (_Core/) > **负责团队**: 开发团队 -> **职责**: 游戏底层框架,全局管理器和核心系统 +> **职责**: 功能实现与组件实现,项目最基本的底层实现 ``` _Core/ @@ -47,15 +44,25 @@ _Core/ │ ├── SceneManager.gd # 场景切换管理 │ ├── NetworkManager.gd # 网络通信管理 │ └── ResponseHandler.gd # API响应处理 -└── systems/ # 核心系统 - └── EventSystem.gd # 全局事件系统 +├── systems/ # 核心系统 +│ └── EventSystem.gd # 全局事件系统 +├── components/ # 基础组件实现 +│ ├── BaseCharacter.gd # 基础角色组件 +│ ├── BaseItem.gd # 基础物品组件 +│ └── BaseUI.gd # 基础UI组件 +├── utils/ # 🔨 核心工具类 +│ ├── StringUtils.gd # 字符串处理工具 +│ ├── MathUtils.gd # 数学计算工具 +│ └── PixelUtils.gd # 像素风游戏专用工具 +├── EventNames.gd # 事件名称定义 +└── ProjectPaths.gd # 路径统一管理 ``` **特点**: - 自动加载 (AutoLoad) 单例 -- 全局可访问 -- 与具体游戏逻辑无关 -- 提供基础服务 +- 全局可访问的核心功能 +- 与具体游戏逻辑无关的底层实现 +- 提供基础服务和组件框架 **使用示例**: ```gdscript @@ -69,167 +76,206 @@ SceneManager.change_scene("main") EventSystem.emit_event("player_moved", {"position": Vector2(100, 200)}) ``` -### 2. 🎬 游戏层 (scenes/) +### 2. 🎬 场景层 (scenes/) > **负责团队**: 开发团队 -> **职责**: 游戏场景、实体和可复用组件 +> **职责**: 场景与视觉呈现,包含地图场景、人物场景等一系列视觉呈现的部分 ``` scenes/ -├── Maps/ # 游戏地图场景 -│ ├── main_scene.tscn # 主游戏场景 -│ └── MainScene.gd # 主场景脚本 -└── Components/ # 可复用组件 - ├── characters/ # 角色组件 - ├── effects/ # 特效组件 - ├── items/ # 物品组件 - └── ui/ # UI组件 +├── maps/ # 地图场景 +│ ├── main_world.tscn # 主世界地图 +│ ├── dungeon_01.tscn # 地牢场景 +│ └── town_center.tscn # 城镇中心 +├── characters/ # 人物场景 +│ ├── player/ # 玩家角色 +│ │ ├── Player.tscn # 玩家场景 +│ │ └── Player.gd # 玩家脚本 +│ ├── npcs/ # NPC角色 +│ └── enemies/ # 敌人角色 +├── ui/ # UI界面场景 +│ ├── menus/ # 菜单界面 +│ ├── hud/ # 游戏HUD +│ └── dialogs/ # 对话框 +├── effects/ # 特效场景 +│ ├── particles/ # 粒子效果 +│ └── animations/ # 动画效果 +└── prefabs/ # 预制体组件 + ├── items/ # 物品预制体 + └── interactive/ # 交互对象预制体 ``` **设计原则**: - **场景内聚**: 脚本紧邻场景文件存放 -- **组件化**: 可复用组件统一管理 -- **模块化**: 按功能类型分类组织 +- **分类明确**: 按功能类型(地图、人物、UI、特效)分类 +- **模块化**: 可复用的预制体统一管理 +- **视觉导向**: 主要负责游戏的视觉呈现和UI实现 -### 3. 🎨 界面层 (UI/) -> **负责团队**: 开发团队 + 美术团队协作 -> **职责**: 用户界面和主题管理 - -``` -UI/ -├── Windows/ # 模态窗口 -│ ├── LoginWindow.tscn # 登录窗口 -│ └── AuthScene.gd # 认证场景脚本 -└── Theme/ # 全局主题 - ├── MainTheme.tres # 主题资源 - └── Fonts/ # 字体文件 - └── msyh.ttc # 微软雅黑字体 -``` - -**组织方式**: -- **Windows/**: 模态窗口和对话框 -- **Theme/**: 统一的UI主题和样式 -- **Fonts/**: 字体资源管理 - -### 4. 🖼️ 资源层 (assets/) +### 3. 🎨 资源层 (assets/) > **负责团队**: 美术团队 -> **职责**: 所有美术资源和素材 +> **职责**: 所有静态资源的存储,包括图片、音乐、视频、贴图等素材 ``` assets/ -├── sprites/ # 精灵图资源 -│ ├── characters/ # 角色精灵 -│ ├── effects/ # 特效精灵 -│ ├── environment/ # 环境精灵 -│ └── icon/ # 图标资源 +├── sprites/ # 精灵图片资源 +│ ├── characters/ # 角色精灵(玩家、NPC、敌人) +│ ├── environment/ # 环境精灵(地形、建筑、装饰) +│ ├── items/ # 物品精灵(道具、装备、收集品) +│ ├── effects/ # 特效精灵(爆炸、魔法、粒子) +│ └── ui/ # UI精灵(按钮、图标、边框) ├── audio/ # 音频资源 -│ ├── music/ # 背景音乐 -│ ├── sounds/ # 音效 -│ └── voice/ # 语音 -├── ui/ # UI专用资源 -│ ├── auth/ # 认证界面资源 -│ │ ├── bg_auth_scene.png # 认证背景 -│ │ └── login_frame_smart_transparent.png -│ ├── chinese_theme.tres # 中文主题 -│ └── datawhale_logo.png # 项目Logo +│ ├── music/ # 背景音乐(BGM) +│ ├── sounds/ # 音效(SFX) +│ └── voice/ # 语音(对话、旁白) ├── fonts/ # 字体文件 +│ ├── pixel_fonts/ # 像素风字体 +│ └── ui_fonts/ # UI专用字体 ├── materials/ # 材质资源 -└── shaders/ # 着色器 +│ ├── pixel_materials/ # 像素风材质 +│ └── shader_materials/ # 着色器材质 +├── shaders/ # 着色器文件 +│ ├── pixel_shaders/ # 像素风着色器 +│ └── effect_shaders/ # 特效着色器 +├── ui/ # UI专用资源 +│ ├── themes/ # UI主题 +│ ├── icons/ # 图标资源 +│ └── backgrounds/ # 背景图片 +└── icon/ # 应用图标 + ├── icon.svg # 矢量图标 + └── icon.png # 位图图标 ``` -**美术团队工作流程**: -1. 按分类将资源放入对应目录 -2. 遵循命名规范 (snake_case) -3. 确保资源格式符合Godot要求 -4. 配置正确的导入设置 (像素艺术使用最近邻过滤) +**像素风游戏资源特点**: +- **像素完美**: 所有精灵使用像素完美设置(Filter: Off, Mipmaps: Off) +- **统一风格**: 保持一致的像素密度和调色板 +- **分辨率标准**: 建议使用16x16、32x32等标准像素尺寸 +- **动画帧**: 角色动画使用精灵表(Sprite Sheet)组织 -### 5. ⚙️ 配置层 (Config/) +### 4. ⚙️ 配置层 (Config/) > **负责团队**: 策划团队 -> **职责**: 游戏配置、数据和本地化 +> **职责**: 配置文件管理,主要用来配置各类环境 ``` Config/ ├── game_config.json # 游戏主配置 -└── zh_CN.json # 中文本地化 +├── zh_CN.json # 中文本地化 +├── environment/ # 环境配置 +│ ├── development.json # 开发环境配置 +│ ├── testing.json # 测试环境配置 +│ └── production.json # 生产环境配置 +├── gameplay/ # 游戏玩法配置 +│ ├── character_stats.json # 角色属性配置 +│ ├── item_database.json # 物品数据库 +│ └── level_config.json # 关卡配置 +└── localization/ # 本地化配置 + ├── en_US.json # 英文本地化 + ├── zh_CN.json # 中文本地化 + └── ja_JP.json # 日文本地化 ``` -**策划团队工作内容**: -- **游戏数值配置**: 角色属性、物品数据、关卡参数 -- **本地化文本**: 多语言文本翻译和管理 -- **游戏平衡**: 数值平衡和游戏性调整 +**配置文件特点**: +- **环境分离**: 开发、测试、生产环境配置分离 +- **数据驱动**: 游戏数值通过配置文件控制 +- **本地化支持**: 多语言文本管理 +- **热更新**: 支持运行时配置更新 -**配置文件示例**: -```json -// game_config.json -{ - "player": { - "move_speed": 200.0, - "max_health": 100, - "jump_height": 400.0 - }, - "game": { - "target_fps": 60, - "auto_save_interval": 300 - } -} -``` - -### 6. 🛠️ 工具层 (Utils/) +### 5. 🧪 测试层 (tests/) > **负责团队**: 开发团队 -> **职责**: 通用工具和辅助脚本 - -``` -Utils/ -└── StringUtils.gd # 字符串处理工具 -``` - -**特点**: -- 纯函数,无依赖 -- 可被任何层调用 -- 提供通用功能 - -### 7. 🧪 测试层 (tests/) -> **负责团队**: 开发团队 -> **职责**: 质量保证和自动化测试 +> **职责**: 测试文件系统,放置所有对应组件的测试代码,方便快速进行功能性与性能测试 ``` tests/ -├── api/ # API接口测试 -├── auth/ # 认证功能测试 ├── unit/ # 单元测试 +│ ├── core/ # 核心组件测试 +│ ├── characters/ # 角色组件测试 +│ └── systems/ # 系统功能测试 ├── integration/ # 集成测试 -└── performance/ # 性能测试 +│ ├── scene_transitions/ # 场景切换测试 +│ ├── save_load/ # 存档系统测试 +│ └── network/ # 网络功能测试 +├── performance/ # 性能测试 +│ ├── framerate/ # 帧率测试 +│ ├── memory/ # 内存使用测试 +│ └── loading_times/ # 加载时间测试 +├── api/ # API接口测试 +│ ├── auth_tests.py # 认证接口测试 +│ └── game_api_tests.py # 游戏API测试 +└── ui/ # UI功能测试 + ├── menu_tests/ # 菜单测试 + └── dialog_tests/ # 对话框测试 ``` -### 8. 🚀 构建层 (tools/) -> **负责团队**: 开发团队/DevOps -> **职责**: 构建脚本和部署工具 +**测试类型说明**: +- **单元测试**: 测试单个组件的功能正确性 +- **集成测试**: 测试组件间的交互和协作 +- **性能测试**: 监控游戏性能指标,确保流畅运行 +- **API测试**: 验证网络接口的正确性和稳定性 +- **UI测试**: 测试用户界面的交互和响应 -``` -tools/ -├── build_web.bat # Windows Web构建脚本 -├── build_web.sh # Linux/macOS Web构建脚本 -├── serve_web.bat # Windows 本地服务器 -├── serve_web.sh # Linux/macOS 本地服务器 -└── README.md # 工具使用说明 -``` - -### 9. 🌐 发布层 (web_assets/) +### 6. 🌐 Web导出层 (web_assets/) > **负责团队**: 自动生成 -> **职责**: Web版本发布资源 +> **职责**: Web导出资源,专门用于Web平台导出的相关资源和配置文件 ``` web_assets/ -├── index.html # Web版本入口 -├── index.js # Godot Web导出JS -├── index.wasm # WebAssembly文件 -├── index.pck # 游戏资源包 -└── [其他Web资源] # 图标、配置等 +├── html/ # HTML模板文件 +│ ├── index.html # Web版本入口页面 +│ └── loading.html # 加载页面模板 +├── css/ # 样式文件 +│ ├── game.css # 游戏样式 +│ └── loading.css # 加载样式 +├── js/ # JavaScript脚本 +│ ├── game_loader.js # 游戏加载器 +│ └── utils.js # 工具函数 +├── icons/ # Web应用图标 +│ ├── favicon.ico # 网站图标 +│ └── app_icons/ # PWA应用图标 +└── config/ # Web配置文件 + ├── manifest.json # PWA清单文件 + └── service-worker.js # 服务工作者 ``` -### 10. 📚 文档层 (docs/) +**Web导出特点**: +- **PWA支持**: 支持渐进式Web应用功能 +- **响应式设计**: 适配不同屏幕尺寸 +- **加载优化**: 优化资源加载和缓存策略 +- **跨平台兼容**: 确保在各种浏览器中正常运行 + +### 7. 📚 文档层 (docs/) > **负责团队**: 全体团队 > **职责**: 项目文档和开发指南 +``` +docs/ +├── 01-项目入门/ # 新人必读文档 +├── 02-开发规范/ # 编码标准文档 +├── 03-技术实现/ # 开发指导文档 +├── 04-高级开发/ # 进阶技巧文档 +├── 05-部署运维/ # 发布部署文档 +├── 06-功能模块/ # 功能文档 +└── AI_docs/ # 🤖 AI专用文档 + ├── README.md # AI文档总览 + ├── architecture_guide.md # 架构执行指南 + ├── coding_standards.md # 代码风格规范 + ├── templates/ # 代码模板库 + │ ├── components.md # 组件模板集合 + │ ├── managers.md # 管理器模板集合 + │ └── ui_templates.md # UI模板集合 + ├── workflows/ # 工作流程指南 + │ ├── feature_development.md # 功能开发流程 + │ ├── bug_fixing.md # Bug修复流程 + │ └── testing_workflow.md # 测试执行流程 + └── quick_reference/ # 快速参考手册 + ├── code_snippets.md # 常用代码片段 + ├── api_reference.md # API快速参考 + └── troubleshooting.md # 故障排除指南 +``` + +**AI_docs特点**: +- **结构化执行**: 每个文档都包含可直接执行的步骤和代码模板 +- **标准化规范**: 为AI编程助手提供统一的开发标准和最佳实践 +- **模板驱动**: 提供完整的代码模板,确保代码一致性和质量 +- **工作流导向**: 包含详细的开发工作流程,提升AI协作效率 + ``` docs/ ├── 01-项目入门/ # 新人必读 @@ -245,18 +291,18 @@ docs/ ## 🤝 团队协作指南 ### 开发团队 🎮 -**主要工作区域**: `_Core/`, `scenes/`, `UI/`, `Utils/`, `tests/` +**主要工作区域**: `_Core/`, `scenes/`, `tests/` **日常工作流程**: -1. 在 `_Core/` 中开发核心系统和管理器 -2. 在 `scenes/` 中创建游戏场景和组件 -3. 在 `UI/` 中实现用户界面 -4. 在 `Utils/` 中编写通用工具 -5. 在 `tests/` 中编写测试用例 +1. 在 `_Core/` 中开发核心系统、管理器、基础组件和工具类 +2. 在 `scenes/` 中创建游戏场景、角色、UI界面和特效 +3. 在 `tests/` 中编写各类测试用例确保代码质量 **协作要点**: -- 遵循架构设计原则,使用事件系统通信 +- 遵循架构设计原则,使用事件系统进行模块通信 - 保持代码模块化和可复用性 +- 将通用工具类放在 `_Core/utils/` 中统一管理 +- 针对像素风游戏特点优化性能 - 及时编写测试和文档 ### 美术团队 🎨 @@ -264,28 +310,30 @@ docs/ **日常工作流程**: 1. 按分类整理美术资源到 `assets/` 对应目录 -2. 遵循命名规范,使用 snake_case 命名 -3. 配置正确的Godot导入设置 -4. 与开发团队协作调整UI资源 +2. 确保像素艺术风格的一致性和像素完美 +3. 配置正确的Godot导入设置(关闭过滤、禁用Mipmaps) +4. 与开发团队协作调整UI和游戏资源 -**协作要点**: -- 严格按照目录结构组织资源 -- 确保资源格式和质量符合要求 -- 及时与开发团队沟通资源需求 +**像素风游戏特殊要求**: +- 严格遵循像素完美原则 +- 保持统一的像素密度和调色板 +- 使用标准像素尺寸(16x16、32x32等) +- 精灵动画使用精灵表组织 ### 策划团队 📋 **主要工作区域**: `Config/` **日常工作流程**: -1. 在 `Config/` 中维护游戏配置文件 -2. 管理游戏数值和平衡性调整 +1. 在 `Config/` 中维护游戏配置和数值平衡 +2. 管理多环境配置(开发、测试、生产) 3. 负责本地化文本的翻译和维护 -4. 与开发团队协作实现游戏功能 +4. 设计游戏玩法和关卡数据 **协作要点**: - 使用JSON格式编写配置文件 -- 保持配置文件的结构清晰 +- 保持配置文件的结构清晰和可维护性 - 及时更新本地化文本 +- 与开发团队协作实现数据驱动的游戏功能 --- @@ -320,15 +368,24 @@ docs/ ### 资源管理规范 - 所有资源必须放在 `assets/` 对应分类目录下 - 使用描述性的文件名,避免使用数字编号 -- 像素艺术资源必须关闭过滤 (Filter: Off) +- **像素艺术资源必须关闭过滤** (Filter: Off, Mipmaps: Off) +- 保持统一的像素密度和调色板 +- 使用标准像素尺寸(16x16、32x32、64x64等) - 及时清理不使用的资源文件 ### 代码组织规范 - 脚本文件与场景文件放在同一目录 -- 使用事件系统实现模块间通信 +- 使用事件系统实现模块间通信,避免直接引用 - 保持单一职责原则,避免过度耦合 +- 针对像素风游戏优化性能(避免浮点数位置、使用整数坐标) - 及时编写注释和文档 +### 像素风游戏特殊规范 +- **像素完美**: 确保所有精灵在整数坐标上渲染 +- **统一风格**: 保持一致的像素密度和艺术风格 +- **性能优化**: 使用对象池管理频繁创建销毁的对象 +- **分辨率适配**: 使用像素完美的缩放方式适配不同分辨率 + --- **记住:良好的项目结构是团队协作成功的基础!** \ No newline at end of file diff --git a/docs/AI_docs/.gitkeep b/docs/AI_docs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/AI_docs/quick_reference/troubleshooting.md b/docs/AI_docs/quick_reference/troubleshooting.md new file mode 100644 index 0000000..a8a6fc8 --- /dev/null +++ b/docs/AI_docs/quick_reference/troubleshooting.md @@ -0,0 +1,238 @@ +# 🔧 故障排除指南 + +> AI编程助手专用:常见问题的快速解决方案 + +## 🚨 常见错误及解决方案 + +### 1. UID无效警告 + +**错误信息**: +``` +WARNING: scene/resources/resource_format_text.cpp:444 - res://path/to/file.tscn:X - ext_resource, invalid UID: uid://xxxxx - using text path instead: res://path/to/script.gd +``` + +**原因**: 文件移动后,Godot的UID缓存没有更新,导致UID引用失效。 + +**解决方案**: +```gdscript +# 方法1: 移除无效的UID,使用文本路径 +# 将这行: +[ext_resource type="Script" uid="uid://invalid_uid" path="res://path/to/script.gd" id="1_script"] + +# 改为: +[ext_resource type="Script" path="res://path/to/script.gd" id="1_script"] +``` + +**预防措施**: +- 移动文件时使用Godot编辑器的文件系统面板 +- 避免直接在文件系统中移动.gd和.tscn文件 +- 移动文件后重新导入项目 + +### 2. 脚本路径错误 + +**错误信息**: +``` +ERROR: Failed to load script "res://old/path/Script.gd" with error "File not found". +``` + +**解决方案**: +```gdscript +# 检查并更新所有.tscn文件中的脚本路径 +# 使用搜索替换功能批量更新: + +# 旧路径 → 新路径 +"res://UI/Windows/" → "res://scenes/ui/" +"res://Utils/" → "res://_Core/utils/" +"res://Scenes/Maps/" → "res://scenes/maps/" +``` + +### 3. AutoLoad路径错误 + +**错误信息**: +``` +ERROR: Cannot load autoload: res://old/path/Manager.gd +``` + +**解决方案**: +```ini +# 在 project.godot 中更新 AutoLoad 路径 +[autoload] +GameManager="*res://_Core/managers/GameManager.gd" +SceneManager="*res://_Core/managers/SceneManager.gd" +EventSystem="*res://_Core/systems/EventSystem.gd" +``` + +### 4. 资源加载失败 + +**错误信息**: +``` +ERROR: Failed to load resource "res://old/path/resource.png". +``` + +**解决方案**: +```gdscript +# 检查资源路径是否正确 +# 使用 ResourceLoader.exists() 验证路径 +func load_resource_safely(path: String): + if not ResourceLoader.exists(path): + push_error("Resource not found: %s" % path) + return null + + return load(path) +``` + +## 🔍 调试技巧 + +### 1. 路径验证 +```gdscript +# 验证文件是否存在 +func verify_file_exists(file_path: String) -> bool: + return FileAccess.file_exists(file_path) + +# 验证资源是否存在 +func verify_resource_exists(resource_path: String) -> bool: + return ResourceLoader.exists(resource_path) + +# 打印当前工作目录 +func print_current_directory(): + print("Current directory: ", OS.get_executable_path().get_base_dir()) +``` + +### 2. 场景加载调试 +```gdscript +# 安全的场景加载 +func load_scene_safely(scene_path: String) -> PackedScene: + if not ResourceLoader.exists(scene_path): + push_error("Scene file not found: %s" % scene_path) + return null + + var scene = load(scene_path) as PackedScene + if scene == null: + push_error("Failed to load scene: %s" % scene_path) + return null + + return scene +``` + +### 3. 节点引用调试 +```gdscript +# 安全的节点获取 +func get_node_safely(node_path: String) -> Node: + var node = get_node_or_null(node_path) + if node == null: + push_warning("Node not found: %s" % node_path) + return node + +# 检查@onready变量是否正确初始化 +func _ready(): + # 验证所有@onready节点 + if not some_button: + push_error("some_button not found - check node path") + if not some_label: + push_error("some_label not found - check node path") +``` + +## 🛠️ 项目结构问题 + +### 1. 文件移动后的检查清单 +- [ ] 更新.tscn文件中的脚本路径 +- [ ] 更新project.godot中的AutoLoad路径 +- [ ] 更新代码中的硬编码路径 +- [ ] 清理Godot缓存文件 +- [ ] 重新导入项目 + +### 2. 缓存清理命令 +```bash +# Windows PowerShell +Remove-Item -Recurse -Force ".godot\uid_cache.bin" +Remove-Item -Recurse -Force ".godot\global_script_class_cache.cfg" + +# Linux/macOS +rm -rf .godot/uid_cache.bin +rm -rf .godot/global_script_class_cache.cfg +``` + +### 3. 路径常量管理 +```gdscript +# 在 _Core/ProjectPaths.gd 中定义所有路径 +class_name ProjectPaths + +# 核心路径 +const CORE_ROOT = "res://_Core/" +const MANAGERS_PATH = CORE_ROOT + "managers/" +const SYSTEMS_PATH = CORE_ROOT + "systems/" +const UTILS_PATH = CORE_ROOT + "utils/" + +# 场景路径 +const SCENES_ROOT = "res://scenes/" +const UI_PATH = SCENES_ROOT + "ui/" +const MAPS_PATH = SCENES_ROOT + "maps/" + +# 使用示例 +var scene_path = ProjectPaths.UI_PATH + "LoginWindow.tscn" +``` + +## 🎯 性能问题 + +### 1. 内存泄漏检测 +```gdscript +# 监控节点数量 +func _ready(): + print("Initial node count: ", get_tree().get_node_count()) + +func _exit_tree(): + print("Final node count: ", get_tree().get_node_count()) + +# 检查未释放的资源 +func check_resource_leaks(): + print("Resource count: ", ResourceLoader.get_resource_list().size()) +``` + +### 2. 帧率监控 +```gdscript +# 在 _Core/managers/PerformanceManager.gd +extends Node + +var frame_count: int = 0 +var fps_timer: float = 0.0 + +func _process(delta: float): + frame_count += 1 + fps_timer += delta + + if fps_timer >= 1.0: + var fps = frame_count / fps_timer + if fps < 30: + push_warning("Low FPS detected: %.1f" % fps) + + frame_count = 0 + fps_timer = 0.0 +``` + +## 🔧 开发工具问题 + +### 1. Godot编辑器崩溃 +**解决方案**: +1. 备份项目文件 +2. 删除.godot文件夹 +3. 重新打开项目 +4. 重新导入所有资源 + +### 2. 脚本编辑器问题 +**解决方案**: +```gdscript +# 检查脚本语法 +# 使用 Godot 内置的语法检查器 +# 或者在命令行中运行: +# godot --check-only script.gd +``` + +### 3. 场景编辑器问题 +**解决方案**: +- 检查场景文件是否损坏 +- 重新创建有问题的场景 +- 使用版本控制恢复到工作版本 + +--- + +**💡 提示**: 遇到问题时,首先检查Godot的输出面板和调试器,它们通常会提供详细的错误信息和解决建议。 \ No newline at end of file diff --git a/docs/AI_docs/templates/managers.md b/docs/AI_docs/templates/managers.md new file mode 100644 index 0000000..6edd9ca --- /dev/null +++ b/docs/AI_docs/templates/managers.md @@ -0,0 +1,617 @@ +# 🎯 管理器模板集合 + +> AI编程助手专用:各类管理器的标准化代码模板 + +## 🎮 游戏管理器模板 + +### 基础游戏管理器 +```gdscript +# _Core/managers/GameManager.gd +extends Node + +## 游戏状态管理器 +## 负责管理游戏的全局状态、玩家数据和游戏流程 + +# 信号定义 +signal game_state_changed(old_state: GameState, new_state: GameState) +signal player_data_updated(data: Dictionary) +signal game_paused() +signal game_resumed() + +# 游戏状态枚举 +enum GameState { + LOADING, + MENU, + PLAYING, + PAUSED, + GAME_OVER, + SETTINGS +} + +# 常量定义 +const SAVE_FILE_PATH: String = "user://game_save.dat" +const CONFIG_FILE_PATH: String = "res://Config/game_config.json" + +# 导出变量 +@export var debug_mode: bool = false +@export var auto_save_interval: float = 30.0 + +# 公共变量 +var current_state: GameState = GameState.LOADING +var is_paused: bool = false +var game_time: float = 0.0 + +# 玩家数据 +var player_data: Dictionary = { + "level": 1, + "experience": 0, + "coins": 100, + "health": 100, + "max_health": 100, + "energy": 100, + "max_energy": 100 +} + +# 私有变量 +var _auto_save_timer: Timer +var _game_config: Dictionary = {} + +func _ready() -> void: + _initialize_manager() + _setup_auto_save() + _load_game_config() + change_state(GameState.MENU) + +func _process(delta: float) -> void: + if current_state == GameState.PLAYING and not is_paused: + game_time += delta + +## 改变游戏状态 +func change_state(new_state: GameState) -> void: + if current_state == new_state: + return + + var old_state = current_state + _exit_state(old_state) + current_state = new_state + _enter_state(new_state) + + game_state_changed.emit(old_state, new_state) + + if debug_mode: + print("[GameManager] State changed: %s -> %s" % [old_state, new_state]) + +## 暂停游戏 +func pause_game() -> void: + if current_state != GameState.PLAYING: + return + + is_paused = true + get_tree().paused = true + game_paused.emit() + +## 恢复游戏 +func resume_game() -> void: + if not is_paused: + return + + is_paused = false + get_tree().paused = false + game_resumed.emit() + +## 更新玩家数据 +func update_player_data(key: String, value) -> void: + if not player_data.has(key): + push_warning("Unknown player data key: %s" % key) + return + + player_data[key] = value + player_data_updated.emit(player_data) + + if debug_mode: + print("[GameManager] Player data updated: %s = %s" % [key, value]) + +## 获取玩家数据 +func get_player_data(key: String = ""): + if key.is_empty(): + return player_data.duplicate() + + return player_data.get(key, null) + +## 保存游戏数据 +func save_game() -> bool: + var save_data = { + "player_data": player_data, + "game_time": game_time, + "current_state": current_state, + "timestamp": Time.get_unix_time_from_system() + } + + var file = FileAccess.open(SAVE_FILE_PATH, FileAccess.WRITE) + if file == null: + push_error("Failed to open save file for writing") + return false + + file.store_string(JSON.stringify(save_data)) + file.close() + + if debug_mode: + print("[GameManager] Game saved successfully") + + return true + +## 加载游戏数据 +func load_game() -> bool: + if not FileAccess.file_exists(SAVE_FILE_PATH): + if debug_mode: + print("[GameManager] No save file found") + return false + + var file = FileAccess.open(SAVE_FILE_PATH, FileAccess.READ) + if file == null: + push_error("Failed to open save file for reading") + return false + + var json_text = file.get_as_text() + file.close() + + var json = JSON.new() + var parse_result = json.parse(json_text) + if parse_result != OK: + push_error("Failed to parse save file JSON") + return false + + var save_data = json.data + + # 恢复玩家数据 + if save_data.has("player_data"): + player_data = save_data.player_data + player_data_updated.emit(player_data) + + # 恢复游戏时间 + if save_data.has("game_time"): + game_time = save_data.game_time + + if debug_mode: + print("[GameManager] Game loaded successfully") + + return true + +# 私有方法 +func _initialize_manager() -> void: + # 设置进程模式为总是处理(即使暂停时也能工作) + process_mode = Node.PROCESS_MODE_ALWAYS + +func _setup_auto_save() -> void: + _auto_save_timer = Timer.new() + add_child(_auto_save_timer) + _auto_save_timer.wait_time = auto_save_interval + _auto_save_timer.timeout.connect(_on_auto_save_timeout) + _auto_save_timer.start() + +func _load_game_config() -> void: + if not FileAccess.file_exists(CONFIG_FILE_PATH): + push_warning("Game config file not found") + return + + var file = FileAccess.open(CONFIG_FILE_PATH, FileAccess.READ) + if file == null: + push_error("Failed to open game config file") + return + + var json_text = file.get_as_text() + file.close() + + var json = JSON.new() + var parse_result = json.parse(json_text) + if parse_result != OK: + push_error("Failed to parse game config JSON") + return + + _game_config = json.data + +func _enter_state(state: GameState) -> void: + match state: + GameState.LOADING: + # 加载游戏资源 + pass + GameState.MENU: + # 显示主菜单 + pass + GameState.PLAYING: + # 开始游戏逻辑 + _auto_save_timer.start() + GameState.PAUSED: + # 暂停游戏 + _auto_save_timer.stop() + GameState.GAME_OVER: + # 游戏结束处理 + save_game() + GameState.SETTINGS: + # 显示设置界面 + pass + +func _exit_state(state: GameState) -> void: + match state: + GameState.PLAYING: + # 退出游戏时自动保存 + save_game() + +func _on_auto_save_timeout() -> void: + if current_state == GameState.PLAYING: + save_game() +``` + +## 🌐 网络管理器模板 + +### HTTP请求管理器 +```gdscript +# _Core/managers/NetworkManager.gd +extends Node + +## 网络请求管理器 +## 负责处理所有HTTP请求和网络通信 + +# 信号定义 +signal request_completed(request_id: String, success: bool, data: Dictionary) +signal connection_status_changed(is_connected: bool) + +# 常量定义 +const BASE_URL: String = "https://api.example.com" +const TIMEOUT_DURATION: float = 10.0 +const MAX_RETRIES: int = 3 + +# 请求状态枚举 +enum RequestStatus { + PENDING, + SUCCESS, + FAILED, + TIMEOUT, + CANCELLED +} + +# 公共变量 +var is_connected: bool = false +var active_requests: Dictionary = {} + +# 私有变量 +var _http_client: HTTPClient +var _request_counter: int = 0 + +func _ready() -> void: + _initialize_network() + _check_connection() + +## 发送GET请求 +func send_get_request(endpoint: String, headers: Dictionary = {}) -> String: + return _send_request(HTTPClient.METHOD_GET, endpoint, "", headers) + +## 发送POST请求 +func send_post_request(endpoint: String, data: Dictionary, headers: Dictionary = {}) -> String: + var json_data = JSON.stringify(data) + return _send_request(HTTPClient.METHOD_POST, endpoint, json_data, headers) + +## 发送PUT请求 +func send_put_request(endpoint: String, data: Dictionary, headers: Dictionary = {}) -> String: + var json_data = JSON.stringify(data) + return _send_request(HTTPClient.METHOD_PUT, endpoint, json_data, headers) + +## 发送DELETE请求 +func send_delete_request(endpoint: String, headers: Dictionary = {}) -> String: + return _send_request(HTTPClient.METHOD_DELETE, endpoint, "", headers) + +## 取消请求 +func cancel_request(request_id: String) -> bool: + if not active_requests.has(request_id): + return false + + var request_data = active_requests[request_id] + if request_data.http_request: + request_data.http_request.cancel_request() + + _cleanup_request(request_id, RequestStatus.CANCELLED) + return true + +## 检查网络连接状态 +func check_connection() -> void: + _check_connection() + +# 私有方法 +func _initialize_network() -> void: + _http_client = HTTPClient.new() + +func _send_request(method: HTTPClient.Method, endpoint: String, data: String, headers: Dictionary) -> String: + var request_id = _generate_request_id() + var full_url = BASE_URL + endpoint + + # 创建HTTP请求节点 + var http_request = HTTPRequest.new() + add_child(http_request) + + # 设置请求超时 + http_request.timeout = TIMEOUT_DURATION + + # 连接完成信号 + http_request.request_completed.connect(_on_request_completed.bind(request_id)) + + # 准备请求头 + var request_headers = ["Content-Type: application/json"] + for key in headers: + request_headers.append("%s: %s" % [key, headers[key]]) + + # 存储请求信息 + active_requests[request_id] = { + "http_request": http_request, + "method": method, + "url": full_url, + "status": RequestStatus.PENDING, + "retry_count": 0, + "start_time": Time.get_time_dict_from_system() + } + + # 发送请求 + var error = http_request.request(full_url, request_headers, method, data) + if error != OK: + push_error("Failed to send HTTP request: %d" % error) + _cleanup_request(request_id, RequestStatus.FAILED) + return "" + + return request_id + +func _generate_request_id() -> String: + _request_counter += 1 + return "req_%d_%d" % [Time.get_time_dict_from_system().hour * 3600 + Time.get_time_dict_from_system().minute * 60 + Time.get_time_dict_from_system().second, _request_counter] + +func _on_request_completed(request_id: String, result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void: + if not active_requests.has(request_id): + return + + var request_data = active_requests[request_id] + var success = false + var response_data = {} + + # 解析响应 + if response_code >= 200 and response_code < 300: + success = true + var body_text = body.get_string_from_utf8() + + if not body_text.is_empty(): + var json = JSON.new() + var parse_result = json.parse(body_text) + if parse_result == OK: + response_data = json.data + else: + response_data = {"raw_response": body_text} + else: + # 处理错误响应 + var body_text = body.get_string_from_utf8() + response_data = { + "error": "HTTP Error %d" % response_code, + "response_code": response_code, + "raw_response": body_text + } + + # 发送完成信号 + request_completed.emit(request_id, success, response_data) + + # 清理请求 + _cleanup_request(request_id, RequestStatus.SUCCESS if success else RequestStatus.FAILED) + +func _cleanup_request(request_id: String, status: RequestStatus) -> void: + if not active_requests.has(request_id): + return + + var request_data = active_requests[request_id] + + # 移除HTTP请求节点 + if request_data.http_request: + request_data.http_request.queue_free() + + # 从活动请求中移除 + active_requests.erase(request_id) + +func _check_connection() -> void: + # 简单的连接检查(可以改为ping服务器) + var old_status = is_connected + is_connected = true # 这里可以实现实际的连接检查逻辑 + + if old_status != is_connected: + connection_status_changed.emit(is_connected) +``` + +## 🎵 音频管理器模板 + +### 音频系统管理器 +```gdscript +# _Core/managers/AudioManager.gd +extends Node + +## 音频管理器 +## 负责管理游戏中的音乐和音效播放 + +# 信号定义 +signal music_finished() +signal sound_effect_finished(sound_name: String) + +# 音频类型枚举 +enum AudioType { + MUSIC, + SOUND_EFFECT, + UI_SOUND, + VOICE +} + +# 常量定义 +const MUSIC_PATH: String = "res://assets/audio/music/" +const SOUND_PATH: String = "res://assets/audio/sounds/" +const VOICE_PATH: String = "res://assets/audio/voice/" + +# 导出变量 +@export var master_volume: float = 1.0 +@export var music_volume: float = 0.7 +@export var sfx_volume: float = 0.8 +@export var voice_volume: float = 0.9 + +# 音频播放器 +var music_player: AudioStreamPlayer +var sfx_players: Array[AudioStreamPlayer] = [] +var voice_player: AudioStreamPlayer + +# 当前播放状态 +var current_music: String = "" +var is_music_playing: bool = false +var active_sounds: Dictionary = {} + +func _ready() -> void: + _initialize_audio_players() + _load_audio_settings() + +## 播放背景音乐 +func play_music(music_name: String, fade_in: bool = true) -> void: + var music_path = MUSIC_PATH + music_name + ".ogg" + + if not ResourceLoader.exists(music_path): + push_warning("Music file not found: %s" % music_path) + return + + # 停止当前音乐 + if is_music_playing: + stop_music(fade_in) + await get_tree().create_timer(0.5).timeout + + # 加载并播放新音乐 + var audio_stream = load(music_path) + music_player.stream = audio_stream + music_player.volume_db = linear_to_db(music_volume * master_volume) + + if fade_in: + _fade_in_music() + else: + music_player.play() + + current_music = music_name + is_music_playing = true + +## 停止背景音乐 +func stop_music(fade_out: bool = true) -> void: + if not is_music_playing: + return + + if fade_out: + _fade_out_music() + else: + music_player.stop() + is_music_playing = false + current_music = "" + +## 播放音效 +func play_sound_effect(sound_name: String, volume_override: float = -1.0) -> void: + var sound_path = SOUND_PATH + sound_name + ".ogg" + + if not ResourceLoader.exists(sound_path): + push_warning("Sound file not found: %s" % sound_path) + return + + # 获取可用的音效播放器 + var player = _get_available_sfx_player() + if player == null: + push_warning("No available sound effect player") + return + + # 加载并播放音效 + var audio_stream = load(sound_path) + player.stream = audio_stream + + var final_volume = volume_override if volume_override > 0 else sfx_volume + player.volume_db = linear_to_db(final_volume * master_volume) + + player.play() + active_sounds[sound_name] = player + +## 设置主音量 +func set_master_volume(volume: float) -> void: + master_volume = clamp(volume, 0.0, 1.0) + _update_all_volumes() + +## 设置音乐音量 +func set_music_volume(volume: float) -> void: + music_volume = clamp(volume, 0.0, 1.0) + if is_music_playing: + music_player.volume_db = linear_to_db(music_volume * master_volume) + +## 设置音效音量 +func set_sfx_volume(volume: float) -> void: + sfx_volume = clamp(volume, 0.0, 1.0) + _update_sfx_volumes() + +# 私有方法 +func _initialize_audio_players() -> void: + # 创建音乐播放器 + music_player = AudioStreamPlayer.new() + add_child(music_player) + music_player.finished.connect(_on_music_finished) + + # 创建多个音效播放器(支持同时播放多个音效) + for i in range(8): + var sfx_player = AudioStreamPlayer.new() + add_child(sfx_player) + sfx_players.append(sfx_player) + + # 创建语音播放器 + voice_player = AudioStreamPlayer.new() + add_child(voice_player) + +func _get_available_sfx_player() -> AudioStreamPlayer: + for player in sfx_players: + if not player.playing: + return player + return null + +func _fade_in_music() -> void: + music_player.volume_db = linear_to_db(0.01) + music_player.play() + + var tween = create_tween() + tween.tween_method(_set_music_volume_db, 0.01, music_volume * master_volume, 1.0) + +func _fade_out_music() -> void: + var tween = create_tween() + tween.tween_method(_set_music_volume_db, music_volume * master_volume, 0.01, 1.0) + tween.tween_callback(_stop_music_after_fade) + +func _set_music_volume_db(volume: float) -> void: + music_player.volume_db = linear_to_db(volume) + +func _stop_music_after_fade() -> void: + music_player.stop() + is_music_playing = false + current_music = "" + +func _update_all_volumes() -> void: + if is_music_playing: + music_player.volume_db = linear_to_db(music_volume * master_volume) + _update_sfx_volumes() + +func _update_sfx_volumes() -> void: + for player in sfx_players: + if player.playing: + player.volume_db = linear_to_db(sfx_volume * master_volume) + +func _load_audio_settings() -> void: + # 从配置文件加载音频设置 + pass + +func _on_music_finished() -> void: + is_music_playing = false + current_music = "" + music_finished.emit() +``` + +--- + +**🎯 使用说明**: +1. 选择合适的管理器模板 +2. 根据具体需求修改类名和功能 +3. 确保在project.godot中配置为AutoLoad +4. 遵循项目的命名规范和代码风格 +5. 添加必要的错误处理和日志记录 \ No newline at end of file diff --git a/docs/AI_docs/workflows/feature_development.md b/docs/AI_docs/workflows/feature_development.md new file mode 100644 index 0000000..bd81490 --- /dev/null +++ b/docs/AI_docs/workflows/feature_development.md @@ -0,0 +1,363 @@ +# 🚀 功能开发流程 + +> AI编程助手专用:新功能开发的标准化工作流程 + +## 🎯 开发流程概览 + +### 阶段1: 需求分析 → 阶段2: 架构设计 → 阶段3: 代码实现 → 阶段4: 测试验证 → 阶段5: 文档更新 + +--- + +## 📋 阶段1: 需求分析 + +### 1.1 理解需求 +```markdown +**必须明确的问题:** +- 功能的具体作用是什么? +- 涉及哪些用户交互? +- 需要哪些数据和状态管理? +- 与现有功能的关系如何? +``` + +### 1.2 需求分类 +```gdscript +# 功能类型分类 +enum FeatureType { + CORE_SYSTEM, # 核心系统功能 → 放在 _Core/ + GAME_SCENE, # 游戏场景功能 → 放在 scenes/ + UI_COMPONENT, # UI组件功能 → 放在 scenes/ui/ + ASSET_RELATED, # 资源相关功能 → 涉及 assets/ + CONFIG_DRIVEN # 配置驱动功能 → 涉及 Config/ +} +``` + +### 1.3 依赖分析 +- 需要哪些现有管理器? +- 需要创建新的管理器吗? +- 需要新的事件定义吗? +- 需要新的配置文件吗? + +--- + +## 🏗️ 阶段2: 架构设计 + +### 2.1 确定文件位置 +```gdscript +# 根据功能类型确定文件位置 +match feature_type: + FeatureType.CORE_SYSTEM: + # _Core/managers/ 或 _Core/systems/ + var file_path = "_Core/managers/YourManager.gd" + + FeatureType.GAME_SCENE: + # scenes/maps/, scenes/characters/, scenes/effects/ + var file_path = "scenes/characters/YourCharacter.gd" + + FeatureType.UI_COMPONENT: + # scenes/ui/ + var file_path = "scenes/ui/YourWindow.gd" +``` + +### 2.2 设计接口 +```gdscript +# 定义公共接口 +class_name YourFeature + +# 信号定义(对外通信) +signal feature_initialized() +signal feature_state_changed(new_state: String) + +# 公共方法(供其他模块调用) +func initialize(config: Dictionary) -> bool +func get_state() -> String +func cleanup() -> void +``` + +### 2.3 事件设计 +```gdscript +# 在 _Core/EventNames.gd 中添加新事件 +const YOUR_FEATURE_STARTED: String = "your_feature_started" +const YOUR_FEATURE_COMPLETED: String = "your_feature_completed" +const YOUR_FEATURE_ERROR: String = "your_feature_error" +``` + +--- + +## 💻 阶段3: 代码实现 + +### 3.1 创建基础结构 +```gdscript +# 使用标准模板创建文件 +# 参考: docs/AI_docs/templates/components.md + +extends Node # 或其他合适的基类 + +## [功能描述] +## 负责[具体职责] + +# 信号定义 +signal feature_ready() + +# 枚举定义 +enum FeatureState { + UNINITIALIZED, + INITIALIZING, + READY, + ERROR +} + +# 常量定义 +const CONFIG_PATH: String = "res://Config/your_feature_config.json" + +# 导出变量 +@export var debug_mode: bool = false + +# 公共变量 +var current_state: FeatureState = FeatureState.UNINITIALIZED + +# 私有变量 +var _config_data: Dictionary = {} + +func _ready() -> void: + initialize() +``` + +### 3.2 实现核心逻辑 +```gdscript +## 初始化功能 +func initialize() -> bool: + if current_state != FeatureState.UNINITIALIZED: + push_warning("Feature already initialized") + return false + + current_state = FeatureState.INITIALIZING + + # 加载配置 + if not _load_config(): + current_state = FeatureState.ERROR + return false + + # 连接事件 + _connect_events() + + # 执行初始化逻辑 + _perform_initialization() + + current_state = FeatureState.READY + feature_ready.emit() + return true + +func _load_config() -> bool: + # 配置加载逻辑 + return true + +func _connect_events() -> void: + # 事件连接逻辑 + EventSystem.connect_event("related_event", _on_related_event) + +func _perform_initialization() -> void: + # 具体初始化逻辑 + pass +``` + +### 3.3 错误处理 +```gdscript +func _handle_error(error_message: String) -> void: + push_error("[YourFeature] %s" % error_message) + current_state = FeatureState.ERROR + + # 发送错误事件 + EventSystem.emit_event(EventNames.YOUR_FEATURE_ERROR, { + "message": error_message, + "timestamp": Time.get_unix_time_from_system() + }) +``` + +--- + +## 🧪 阶段4: 测试验证 + +### 4.1 创建测试文件 +```gdscript +# tests/unit/test_your_feature.gd +extends "res://addons/gut/test.gd" + +## YourFeature 单元测试 + +var your_feature: YourFeature + +func before_each(): + your_feature = preload("res://_Core/managers/YourFeature.gd").new() + add_child(your_feature) + +func after_each(): + your_feature.queue_free() + +func test_initialization(): + # 测试初始化 + var result = your_feature.initialize() + assert_true(result, "Feature should initialize successfully") + assert_eq(your_feature.current_state, YourFeature.FeatureState.READY) + +func test_error_handling(): + # 测试错误处理 + # 模拟错误条件 + pass +``` + +### 4.2 集成测试 +```gdscript +# tests/integration/test_your_feature_integration.gd +extends "res://addons/gut/test.gd" + +## YourFeature 集成测试 + +func test_feature_with_event_system(): + # 测试与事件系统的集成 + var event_received = false + + EventSystem.connect_event("your_feature_started", func(data): event_received = true) + + # 触发功能 + # 验证事件是否正确发送 + assert_true(event_received, "Event should be emitted") +``` + +### 4.3 性能测试 +```gdscript +# tests/performance/test_your_feature_performance.gd +extends "res://addons/gut/test.gd" + +## YourFeature 性能测试 + +func test_initialization_performance(): + var start_time = Time.get_time_dict_from_system() + + # 执行功能 + your_feature.initialize() + + var end_time = Time.get_time_dict_from_system() + var duration = _calculate_duration(start_time, end_time) + + # 验证性能要求(例如:初始化应在100ms内完成) + assert_lt(duration, 0.1, "Initialization should complete within 100ms") +``` + +--- + +## 📚 阶段5: 文档更新 + +### 5.1 更新API文档 +```markdown +# 在 docs/AI_docs/quick_reference/api_reference.md 中添加 + +## YourFeature API + +### 初始化 +```gdscript +var feature = YourFeature.new() +feature.initialize(config_dict) +``` + +### 主要方法 +- `initialize(config: Dictionary) -> bool` - 初始化功能 +- `get_state() -> FeatureState` - 获取当前状态 +- `cleanup() -> void` - 清理资源 + +### 事件 +- `feature_ready` - 功能准备就绪 +- `feature_state_changed(new_state)` - 状态改变 +``` + +### 5.2 更新使用示例 +```gdscript +# 在 docs/AI_docs/quick_reference/code_snippets.md 中添加 + +## YourFeature 使用示例 + +### 基本使用 +```gdscript +# 创建和初始化 +var feature = YourFeature.new() +add_child(feature) + +# 连接信号 +feature.feature_ready.connect(_on_feature_ready) + +# 初始化 +var config = {"setting1": "value1"} +feature.initialize(config) + +func _on_feature_ready(): + print("Feature is ready to use") +``` +``` + +### 5.3 更新架构文档 +```markdown +# 在 docs/AI_docs/architecture_guide.md 中更新 + +## 新增功能: YourFeature + +### 位置 +- 文件路径: `_Core/managers/YourFeature.gd` +- AutoLoad: 是/否 +- 依赖: EventSystem, ConfigManager + +### 职责 +- 负责[具体职责描述] +- 管理[相关数据/状态] +- 提供[对外接口] +``` + +--- + +## ✅ 开发检查清单 + +### 代码质量检查 +- [ ] 遵循命名规范(PascalCase类名,snake_case变量名) +- [ ] 所有变量和函数都有类型注解 +- [ ] 添加了适当的注释和文档字符串 +- [ ] 实现了错误处理和边界检查 +- [ ] 使用事件系统进行模块间通信 + +### 架构一致性检查 +- [ ] 文件放在正确的目录中 +- [ ] 如果是管理器,已配置AutoLoad +- [ ] 事件名称已添加到EventNames.gd +- [ ] 配置文件已放在Config/目录 +- [ ] 遵循项目的架构原则 + +### 测试覆盖检查 +- [ ] 编写了单元测试 +- [ ] 编写了集成测试(如果需要) +- [ ] 编写了性能测试(如果是核心功能) +- [ ] 所有测试都能通过 +- [ ] 测试覆盖了主要功能和边界情况 + +### 文档更新检查 +- [ ] 更新了API参考文档 +- [ ] 添加了使用示例 +- [ ] 更新了架构文档 +- [ ] 更新了相关的工作流程文档 + +--- + +## 🔄 迭代优化 + +### 代码审查要点 +1. **功能完整性**: 是否满足所有需求? +2. **性能表现**: 是否存在性能瓶颈? +3. **错误处理**: 是否处理了所有可能的错误情况? +4. **代码可读性**: 代码是否清晰易懂? +5. **测试覆盖**: 测试是否充分? + +### 持续改进 +- 收集用户反馈 +- 监控性能指标 +- 定期重构优化 +- 更新文档和示例 + +--- + +**🎯 记住**: 这个流程确保了功能开发的质量和一致性。严格遵循每个阶段的要求,将大大提高开发效率和代码质量。 \ No newline at end of file diff --git a/project.godot b/project.godot index aeeb2d3..49e9865 100644 --- a/project.godot +++ b/project.godot @@ -11,7 +11,7 @@ config_version=5 [application] config/name="whaleTown" -run/main_scene="res://Scenes/Maps/main_scene.tscn" +run/main_scene="res://scenes/maps/main_scene.tscn" config/features=PackedStringArray("4.5", "Forward Plus") config/icon="res://icon.svg" diff --git a/scenes/Components/characters/.gitkeep b/scenes/Components/characters/.gitkeep deleted file mode 100644 index fb0695e..0000000 --- a/scenes/Components/characters/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# 保持目录结构 - 角色预制体目录 \ No newline at end of file diff --git a/scenes/Components/effects/.gitkeep b/scenes/Components/effects/.gitkeep deleted file mode 100644 index 6691578..0000000 --- a/scenes/Components/effects/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# 保持目录结构 - 特效预制体目录 \ No newline at end of file diff --git a/scenes/Components/items/.gitkeep b/scenes/Components/items/.gitkeep deleted file mode 100644 index 2e3c48c..0000000 --- a/scenes/Components/items/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# 保持目录结构 - 物品预制体目录 \ No newline at end of file diff --git a/scenes/Components/ui/.gitkeep b/scenes/Components/ui/.gitkeep deleted file mode 100644 index 884109f..0000000 --- a/scenes/Components/ui/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# 保持目录结构 - UI预制体目录 \ No newline at end of file diff --git a/scenes/Maps/.gitkeep b/scenes/Maps/.gitkeep new file mode 100644 index 0000000..c8f3ac4 --- /dev/null +++ b/scenes/Maps/.gitkeep @@ -0,0 +1,2 @@ +# 地图场景目录 +# 存放游戏关卡、世界地图等地图场景 \ No newline at end of file diff --git a/scenes/Maps/MainScene.gd b/scenes/Maps/MainScene.gd index 004ae0d..3818a01 100644 --- a/scenes/Maps/MainScene.gd +++ b/scenes/Maps/MainScene.gd @@ -113,4 +113,4 @@ func _input(event): get_tree().quit() GameState.MAIN_GAME: # 在游戏中按ESC可能显示菜单或返回登录 - show_auth_scene() + show_auth_scene() \ No newline at end of file diff --git a/scenes/Maps/MainScene.gd.uid b/scenes/Maps/MainScene.gd.uid index 4feac40..2d135e3 100644 --- a/scenes/Maps/MainScene.gd.uid +++ b/scenes/Maps/MainScene.gd.uid @@ -1 +1 @@ -uid://blp30m0tuach8 +uid://cn2xjgj3h847p diff --git a/scenes/Maps/main_scene.tscn b/scenes/Maps/main_scene.tscn index c7df691..cb02a22 100644 --- a/scenes/Maps/main_scene.tscn +++ b/scenes/Maps/main_scene.tscn @@ -1,28 +1,14 @@ -[gd_scene load_steps=4 format=3 uid="uid://4ptgx76y83mx"] +[gd_scene load_steps=3 format=3 uid="uid://21a49e14a0c58d7941d04142a5bf9ddc"] -[ext_resource type="Texture2D" uid="uid://bx17oy8lvaca4" path="res://assets/ui/auth/bg_auth_scene.png" id="1_background"] -[ext_resource type="PackedScene" uid="uid://by7m8snb4xllf" path="res://UI/Windows/LoginWindow.tscn" id="2_main"] -[ext_resource type="Script" uid="uid://blp30m0tuach8" path="res://Scenes/Maps/MainScene.gd" id="3_script"] +[ext_resource type="Script" path="res://scenes/maps/MainScene.gd" id="1_script"] +[ext_resource type="PackedScene" uid="uid://by7m8snb4xllf" path="res://scenes/ui/LoginWindow.tscn" id="2_main"] [node name="Main" type="Control"] layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -script = ExtResource("3_script") - -[node name="BackgroundImage" type="TextureRect" parent="."] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -texture = ExtResource("1_background") -expand_mode = 1 -stretch_mode = 6 +script = ExtResource("1_script") [node name="AuthScene" parent="." instance=ExtResource("2_main")] layout_mode = 1 @@ -33,24 +19,12 @@ layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 - -[node name="UIOverlay" type="ColorRect" parent="MainGameUI"] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -color = Color(0, 0, 0, 0.3) [node name="TopBar" type="Panel" parent="MainGameUI"] layout_mode = 1 anchors_preset = 10 anchor_right = 1.0 offset_bottom = 60.0 -grow_horizontal = 2 [node name="HBoxContainer" type="HBoxContainer" parent="MainGameUI/TopBar"] layout_mode = 1 @@ -61,26 +35,16 @@ offset_left = 20.0 offset_top = 10.0 offset_right = -20.0 offset_bottom = -10.0 -grow_horizontal = 2 -grow_vertical = 2 - -[node name="WelcomeLabel" type="Label" parent="MainGameUI/TopBar/HBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -theme_override_colors/font_color = Color(1, 1, 1, 1) -text = "🐋 欢迎来到鲸鱼镇!" -vertical_alignment = 1 [node name="UserLabel" type="Label" parent="MainGameUI/TopBar/HBoxContainer"] layout_mode = 2 -theme_override_colors/font_color = Color(1, 1, 1, 1) -text = "当前用户: [用户名]" -horizontal_alignment = 2 +size_flags_horizontal = 3 +text = "当前用户: " vertical_alignment = 1 [node name="LogoutButton" type="Button" parent="MainGameUI/TopBar/HBoxContainer"] layout_mode = 2 -text = "退出" +text = "登出" [node name="MainContent" type="Control" parent="MainGameUI"] layout_mode = 1 @@ -88,80 +52,29 @@ anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 offset_top = 60.0 -grow_horizontal = 2 -grow_vertical = 2 [node name="CenterContainer" type="CenterContainer" parent="MainGameUI/MainContent"] layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 [node name="VBoxContainer" type="VBoxContainer" parent="MainGameUI/MainContent/CenterContainer"] -custom_minimum_size = Vector2(600, 400) -layout_mode = 2 - -[node name="GameTitle" type="Label" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer"] -layout_mode = 2 -theme_override_colors/font_color = Color(1, 1, 1, 1) -theme_override_font_sizes/font_size = 24 -text = "🏘️ 鲸鱼镇主界面" -horizontal_alignment = 1 - -[node name="HSeparator" type="HSeparator" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer"] -layout_mode = 2 - -[node name="GameMenuGrid" type="GridContainer" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 3 -columns = 2 - -[node name="ExploreButton" type="Button" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/GameMenuGrid"] -custom_minimum_size = Vector2(280, 80) -layout_mode = 2 -text = "🗺️ 探索小镇" - -[node name="InventoryButton" type="Button" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/GameMenuGrid"] -custom_minimum_size = Vector2(280, 80) -layout_mode = 2 -text = "🎒 背包物品" - -[node name="ShopButton" type="Button" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/GameMenuGrid"] -custom_minimum_size = Vector2(280, 80) -layout_mode = 2 -text = "🏪 商店购物" - -[node name="FriendsButton" type="Button" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/GameMenuGrid"] -custom_minimum_size = Vector2(280, 80) -layout_mode = 2 -text = "👥 好友列表" - -[node name="HSeparator2" type="HSeparator" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer"] layout_mode = 2 [node name="StatusPanel" type="Panel" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer"] -custom_minimum_size = Vector2(0, 120) layout_mode = 2 +custom_minimum_size = Vector2(400, 150) -[node name="StatusContainer" type="VBoxContainer" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/StatusPanel"] +[node name="StatusContainer" type="MarginContainer" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/StatusPanel"] layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 offset_left = 20.0 -offset_top = 10.0 +offset_top = 20.0 offset_right = -20.0 -offset_bottom = -10.0 -grow_horizontal = 2 -grow_vertical = 2 - -[node name="StatusTitle" type="Label" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/StatusPanel/StatusContainer"] -layout_mode = 2 -theme_override_colors/font_color = Color(1, 1, 1, 1) -text = "📊 玩家状态" -horizontal_alignment = 1 +offset_bottom = -20.0 [node name="StatusGrid" type="GridContainer" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/StatusPanel/StatusContainer"] layout_mode = 2 @@ -169,20 +82,40 @@ columns = 2 [node name="LevelLabel" type="Label" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/StatusPanel/StatusContainer/StatusGrid"] layout_mode = 2 -theme_override_colors/font_color = Color(1, 1, 1, 1) text = "等级: 1" [node name="CoinsLabel" type="Label" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/StatusPanel/StatusContainer/StatusGrid"] layout_mode = 2 -theme_override_colors/font_color = Color(1, 1, 1, 1) text = "金币: 100" [node name="ExpLabel" type="Label" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/StatusPanel/StatusContainer/StatusGrid"] layout_mode = 2 -theme_override_colors/font_color = Color(1, 1, 1, 1) text = "经验: 0/100" [node name="EnergyLabel" type="Label" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/StatusPanel/StatusContainer/StatusGrid"] layout_mode = 2 -theme_override_colors/font_color = Color(1, 1, 1, 1) text = "体力: 100/100" + +[node name="GameMenuGrid" type="GridContainer" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="ExploreButton" type="Button" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/GameMenuGrid"] +layout_mode = 2 +custom_minimum_size = Vector2(150, 50) +text = "🗺️ 探索小镇" + +[node name="InventoryButton" type="Button" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/GameMenuGrid"] +layout_mode = 2 +custom_minimum_size = Vector2(150, 50) +text = "🎒 背包" + +[node name="ShopButton" type="Button" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/GameMenuGrid"] +layout_mode = 2 +custom_minimum_size = Vector2(150, 50) +text = "🏪 商店" + +[node name="FriendsButton" type="Button" parent="MainGameUI/MainContent/CenterContainer/VBoxContainer/GameMenuGrid"] +layout_mode = 2 +custom_minimum_size = Vector2(150, 50) +text = "👥 好友" \ No newline at end of file diff --git a/scenes/characters/.gitkeep b/scenes/characters/.gitkeep new file mode 100644 index 0000000..c6ef796 --- /dev/null +++ b/scenes/characters/.gitkeep @@ -0,0 +1,2 @@ +# 人物场景目录 +# 存放角色、NPC、敌人等人物相关场景 \ No newline at end of file diff --git a/scenes/effects/.gitkeep b/scenes/effects/.gitkeep new file mode 100644 index 0000000..48501db --- /dev/null +++ b/scenes/effects/.gitkeep @@ -0,0 +1,2 @@ +# 特效场景目录 +# 存放粒子效果、动画等特效场景 \ No newline at end of file diff --git a/scenes/prefabs/.gitkeep b/scenes/prefabs/.gitkeep new file mode 100644 index 0000000..afb3d03 --- /dev/null +++ b/scenes/prefabs/.gitkeep @@ -0,0 +1,2 @@ +# 预制体组件目录 +# 存放可复用的预制体组件 \ No newline at end of file diff --git a/scenes/prefabs/characters/.gitkeep b/scenes/prefabs/characters/.gitkeep new file mode 100644 index 0000000..03176b7 --- /dev/null +++ b/scenes/prefabs/characters/.gitkeep @@ -0,0 +1,2 @@ +# 角色预制体目录 +# 存放可复用的角色组件预制体 \ No newline at end of file diff --git a/scenes/prefabs/effects/.gitkeep b/scenes/prefabs/effects/.gitkeep new file mode 100644 index 0000000..2d4709c --- /dev/null +++ b/scenes/prefabs/effects/.gitkeep @@ -0,0 +1,2 @@ +# 特效预制体目录 +# 存放可复用的特效组件预制体 \ No newline at end of file diff --git a/scenes/prefabs/items/.gitkeep b/scenes/prefabs/items/.gitkeep new file mode 100644 index 0000000..55f90aa --- /dev/null +++ b/scenes/prefabs/items/.gitkeep @@ -0,0 +1,2 @@ +# 物品预制体目录 +# 存放可复用的物品组件预制体 \ No newline at end of file diff --git a/scenes/prefabs/ui/.gitkeep b/scenes/prefabs/ui/.gitkeep new file mode 100644 index 0000000..9371238 --- /dev/null +++ b/scenes/prefabs/ui/.gitkeep @@ -0,0 +1,2 @@ +# UI预制体目录 +# 存放可复用的UI组件预制体 \ No newline at end of file diff --git a/scenes/ui/.gitkeep b/scenes/ui/.gitkeep new file mode 100644 index 0000000..6f9d732 --- /dev/null +++ b/scenes/ui/.gitkeep @@ -0,0 +1,2 @@ +# UI界面场景目录 +# 存放菜单、HUD、对话框等UI界面场景 \ No newline at end of file diff --git a/UI/Windows/AuthScene.gd b/scenes/ui/AuthScene.gd similarity index 99% rename from UI/Windows/AuthScene.gd rename to scenes/ui/AuthScene.gd index 4c235c0..485da13 100644 --- a/UI/Windows/AuthScene.gd +++ b/scenes/ui/AuthScene.gd @@ -1029,4 +1029,4 @@ func _exit_tree(): func _input(event): if event.is_action_pressed("ui_cancel"): - get_tree().quit() + get_tree().quit() \ No newline at end of file diff --git a/scenes/ui/AuthScene.gd.uid b/scenes/ui/AuthScene.gd.uid new file mode 100644 index 0000000..97b8ff9 --- /dev/null +++ b/scenes/ui/AuthScene.gd.uid @@ -0,0 +1 @@ +uid://b514h2wuido0h diff --git a/UI/Windows/LoginWindow.tscn b/scenes/ui/LoginWindow.tscn similarity index 99% rename from UI/Windows/LoginWindow.tscn rename to scenes/ui/LoginWindow.tscn index 50e32f6..3cf8c76 100644 --- a/UI/Windows/LoginWindow.tscn +++ b/scenes/ui/LoginWindow.tscn @@ -2,7 +2,7 @@ [ext_resource type="Texture2D" uid="uid://bx17oy8lvaca4" path="res://assets/ui/auth/bg_auth_scene.png" id="1_background"] [ext_resource type="Texture2D" uid="uid://de4q4s1gxivtf" path="res://assets/ui/auth/login_frame_smart_transparent.png" id="2_frame"] -[ext_resource type="Script" uid="uid://bs1vy3ierj66t" path="res://UI/Windows/AuthScene.gd" id="3_script"] +[ext_resource type="Script" path="res://scenes/ui/AuthScene.gd" id="3_script"] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_1"] diff --git a/tests/auth/auth_ui_test.tscn b/tests/auth/auth_ui_test.tscn index cb00105..0285847 100644 --- a/tests/auth/auth_ui_test.tscn +++ b/tests/auth/auth_ui_test.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=4 format=3 uid="uid://bvn8y7x2qkqxe"] [ext_resource type="Script" uid="uid://ddb8v5c6aeqe7" path="res://tests/auth/auth_ui_test.gd" id="1_test_script"] -[ext_resource type="PackedScene" uid="uid://by7m8snb4xllf" path="res://UI/Windows/LoginWindow.tscn" id="2_auth_scene"] +[ext_resource type="PackedScene" uid="uid://by7m8snb4xllf" path="res://scenes/ui/LoginWindow.tscn" id="2_auth_scene"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_feedback_info"] bg_color = Color(0.2, 0.5, 0.8, 0.9) diff --git a/tests/auth/enhanced_toast_test.gd b/tests/auth/enhanced_toast_test.gd index fb0a889..082ac87 100644 --- a/tests/auth/enhanced_toast_test.gd +++ b/tests/auth/enhanced_toast_test.gd @@ -6,7 +6,7 @@ class_name EnhancedToastTest # 测试新增的错误码处理 func test_new_error_codes(): - var auth_scene = preload("res://UI/Windows/AuthScene.gd").new() + var auth_scene = preload("res://scenes/ui/AuthScene.gd").new() # 测试验证码登录失败 var verification_login_error = {