Files
moyin 3175c98ea3 refactor:实现新的项目结构组织
- 添加 _Core/components/ 和 _Core/utils/ 目录
- 重新组织 scenes/ 目录结构,按功能分类
- 迁移 StringUtils.gd 到新的 _Core/utils/ 位置
- 迁移 AuthScene.gd 到新的 scenes/ui/ 位置
- 添加 AI 文档支持目录 docs/AI_docs/
- 添加开发参考文档 claude.md
2026-01-02 00:58:34 +08:00

617 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🎯 管理器模板集合
> 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. 添加必要的错误处理和日志记录