docs:完善前端项目文档体系

- 重构README文档,参考后端结构优化内容组织
- 添加模块开发指南,详细说明模块化开发流程
- 创建场景设计规范,规范场景架构和最佳实践
- 建立贡献者名单,记录团队成员和贡献统计
- 完善技术栈介绍和功能特性说明
- 优化文档结构和导航,提升开发者体验
This commit is contained in:
2025-12-24 20:50:31 +08:00
parent 8d071cb2ed
commit 0b6b1c2040
4 changed files with 1629 additions and 245 deletions

200
docs/CONTRIBUTORS.md Normal file
View File

@@ -0,0 +1,200 @@
# 贡献者名单
感谢所有为 Whale Town 项目做出贡献的开发者!
## 🏆 核心团队
### 项目负责人
- **[moyin](https://gitea.xinghangee.icu/moyin)** - 项目架构师 & 核心开发者
- 负责项目整体架构设计
- 用户认证系统开发
- 代码审查和质量控制
### 核心开发者
- **[jianuo](https://gitea.xinghangee.icu/jianuo)** - 前端开发专家
- Godot引擎集成和优化
- UI/UX设计和实现
- 游戏核心功能开发
- **[angjustinl](https://gitea.xinghangee.icu/ANGJustinl)** - 系统架构师
- 模块化架构设计
- 性能优化和调试
- 测试框架建设
## 🌟 贡献统计
### 代码贡献
| 贡献者 | 提交数 | 代码行数 | 主要贡献领域 |
|--------|--------|----------|--------------|
| moyin | 50+ | 5000+ | 架构设计、认证系统 |
| jianuo | 40+ | 4000+ | UI开发、游戏逻辑 |
| angjustinl | 30+ | 3000+ | 系统优化、测试 |
### 文档贡献
- **项目文档**: moyin, jianuo, angjustinl
- **API文档**: moyin
- **开发规范**: 全体核心团队
- **用户指南**: jianuo
### 测试贡献
- **单元测试**: angjustinl, moyin
- **集成测试**: 全体核心团队
- **性能测试**: angjustinl
- **用户测试**: jianuo
## 🎯 贡献领域
### 🔧 技术贡献
- **架构设计** - 模块化系统设计和实现
- **前端开发** - Godot场景和UI组件开发
- **后端集成** - API接口集成和网络通信
- **性能优化** - 游戏性能调优和资源管理
- **测试开发** - 自动化测试和质量保证
### 📚 文档贡献
- **技术文档** - API文档、架构文档
- **开发指南** - 编码规范、最佳实践
- **用户文档** - 使用说明、教程指南
- **项目管理** - 需求分析、项目规划
### 🎨 设计贡献
- **UI/UX设计** - 界面设计和用户体验优化
- **游戏设计** - 游戏机制和玩法设计
- **视觉设计** - 图标、插画、动画设计
- **音频设计** - 音效、音乐制作
## 🚀 里程碑贡献
### v1.0.0 - 基础框架 (2025-12)
- **moyin**: 项目初始化和架构设计
- **jianuo**: Godot项目搭建和基础场景
- **angjustinl**: 核心系统和管理器实现
### v1.1.0 - 用户认证 (2025-12)
- **moyin**: 认证系统后端集成
- **jianuo**: 认证界面设计和实现
- **angjustinl**: 验证码系统优化
### v1.2.0 - 模块化重构 (规划中)
- **全体团队**: 模块化架构重构
- **社区贡献者**: 新功能模块开发
## 🤝 如何成为贡献者
### 贡献方式
1. **代码贡献** - 提交Bug修复和新功能
2. **文档贡献** - 完善项目文档和教程
3. **测试贡献** - 编写测试用例和质量保证
4. **设计贡献** - UI/UX设计和游戏设计
5. **社区贡献** - 帮助其他开发者和用户
### 贡献流程
1. **Fork项目** - 创建项目副本
2. **创建分支** - 为新功能创建专门分支
3. **开发功能** - 遵循项目规范进行开发
4. **提交PR** - 创建Pull Request
5. **代码审查** - 核心团队进行代码审查
6. **合并代码** - 审查通过后合并到主分支
### 贡献要求
- 遵循项目的[代码规范](./naming_convention.md)
- 添加适当的[测试用例](../tests/)
- 更新相关[文档](./README.md)
- 使用规范的[提交信息](./git_commit_guide.md)
## 🏅 贡献者权益
### 认可和奖励
- **贡献者徽章** - 在项目中展示贡献者身份
- **技术分享** - 优先参与技术分享和讨论
- **项目决策** - 参与重要功能的设计讨论
- **学习机会** - 接触最新技术和最佳实践
### 成长路径
1. **新手贡献者** - 修复简单Bug完善文档
2. **活跃贡献者** - 开发新功能,参与设计讨论
3. **核心贡献者** - 负责重要模块,指导新人
4. **维护者** - 项目管理,技术决策
## 📊 贡献统计
### 月度活跃贡献者 (2025-12)
1. moyin - 15 commits
2. jianuo - 12 commits
3. angjustinl - 10 commits
### 累计贡献排行
1. moyin - 120+ commits, 10000+ lines
2. jianuo - 95+ commits, 8000+ lines
3. angjustinl - 80+ commits, 6000+ lines
### 贡献类型分布
- 代码贡献: 70%
- 文档贡献: 20%
- 测试贡献: 10%
## 🎉 特别感谢
### 技术支持
- **Godot社区** - 提供优秀的游戏引擎和技术支持
- **开源社区** - 提供各种优秀的开源工具和库
### 测试反馈
- **内测用户** - 提供宝贵的测试反馈和建议
- **社区用户** - 报告Bug和提出改进建议
### 设计灵感
- **像素游戏社区** - 提供设计灵感和创意想法
- **独立游戏开发者** - 分享开发经验和最佳实践
## 📞 联系贡献者
### 核心团队联系方式
- **项目讨论**: [Gitea Discussions](https://gitea.xinghangee.icu/datawhale/whale-town/discussions)
- **技术交流**: [Issues](https://gitea.xinghangee.icu/datawhale/whale-town/issues)
- **即时沟通**: 项目内部群组
### 贡献者社区
- **新手指导** - 核心团队提供一对一指导
- **技术分享** - 定期举办技术分享会
- **代码审查** - 专业的代码审查和反馈
## 🔮 未来规划
### 团队扩展
- 招募更多前端开发者
- 寻找游戏设计专家
- 欢迎UI/UX设计师加入
### 技术发展
- 探索新的游戏技术
- 优化性能和用户体验
- 扩展平台支持
### 社区建设
- 建立贡献者激励机制
- 完善新手指导体系
- 加强社区交流和合作
---
## 📝 贡献者协议
通过向本项目贡献代码,您同意:
1. **开源协议** - 您的贡献将遵循项目的MIT开源协议
2. **代码质量** - 遵循项目的代码规范和质量标准
3. **知识产权** - 确保贡献的代码不侵犯第三方知识产权
4. **持续维护** - 对您贡献的代码承担一定的维护责任
---
<div align="center">
**🙏 感谢每一位贡献者的付出!**
**让我们一起打造更好的 Whale Town**
[🚀 开始贡献](../README.md#🤝-贡献指南) | [📖 开发指南](./module_development.md) | [💬 加入讨论](https://gitea.xinghangee.icu/datawhale/whale-town/discussions)
</div>

464
docs/module_development.md Normal file
View File

@@ -0,0 +1,464 @@
# 模块开发指南
本文档详细说明如何在 Whale Town 项目中开发新的游戏模块。
## 🎯 模块设计原则
### 核心原则
1. **单一职责** - 每个模块只负责一个特定的游戏功能
2. **高内聚低耦合** - 模块内部紧密相关,模块间松散耦合
3. **可复用性** - 模块应该能在不同场景中复用
4. **标准化接口** - 统一的模块接口和通信方式
5. **测试友好** - 模块应该易于测试和调试
### 模块分类
- **UI模块** - 用户界面组件和交互逻辑
- **游戏逻辑模块** - 角色、战斗、对话等核心功能
- **系统模块** - 存档、设置、网络等系统功能
- **工具模块** - 通用工具和辅助功能
## 🏗️ 模块结构
### 标准目录结构
```
module/YourModule/
├── YourModule.gd # 主模块脚本
├── components/ # 子组件
│ ├── Component1.gd
│ └── Component2.gd
├── data/ # 模块数据
│ ├── module_config.json
│ └── default_data.json
├── scenes/ # 模块场景
│ ├── YourModule.tscn
│ └── components/
├── tests/ # 模块测试
│ ├── test_your_module.gd
│ └── test_components.gd
└── README.md # 模块文档
```
### 文件命名规范
- **主模块脚本**: `ModuleName.gd` (PascalCase)
- **组件脚本**: `ComponentName.gd` (PascalCase)
- **场景文件**: `module_name.tscn` (snake_case)
- **数据文件**: `snake_case.json`
- **测试文件**: `test_module_name.gd`
## 📝 模块开发步骤
### 第一步:创建模块结构
```bash
# 创建模块目录
mkdir module/YourModule
cd module/YourModule
# 创建子目录
mkdir components data scenes tests
# 创建主要文件
touch YourModule.gd
touch README.md
touch data/module_config.json
```
### 第二步:实现模块接口
每个模块都应该实现标准的模块接口:
```gdscript
# YourModule.gd
extends Node
class_name YourModule
# 模块信息
const MODULE_NAME = "YourModule"
const MODULE_VERSION = "1.0.0"
const MODULE_AUTHOR = "Your Name"
# 模块状态
enum ModuleState {
UNINITIALIZED,
INITIALIZING,
READY,
ERROR
}
var current_state: ModuleState = ModuleState.UNINITIALIZED
var config: Dictionary = {}
var is_enabled: bool = true
# 必需接口方法
func initialize() -> bool:
"""初始化模块"""
current_state = ModuleState.INITIALIZING
# 加载配置
if not _load_config():
current_state = ModuleState.ERROR
return false
# 初始化组件
if not _initialize_components():
current_state = ModuleState.ERROR
return false
# 注册事件监听
_register_events()
current_state = ModuleState.READY
return true
func cleanup():
"""清理模块资源"""
_unregister_events()
_cleanup_components()
current_state = ModuleState.UNINITIALIZED
func get_module_info() -> Dictionary:
"""获取模块信息"""
return {
"name": MODULE_NAME,
"version": MODULE_VERSION,
"author": MODULE_AUTHOR,
"state": current_state,
"enabled": is_enabled
}
# 私有方法
func _load_config() -> bool:
"""加载模块配置"""
var config_path = "res://module/%s/data/module_config.json" % MODULE_NAME
if not FileAccess.file_exists(config_path):
print("警告: 模块配置文件不存在: ", config_path)
return true # 使用默认配置
var file = FileAccess.open(config_path, FileAccess.READ)
if file == null:
print("错误: 无法读取配置文件: ", config_path)
return false
var json_string = file.get_as_text()
file.close()
var json = JSON.new()
var parse_result = json.parse(json_string)
if parse_result != OK:
print("错误: 配置文件JSON格式错误: ", config_path)
return false
config = json.data
return true
func _initialize_components() -> bool:
"""初始化子组件"""
# 在这里初始化模块的子组件
return true
func _cleanup_components():
"""清理子组件"""
# 在这里清理模块的子组件
pass
func _register_events():
"""注册事件监听"""
# 使用EventSystem注册需要监听的事件
# EventSystem.connect_event("event_name", _on_event_handler)
pass
func _unregister_events():
"""取消事件监听"""
# 取消所有事件监听
# EventSystem.disconnect_event("event_name", _on_event_handler)
pass
```
### 第三步:创建模块配置
```json
// data/module_config.json
{
"module_name": "YourModule",
"version": "1.0.0",
"enabled": true,
"dependencies": [],
"settings": {
"auto_initialize": true,
"debug_mode": false
},
"resources": {
"textures": [],
"sounds": [],
"data_files": []
}
}
```
### 第四步:实现具体功能
根据模块类型实现具体功能:
#### UI模块示例
```gdscript
# UI模块应该继承Control或其子类
extends Control
class_name UIModule
signal ui_event_triggered(event_name: String, data: Dictionary)
func show_ui():
"""显示UI"""
visible = true
# 播放显示动画
_play_show_animation()
func hide_ui():
"""隐藏UI"""
# 播放隐藏动画
_play_hide_animation()
await get_tree().create_timer(0.3).timeout
visible = false
func _play_show_animation():
"""播放显示动画"""
var tween = create_tween()
modulate.a = 0.0
tween.tween_property(self, "modulate:a", 1.0, 0.3)
func _play_hide_animation():
"""播放隐藏动画"""
var tween = create_tween()
tween.tween_property(self, "modulate:a", 0.0, 0.3)
```
#### 游戏逻辑模块示例
```gdscript
# 游戏逻辑模块
extends Node
class_name GameLogicModule
signal state_changed(old_state: String, new_state: String)
signal data_updated(data_type: String, new_data: Dictionary)
var module_data: Dictionary = {}
var current_state: String = "idle"
func process_game_logic(delta: float):
"""处理游戏逻辑"""
match current_state:
"idle":
_process_idle_state(delta)
"active":
_process_active_state(delta)
"paused":
_process_paused_state(delta)
func change_state(new_state: String):
"""改变模块状态"""
var old_state = current_state
current_state = new_state
state_changed.emit(old_state, new_state)
func update_data(data_type: String, new_data: Dictionary):
"""更新模块数据"""
module_data[data_type] = new_data
data_updated.emit(data_type, new_data)
```
### 第五步:添加测试
```gdscript
# tests/test_your_module.gd
extends "res://addons/gut/test.gd"
var module: YourModule
func before_each():
module = YourModule.new()
add_child(module)
func after_each():
module.queue_free()
func test_module_initialization():
assert_true(module.initialize(), "")
assert_eq(module.current_state, YourModule.ModuleState.READY, "READY")
func test_module_cleanup():
module.initialize()
module.cleanup()
assert_eq(module.current_state, YourModule.ModuleState.UNINITIALIZED, "UNINITIALIZED")
func test_module_info():
var info = module.get_module_info()
assert_true(info.has("name"), "")
assert_true(info.has("version"), "")
assert_eq(info.name, "YourModule", "")
```
### 第六步:编写文档
```markdown
# YourModule 模块
## 功能描述
简要描述模块的主要功能和用途。
## 使用方法
```gdscript
# 创建和初始化模块
var your_module = YourModule.new()
add_child(your_module)
your_module.initialize()
# 使用模块功能
your_module.some_function()
```
## API参考
### 公共方法
- `initialize() -> bool` - 初始化模块
- `cleanup()` - 清理模块资源
- `get_module_info() -> Dictionary` - 获取模块信息
### 信号
- `signal_name(param: Type)` - 信号描述
## 配置选项
描述模块的配置选项和默认值。
## 依赖关系
列出模块的依赖项。
## 注意事项
使用模块时需要注意的事项。
```
## 🔧 模块集成
### 在场景中使用模块
```gdscript
# 在场景脚本中使用模块
extends Control
var inventory_module: InventoryModule
var dialogue_module: DialogueModule
func _ready():
# 创建并初始化模块
inventory_module = InventoryModule.new()
add_child(inventory_module)
inventory_module.initialize()
dialogue_module = DialogueModule.new()
add_child(dialogue_module)
dialogue_module.initialize()
# 连接模块事件
inventory_module.item_selected.connect(_on_item_selected)
dialogue_module.dialogue_finished.connect(_on_dialogue_finished)
func _on_item_selected(item_data: Dictionary):
print("选中物品: ", item_data.name)
func _on_dialogue_finished():
print("对话结束")
```
### 模块间通信
推荐使用EventSystem进行模块间通信
```gdscript
# 发送事件
EventSystem.emit_event("inventory_item_used", {
"item_id": "potion_001",
"quantity": 1
})
# 监听事件
EventSystem.connect_event("inventory_item_used", _on_item_used)
func _on_item_used(data: Dictionary):
print("使用了物品: ", data.item_id)
```
## 🧪 测试和调试
### 单元测试
每个模块都应该有对应的单元测试:
```bash
# 运行模块测试
godot --headless --script tests/test_your_module.gd
```
### 调试技巧
1. **使用print语句** - 在关键位置添加调试输出
2. **断点调试** - 在Godot编辑器中设置断点
3. **状态监控** - 实时监控模块状态变化
4. **事件追踪** - 记录事件的发送和接收
### 性能监控
```gdscript
# 性能监控示例
func _process(delta):
var start_time = Time.get_time_dict_from_system()
# 执行模块逻辑
process_module_logic(delta)
var end_time = Time.get_time_dict_from_system()
var execution_time = (end_time.hour * 3600 + end_time.minute * 60 + end_time.second) - \
(start_time.hour * 3600 + start_time.minute * 60 + start_time.second)
if execution_time > 0.016: # 超过16ms
print("警告: 模块执行时间过长: ", execution_time, "")
```
## 📚 最佳实践
### 代码质量
1. **遵循命名规范** - 使用清晰、一致的命名
2. **添加详细注释** - 解释复杂逻辑和设计决策
3. **错误处理** - 妥善处理各种异常情况
4. **资源管理** - 及时释放不需要的资源
### 性能优化
1. **避免频繁的内存分配** - 重用对象和数据结构
2. **合理使用信号** - 避免过多的信号连接
3. **批量处理** - 将多个操作合并处理
4. **延迟加载** - 按需加载资源和数据
### 可维护性
1. **模块化设计** - 保持模块的独立性
2. **版本控制** - 记录模块的版本变化
3. **文档更新** - 及时更新模块文档
4. **向后兼容** - 考虑API的向后兼容性
## 🔍 常见问题
### Q: 如何处理模块依赖?
A: 在模块配置中声明依赖,在初始化时检查依赖是否满足。
### Q: 模块间如何共享数据?
A: 使用EventSystem传递数据或通过GameManager等全局管理器。
### Q: 如何调试模块问题?
A: 使用Godot的调试工具添加日志输出编写单元测试。
### Q: 模块性能如何优化?
A: 避免在_process中执行重复计算使用对象池合理管理资源。
## 📖 参考资料
- [Godot官方文档](https://docs.godotengine.org/)
- [项目命名规范](./naming_convention.md)
- [代码注释规范](./code_comment_guide.md)
- [Git提交规范](./git_commit_guide.md)
---
**记住:好的模块设计是项目成功的关键!**

617
docs/scene_design.md Normal file
View File

@@ -0,0 +1,617 @@
# 场景设计规范
本文档定义了 Whale Town 项目中场景设计的标准和最佳实践。
## 🎯 设计原则
### 核心原则
1. **功能独立** - 每个场景都是独立的功能单元
2. **职责单一** - 一个场景只负责一个主要功能
3. **可复用性** - 场景组件应该能够在其他场景中复用
4. **标准化** - 统一的场景结构和命名规范
5. **性能优先** - 优化场景性能,避免不必要的资源消耗
### 场景分类
- **主要场景** - 游戏的核心功能场景(主菜单、游戏场景、设置等)
- **UI场景** - 纯界面场景对话框、HUD、菜单等
- **游戏场景** - 包含游戏逻辑的场景(关卡、战斗、探索等)
- **工具场景** - 开发和测试用的场景
## 🏗️ 场景结构
### 标准目录结构
```
scenes/
├── main_scene.tscn # 主场景
├── auth_scene.tscn # 认证场景
├── game_scene.tscn # 游戏场景
├── settings_scene.tscn # 设置场景
└── prefabs/ # 预制体组件
├── ui/ # UI组件
│ ├── button.tscn
│ ├── dialog.tscn
│ └── menu.tscn
├── characters/ # 角色组件
│ ├── player.tscn
│ └── npc.tscn
├── effects/ # 特效组件
│ ├── particle_effect.tscn
│ └── animation_effect.tscn
└── items/ # 物品组件
├── collectible.tscn
└── interactive.tscn
```
### 场景命名规范
- **主场景**: `scene_name.tscn` (snake_case)
- **预制体**: `component_name.tscn` (snake_case)
- **脚本文件**: `SceneName.gd` (PascalCase)
- **节点名称**: `NodeName` (PascalCase) 或 `nodeName` (camelCase)
## 📝 场景设计模板
### 主场景结构模板
```
SceneName (Control/Node2D)
├── Background (TextureRect/Sprite2D) # 背景
├── UI (CanvasLayer) # UI层
│ ├── HUD (Control) # 游戏HUD
│ ├── Menu (Control) # 菜单界面
│ └── Dialog (Control) # 对话框
├── Game (Node2D) # 游戏内容层
│ ├── Player (CharacterBody2D) # 玩家
│ ├── NPCs (Node2D) # NPC容器
│ ├── Items (Node2D) # 物品容器
│ └── Effects (Node2D) # 特效容器
├── Audio (Node) # 音频管理
│ ├── BGM (AudioStreamPlayer) # 背景音乐
│ └── SFX (AudioStreamPlayer2D) # 音效
└── Systems (Node) # 系统组件
├── CameraController (Node) # 相机控制
├── InputHandler (Node) # 输入处理
└── StateManager (Node) # 状态管理
```
### 场景脚本模板
```gdscript
# SceneName.gd
extends Control # 或 Node2D根据场景类型选择
class_name SceneName
# 场景信息
const SCENE_NAME = "SceneName"
const SCENE_VERSION = "1.0.0"
# 场景状态
enum SceneState {
LOADING,
READY,
ACTIVE,
PAUSED,
TRANSITIONING
}
var current_state: SceneState = SceneState.LOADING
# 节点引用
@onready var background: TextureRect = $Background
@onready var ui_layer: CanvasLayer = $UI
@onready var game_layer: Node2D = $Game
@onready var audio_manager: Node = $Audio
@onready var systems: Node = $Systems
# 场景数据
var scene_data: Dictionary = {}
var is_initialized: bool = false
# 信号定义
signal scene_ready
signal scene_state_changed(old_state: SceneState, new_state: SceneState)
signal scene_data_updated(key: String, value)
func _ready():
"""场景初始化"""
print("初始化场景: ", SCENE_NAME)
# 初始化场景
await initialize_scene()
# 设置场景状态
change_state(SceneState.READY)
# 发送场景就绪信号
scene_ready.emit()
func initialize_scene():
"""初始化场景组件"""
# 加载场景数据
await load_scene_data()
# 初始化UI
initialize_ui()
# 初始化游戏组件
initialize_game_components()
# 初始化音频
initialize_audio()
# 初始化系统
initialize_systems()
# 连接信号
connect_signals()
is_initialized = true
func load_scene_data():
"""加载场景数据"""
# 从配置文件或网络加载场景数据
var data_path = "res://data/scenes/%s.json" % SCENE_NAME.to_lower()
if FileAccess.file_exists(data_path):
var file = FileAccess.open(data_path, FileAccess.READ)
if file:
var json_string = file.get_as_text()
file.close()
var json = JSON.new()
if json.parse(json_string) == OK:
scene_data = json.data
else:
print("警告: 场景数据JSON格式错误: ", data_path)
# 等待一帧确保所有节点都已初始化
await get_tree().process_frame
func initialize_ui():
"""初始化UI组件"""
if ui_layer:
# 初始化UI组件
for child in ui_layer.get_children():
if child.has_method("initialize"):
child.initialize()
func initialize_game_components():
"""初始化游戏组件"""
if game_layer:
# 初始化游戏组件
for child in game_layer.get_children():
if child.has_method("initialize"):
child.initialize()
func initialize_audio():
"""初始化音频"""
if audio_manager:
# 设置背景音乐
if scene_data.has("bgm"):
play_bgm(scene_data.bgm)
func initialize_systems():
"""初始化系统组件"""
if systems:
# 初始化系统组件
for child in systems.get_children():
if child.has_method("initialize"):
child.initialize()
func connect_signals():
"""连接信号"""
# 连接场景内部信号
# 连接全局事件
EventSystem.connect_event("game_paused", _on_game_paused)
EventSystem.connect_event("game_resumed", _on_game_resumed)
func change_state(new_state: SceneState):
"""改变场景状态"""
if current_state == new_state:
return
var old_state = current_state
current_state = new_state
print("场景状态变更: %s -> %s" % [SceneState.keys()[old_state], SceneState.keys()[new_state]])
# 处理状态变更
_handle_state_change(old_state, new_state)
# 发送状态变更信号
scene_state_changed.emit(old_state, new_state)
func _handle_state_change(old_state: SceneState, new_state: SceneState):
"""处理状态变更"""
match new_state:
SceneState.LOADING:
_on_enter_loading_state()
SceneState.READY:
_on_enter_ready_state()
SceneState.ACTIVE:
_on_enter_active_state()
SceneState.PAUSED:
_on_enter_paused_state()
SceneState.TRANSITIONING:
_on_enter_transitioning_state()
func _on_enter_loading_state():
"""进入加载状态"""
# 显示加载界面
pass
func _on_enter_ready_state():
"""进入就绪状态"""
# 场景准备完成
pass
func _on_enter_active_state():
"""进入活跃状态"""
# 开始游戏逻辑
pass
func _on_enter_paused_state():
"""进入暂停状态"""
# 暂停游戏逻辑
get_tree().paused = true
func _on_enter_transitioning_state():
"""进入转换状态"""
# 场景转换中
pass
func play_bgm(bgm_path: String):
"""播放背景音乐"""
var bgm_player = audio_manager.get_node("BGM") as AudioStreamPlayer
if bgm_player and FileAccess.file_exists(bgm_path):
var audio_stream = load(bgm_path)
bgm_player.stream = audio_stream
bgm_player.play()
func play_sfx(sfx_path: String, position: Vector2 = Vector2.ZERO):
"""播放音效"""
var sfx_player = audio_manager.get_node("SFX") as AudioStreamPlayer2D
if sfx_player and FileAccess.file_exists(sfx_path):
var audio_stream = load(sfx_path)
sfx_player.stream = audio_stream
if position != Vector2.ZERO:
sfx_player.global_position = position
sfx_player.play()
func update_scene_data(key: String, value):
"""更新场景数据"""
scene_data[key] = value
scene_data_updated.emit(key, value)
func get_scene_data(key: String, default_value = null):
"""获取场景数据"""
return scene_data.get(key, default_value)
func cleanup():
"""清理场景资源"""
print("清理场景: ", SCENE_NAME)
# 断开信号连接
EventSystem.disconnect_event("game_paused", _on_game_paused)
EventSystem.disconnect_event("game_resumed", _on_game_resumed)
# 清理组件
if ui_layer:
for child in ui_layer.get_children():
if child.has_method("cleanup"):
child.cleanup()
if game_layer:
for child in game_layer.get_children():
if child.has_method("cleanup"):
child.cleanup()
if systems:
for child in systems.get_children():
if child.has_method("cleanup"):
child.cleanup()
# 停止音频
if audio_manager:
var bgm_player = audio_manager.get_node("BGM") as AudioStreamPlayer
if bgm_player:
bgm_player.stop()
# 事件处理
func _on_game_paused():
"""游戏暂停事件"""
if current_state == SceneState.ACTIVE:
change_state(SceneState.PAUSED)
func _on_game_resumed():
"""游戏恢复事件"""
if current_state == SceneState.PAUSED:
change_state(SceneState.ACTIVE)
get_tree().paused = false
# 输入处理
func _input(event):
"""处理输入事件"""
if current_state != SceneState.ACTIVE:
return
# 处理场景特定的输入
_handle_scene_input(event)
func _handle_scene_input(event):
"""处理场景特定输入"""
# 在子类中重写此方法
pass
# 生命周期方法
func _process(delta):
"""每帧更新"""
if current_state == SceneState.ACTIVE:
_update_scene(delta)
func _update_scene(delta):
"""更新场景逻辑"""
# 在子类中重写此方法
pass
func _physics_process(delta):
"""物理更新"""
if current_state == SceneState.ACTIVE:
_physics_update_scene(delta)
func _physics_update_scene(delta):
"""物理更新场景逻辑"""
# 在子类中重写此方法
pass
```
## 🎨 UI设计规范
### UI层级结构
```
UI (CanvasLayer)
├── Background (Control) # UI背景
├── MainContent (Control) # 主要内容
│ ├── Header (Control) # 头部区域
│ ├── Body (Control) # 主体区域
│ └── Footer (Control) # 底部区域
├── Overlay (Control) # 覆盖层
│ ├── Loading (Control) # 加载界面
│ ├── Dialog (Control) # 对话框
│ └── Toast (Control) # 提示消息
└── Debug (Control) # 调试信息
```
### UI组件规范
1. **响应式设计** - 使用Anchor和Margin实现自适应布局
2. **主题统一** - 使用统一的主题资源
3. **动画效果** - 添加适当的过渡动画
4. **无障碍支持** - 考虑键盘导航和屏幕阅读器
### UI脚本模板
```gdscript
# UIComponent.gd
extends Control
class_name UIComponent
signal ui_action(action_name: String, data: Dictionary)
@export var auto_initialize: bool = true
@export var animation_duration: float = 0.3
var is_visible: bool = false
var is_initialized: bool = false
func _ready():
if auto_initialize:
initialize()
func initialize():
"""初始化UI组件"""
if is_initialized:
return
# 设置初始状态
modulate.a = 0.0
visible = false
# 连接信号
_connect_signals()
is_initialized = true
func show_ui(animated: bool = true):
"""显示UI"""
if is_visible:
return
visible = true
is_visible = true
if animated:
var tween = create_tween()
tween.tween_property(self, "modulate:a", 1.0, animation_duration)
else:
modulate.a = 1.0
func hide_ui(animated: bool = true):
"""隐藏UI"""
if not is_visible:
return
is_visible = false
if animated:
var tween = create_tween()
tween.tween_property(self, "modulate:a", 0.0, animation_duration)
await tween.finished
visible = false
else:
modulate.a = 0.0
visible = false
func _connect_signals():
"""连接信号"""
# 在子类中重写
pass
```
## 🎮 游戏场景规范
### 游戏场景结构
```
GameScene (Node2D)
├── Background (ParallaxBackground) # 背景层
├── Environment (Node2D) # 环境层
│ ├── Terrain (TileMap) # 地形
│ ├── Props (Node2D) # 道具
│ └── Decorations (Node2D) # 装饰
├── Entities (Node2D) # 实体层
│ ├── Player (CharacterBody2D) # 玩家
│ ├── NPCs (Node2D) # NPC
│ ├── Enemies (Node2D) # 敌人
│ └── Items (Node2D) # 物品
├── Effects (Node2D) # 特效层
│ ├── Particles (Node2D) # 粒子效果
│ └── Animations (Node2D) # 动画效果
└── Camera (Camera2D) # 相机
```
### 性能优化
1. **对象池** - 重用频繁创建销毁的对象
2. **视锥剔除** - 只渲染可见区域的对象
3. **LOD系统** - 根据距离调整细节级别
4. **批量处理** - 合并相似的渲染调用
## 🔧 场景管理
### 场景切换
```gdscript
# 使用SceneManager进行场景切换
SceneManager.change_scene("game_scene", {
"level": 1,
"player_data": player_data
})
# 带过渡效果的场景切换
SceneManager.change_scene_with_transition("battle_scene", {
"enemy_data": enemy_data
}, "fade")
```
### 场景数据传递
```gdscript
# 发送场景数据
var scene_data = {
"player_level": 10,
"inventory": player_inventory,
"quest_progress": quest_data
}
SceneManager.change_scene("next_scene", scene_data)
# 接收场景数据
func _on_scene_data_received(data: Dictionary):
if data.has("player_level"):
player_level = data.player_level
if data.has("inventory"):
load_inventory(data.inventory)
```
## 🧪 场景测试
### 测试场景创建
```gdscript
# TestScene.gd
extends "res://scenes/BaseScene.gd"
func _ready():
super._ready()
# 设置测试环境
setup_test_environment()
# 运行测试用例
run_test_cases()
func setup_test_environment():
""""""
# 创建测试数据
# 设置测试状态
pass
func run_test_cases():
""""""
test_scene_initialization()
test_ui_interactions()
test_game_logic()
func test_scene_initialization():
""""""
assert(is_initialized, "")
assert(current_state == SceneState.READY, "READY")
func test_ui_interactions():
"""UI交互"""
# 模拟用户输入
# 验证UI响应
pass
func test_game_logic():
""""""
# 测试游戏规则
# 验证状态变化
pass
```
### 性能测试
```gdscript
# 性能监控
func _process(delta):
super._process(delta)
# 监控帧率
var fps = Engine.get_frames_per_second()
if fps < 30:
print("警告: 帧率过低: ", fps)
# 监控内存使用
var memory_usage = OS.get_static_memory_usage_by_type()
if memory_usage > 100 * 1024 * 1024: # 100MB
print("警告: 内存使用过高: ", memory_usage / 1024 / 1024, "MB")
```
## 📚 最佳实践
### 代码组织
1. **单一职责** - 每个场景只负责一个主要功能
2. **模块化** - 将复杂功能拆分为独立组件
3. **可测试** - 设计易于测试的场景结构
4. **文档化** - 为场景添加详细的文档说明
### 性能优化
1. **延迟加载** - 按需加载资源和组件
2. **对象复用** - 使用对象池管理频繁创建的对象
3. **批量操作** - 合并相似的操作减少开销
4. **内存管理** - 及时释放不需要的资源
### 用户体验
1. **响应式设计** - 支持不同分辨率和设备
2. **流畅动画** - 添加适当的过渡效果
3. **错误处理** - 优雅处理异常情况
4. **加载提示** - 为长时间操作提供进度反馈
## 🔍 常见问题
### Q: 如何处理场景间的数据传递?
A: 使用SceneManager的场景切换方法传递数据或通过全局单例存储共享数据。
### Q: 场景性能如何优化?
A: 使用对象池、视锥剔除、LOD系统避免在_process中执行重复计算。
### Q: 如何调试场景问题?
A: 使用Godot的远程调试器添加性能监控编写场景测试用例。
### Q: 场景切换如何添加过渡效果?
A: 使用SceneManager的过渡系统或自定义Tween动画实现过渡效果。
---
**记住:良好的场景设计是游戏体验的基础!**