优化项目架构
This commit is contained in:
76
SproutFarm-Frontend/GlobalScript/GlobalFunctions.gd
Normal file
76
SproutFarm-Frontend/GlobalScript/GlobalFunctions.gd
Normal file
@@ -0,0 +1,76 @@
|
||||
extends Node
|
||||
|
||||
# 全局通用功能脚本
|
||||
# 使用方法:首先在项目设置的自动加载中添加此脚本,然后在任何地方使用 GlobalFunctions.函数名() 调用
|
||||
|
||||
func _ready():
|
||||
print("全局函数库已加载")
|
||||
|
||||
# 写入 TXT 文件
|
||||
func write_txt_file(file_path: String, text: String, append: bool = false) -> void:
|
||||
var file
|
||||
if append == true:
|
||||
file = FileAccess.open(file_path, FileAccess.READ_WRITE) # 追加模式
|
||||
if file:
|
||||
file.seek_end() # 移动光标到文件末尾
|
||||
else:
|
||||
file = FileAccess.open(file_path, FileAccess.WRITE) # 覆盖模式
|
||||
if file:
|
||||
file.store_string(text)
|
||||
file.close()
|
||||
if has_node("/root/ToastScript"):
|
||||
get_node("/root/ToastScript").show("游戏已保存!", Color.GREEN, 5.0, 1.0)
|
||||
else:
|
||||
print("写入文件时打开失败: ", file_path)
|
||||
if has_node("/root/ToastScript"):
|
||||
get_node("/root/ToastScript").show("写入文件时打开失败!", Color.RED, 5.0, 1.0)
|
||||
|
||||
|
||||
# 读取 TXT 文件
|
||||
func read_txt_file(file_path: String) -> String:
|
||||
var file = FileAccess.open(file_path, FileAccess.READ)
|
||||
if file:
|
||||
var text = file.get_as_text()
|
||||
file.close()
|
||||
return text
|
||||
else:
|
||||
print("打开文件失败: ", file_path)
|
||||
return "false"
|
||||
|
||||
|
||||
#生成随机数-用于作物随机死亡
|
||||
func random_probability(probability: float) -> bool:
|
||||
# 确保传入的概率值在 0 到 1 之间
|
||||
if probability*0.001 < 0.0 or probability*0.001 > 1.0:
|
||||
print("概率值必须在 0 和 1 之间")
|
||||
return false
|
||||
|
||||
# 生成一个 0 到 1 之间的随机数
|
||||
var random_value = randf()
|
||||
|
||||
# 如果随机数小于等于概率值,则返回 true
|
||||
return random_value <= (probability*0.001)
|
||||
|
||||
|
||||
# 格式化时间为可读字符串
|
||||
func format_time(seconds: int) -> String:
|
||||
var minutes = seconds / 60
|
||||
seconds = seconds % 60
|
||||
var hours = minutes / 60
|
||||
minutes = minutes % 60
|
||||
|
||||
if hours > 0:
|
||||
return "%02d:%02d:%02d" % [hours, minutes, seconds]
|
||||
else:
|
||||
return "%02d:%02d" % [minutes, seconds]
|
||||
|
||||
|
||||
#双击切换UI事件-比如按一下打开再按一下关闭
|
||||
func double_click_close(node):
|
||||
if node.visible == false:
|
||||
node.show()
|
||||
pass
|
||||
else :
|
||||
node.hide()
|
||||
pass
|
||||
pass
|
||||
1
SproutFarm-Frontend/GlobalScript/GlobalFunctions.gd.uid
Normal file
1
SproutFarm-Frontend/GlobalScript/GlobalFunctions.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bv4lf4v2c73pb
|
||||
17
SproutFarm-Frontend/GlobalScript/GlobalVariables.gd
Normal file
17
SproutFarm-Frontend/GlobalScript/GlobalVariables.gd
Normal file
@@ -0,0 +1,17 @@
|
||||
extends Node
|
||||
|
||||
const client_version :String = "2.2.0" #记录客户端版本
|
||||
|
||||
var isZoomDisabled :bool = false
|
||||
|
||||
const server_configs = [
|
||||
{"host": "127.0.0.1", "port": 7070, "name": "本地"},
|
||||
#{"host": "192.168.31.233", "port": 6060, "name": "家里面局域网"},
|
||||
#{"host": "192.168.31.205", "port": 6060, "name": "家里面电脑"},
|
||||
#{"host": "192.168.1.110", "port": 4040, "name": "萌芽局域网"},
|
||||
#{"host": "47.108.90.0", "port": 4040, "name": "成都内网穿透"}#成都内网穿透
|
||||
#{"host": "47.108.90.0", "port": 6060, "name": "成都公网"}#成都服务器
|
||||
]
|
||||
|
||||
const DisableWeatherDisplay :bool = false #是否禁止显示天气
|
||||
const BackgroundMusicVolume = 1.0 #背景音乐音量
|
||||
1
SproutFarm-Frontend/GlobalScript/GlobalVariables.gd.uid
Normal file
1
SproutFarm-Frontend/GlobalScript/GlobalVariables.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://co5rk48low4kq
|
||||
239
SproutFarm-Frontend/GlobalScript/ResourceLoadingDebugger.gd
Normal file
239
SproutFarm-Frontend/GlobalScript/ResourceLoadingDebugger.gd
Normal file
@@ -0,0 +1,239 @@
|
||||
extends Node
|
||||
|
||||
## 资源加载调试器
|
||||
## 用于诊断和监控资源加载问题
|
||||
|
||||
class_name ResourceLoadingDebugger
|
||||
|
||||
# 调试信息收集
|
||||
var loading_stats: Dictionary = {}
|
||||
var failed_resources: Array = []
|
||||
var performance_metrics: Dictionary = {}
|
||||
|
||||
## 初始化调试器
|
||||
func _ready():
|
||||
print("[ResourceLoadingDebugger] 资源加载调试器已启动")
|
||||
_init_performance_monitoring()
|
||||
|
||||
## 初始化性能监控
|
||||
func _init_performance_monitoring():
|
||||
performance_metrics = {
|
||||
"total_load_time": 0.0,
|
||||
"average_load_time": 0.0,
|
||||
"peak_memory_usage": 0,
|
||||
"current_memory_usage": 0,
|
||||
"successful_loads": 0,
|
||||
"failed_loads": 0
|
||||
}
|
||||
|
||||
## 记录资源加载开始
|
||||
func start_loading_resource(resource_path: String) -> int:
|
||||
var start_time = Time.get_ticks_msec()
|
||||
var load_id = randi()
|
||||
|
||||
loading_stats[load_id] = {
|
||||
"path": resource_path,
|
||||
"start_time": start_time,
|
||||
"status": "loading"
|
||||
}
|
||||
|
||||
return load_id
|
||||
|
||||
## 记录资源加载完成
|
||||
func finish_loading_resource(load_id: int, success: bool, resource: Resource = null):
|
||||
if not loading_stats.has(load_id):
|
||||
return
|
||||
|
||||
var end_time = Time.get_ticks_msec()
|
||||
var load_info = loading_stats[load_id]
|
||||
var load_time = end_time - load_info["start_time"]
|
||||
|
||||
load_info["end_time"] = end_time
|
||||
load_info["load_time"] = load_time
|
||||
load_info["success"] = success
|
||||
load_info["status"] = "completed"
|
||||
|
||||
# 更新性能指标
|
||||
performance_metrics["total_load_time"] += load_time
|
||||
if success:
|
||||
performance_metrics["successful_loads"] += 1
|
||||
if resource:
|
||||
load_info["resource_size"] = _get_resource_memory_size(resource)
|
||||
else:
|
||||
performance_metrics["failed_loads"] += 1
|
||||
failed_resources.append(load_info["path"])
|
||||
|
||||
# 计算平均加载时间
|
||||
var total_loads = performance_metrics["successful_loads"] + performance_metrics["failed_loads"]
|
||||
if total_loads > 0:
|
||||
performance_metrics["average_load_time"] = performance_metrics["total_load_time"] / total_loads
|
||||
|
||||
# 更新内存使用情况
|
||||
_update_memory_usage()
|
||||
|
||||
## 获取资源内存大小估算
|
||||
func _get_resource_memory_size(resource: Resource) -> int:
|
||||
if resource is Texture2D:
|
||||
var texture = resource as Texture2D
|
||||
var size = texture.get_size()
|
||||
# 估算:RGBA * 宽 * 高 * 4字节
|
||||
return size.x * size.y * 4
|
||||
return 0
|
||||
|
||||
## 更新内存使用情况
|
||||
func _update_memory_usage():
|
||||
var current_memory = OS.get_static_memory_usage()
|
||||
performance_metrics["current_memory_usage"] = current_memory
|
||||
|
||||
if current_memory > performance_metrics["peak_memory_usage"]:
|
||||
performance_metrics["peak_memory_usage"] = current_memory
|
||||
|
||||
## 检测设备资源加载能力
|
||||
func detect_device_capabilities() -> Dictionary:
|
||||
var capabilities = {}
|
||||
|
||||
# 设备基本信息
|
||||
capabilities["platform"] = OS.get_name()
|
||||
capabilities["processor_count"] = OS.get_processor_count()
|
||||
capabilities["memory_total"] = OS.get_static_memory_usage()
|
||||
|
||||
# 图形信息
|
||||
var rendering_device = RenderingServer.get_rendering_device()
|
||||
if rendering_device:
|
||||
capabilities["gpu_name"] = rendering_device.get_device_name()
|
||||
capabilities["gpu_vendor"] = rendering_device.get_device_vendor_name()
|
||||
|
||||
# 存储信息
|
||||
capabilities["user_data_dir"] = OS.get_user_data_dir()
|
||||
|
||||
# 性能测试
|
||||
capabilities["texture_loading_speed"] = _benchmark_texture_loading()
|
||||
|
||||
return capabilities
|
||||
|
||||
## 基准测试纹理加载速度
|
||||
func _benchmark_texture_loading() -> float:
|
||||
var test_path = "res://assets/作物/默认/0.webp"
|
||||
if not ResourceLoader.exists(test_path):
|
||||
return -1.0
|
||||
|
||||
var start_time = Time.get_ticks_msec()
|
||||
var iterations = 10
|
||||
|
||||
for i in range(iterations):
|
||||
var texture = ResourceLoader.load(test_path)
|
||||
if not texture:
|
||||
return -1.0
|
||||
|
||||
var end_time = Time.get_ticks_msec()
|
||||
return float(end_time - start_time) / iterations
|
||||
|
||||
## 诊断资源加载问题
|
||||
func diagnose_loading_issues() -> Dictionary:
|
||||
var diagnosis = {
|
||||
"issues_found": [],
|
||||
"recommendations": [],
|
||||
"severity": "normal"
|
||||
}
|
||||
|
||||
# 检查失败率
|
||||
var total_loads = performance_metrics["successful_loads"] + performance_metrics["failed_loads"]
|
||||
if total_loads > 0:
|
||||
var failure_rate = float(performance_metrics["failed_loads"]) / total_loads
|
||||
if failure_rate > 0.1: # 失败率超过10%
|
||||
diagnosis["issues_found"].append("资源加载失败率过高: %.1f%%" % (failure_rate * 100))
|
||||
diagnosis["recommendations"].append("检查资源文件完整性和路径正确性")
|
||||
diagnosis["severity"] = "warning"
|
||||
|
||||
if failure_rate > 0.3: # 失败率超过30%
|
||||
diagnosis["severity"] = "critical"
|
||||
diagnosis["recommendations"].append("考虑降低资源质量或减少同时加载的资源数量")
|
||||
|
||||
# 检查加载速度
|
||||
if performance_metrics["average_load_time"] > 100: # 平均加载时间超过100ms
|
||||
diagnosis["issues_found"].append("资源加载速度较慢: %.1fms" % performance_metrics["average_load_time"])
|
||||
diagnosis["recommendations"].append("考虑使用多线程加载或预加载常用资源")
|
||||
if diagnosis["severity"] == "normal":
|
||||
diagnosis["severity"] = "warning"
|
||||
|
||||
# 检查内存使用
|
||||
var memory_mb = performance_metrics["peak_memory_usage"] / (1024 * 1024)
|
||||
if memory_mb > 500: # 峰值内存使用超过500MB
|
||||
diagnosis["issues_found"].append("内存使用过高: %.1fMB" % memory_mb)
|
||||
diagnosis["recommendations"].append("实施LRU缓存清理或降低缓存大小")
|
||||
if diagnosis["severity"] == "normal":
|
||||
diagnosis["severity"] = "warning"
|
||||
|
||||
# 检查平台特定问题
|
||||
var platform = OS.get_name()
|
||||
if platform in ["Android", "iOS"]:
|
||||
if performance_metrics["failed_loads"] > 5:
|
||||
diagnosis["issues_found"].append("移动设备上资源加载失败较多")
|
||||
diagnosis["recommendations"].append("移动设备内存有限,建议降低资源质量或实施更积极的缓存清理")
|
||||
|
||||
return diagnosis
|
||||
|
||||
## 生成资源加载报告
|
||||
func generate_loading_report() -> String:
|
||||
var report = "=== 资源加载调试报告 ===\n\n"
|
||||
|
||||
# 基本统计
|
||||
report += "基本统计:\n"
|
||||
report += " 成功加载: %d\n" % performance_metrics["successful_loads"]
|
||||
report += " 失败加载: %d\n" % performance_metrics["failed_loads"]
|
||||
report += " 平均加载时间: %.1fms\n" % performance_metrics["average_load_time"]
|
||||
report += " 总加载时间: %.1fs\n" % (performance_metrics["total_load_time"] / 1000.0)
|
||||
report += " 峰值内存使用: %.1fMB\n\n" % (performance_metrics["peak_memory_usage"] / (1024 * 1024))
|
||||
|
||||
# 设备信息
|
||||
var capabilities = detect_device_capabilities()
|
||||
report += "设备信息:\n"
|
||||
report += " 平台: %s\n" % capabilities.get("platform", "未知")
|
||||
report += " CPU核心数: %d\n" % capabilities.get("processor_count", 0)
|
||||
report += " 纹理加载速度: %.1fms\n\n" % capabilities.get("texture_loading_speed", -1)
|
||||
|
||||
# 失败的资源
|
||||
if failed_resources.size() > 0:
|
||||
report += "加载失败的资源:\n"
|
||||
for i in range(min(10, failed_resources.size())): # 只显示前10个
|
||||
report += " - %s\n" % failed_resources[i]
|
||||
if failed_resources.size() > 10:
|
||||
report += " ... 还有 %d 个失败的资源\n" % (failed_resources.size() - 10)
|
||||
report += "\n"
|
||||
|
||||
# 诊断结果
|
||||
var diagnosis = diagnose_loading_issues()
|
||||
report += "诊断结果 [%s]:\n" % diagnosis["severity"].to_upper()
|
||||
for issue in diagnosis["issues_found"]:
|
||||
report += " 问题: %s\n" % issue
|
||||
for recommendation in diagnosis["recommendations"]:
|
||||
report += " 建议: %s\n" % recommendation
|
||||
|
||||
return report
|
||||
|
||||
## 清理调试数据
|
||||
func clear_debug_data():
|
||||
loading_stats.clear()
|
||||
failed_resources.clear()
|
||||
_init_performance_monitoring()
|
||||
print("[ResourceLoadingDebugger] 调试数据已清理")
|
||||
|
||||
## 导出调试数据到文件
|
||||
func export_debug_data_to_file():
|
||||
var report = generate_loading_report()
|
||||
var datetime = Time.get_datetime_dict_from_system()
|
||||
var filename = "resource_loading_debug_%04d%02d%02d_%02d%02d%02d.txt" % [
|
||||
datetime.year, datetime.month, datetime.day,
|
||||
datetime.hour, datetime.minute, datetime.second
|
||||
]
|
||||
|
||||
var file_path = OS.get_user_data_dir() + "/" + filename
|
||||
var file = FileAccess.open(file_path, FileAccess.WRITE)
|
||||
if file:
|
||||
file.store_string(report)
|
||||
file.close()
|
||||
print("[ResourceLoadingDebugger] 调试报告已导出到: ", file_path)
|
||||
return file_path
|
||||
else:
|
||||
print("[ResourceLoadingDebugger] 导出调试报告失败")
|
||||
return ""
|
||||
@@ -0,0 +1 @@
|
||||
uid://dk6uoldjqtc0p
|
||||
152
SproutFarm-Frontend/GlobalScript/Toast.gd
Normal file
152
SproutFarm-Frontend/GlobalScript/Toast.gd
Normal file
@@ -0,0 +1,152 @@
|
||||
# Toast.gd - 合并的Toast系统
|
||||
extends Node
|
||||
|
||||
# Toast节点缓存
|
||||
var toast_container: Control
|
||||
|
||||
func _ready():
|
||||
# 延迟创建Toast容器,避免在节点初始化期间添加子节点的冲突
|
||||
setup_toast_container.call_deferred()
|
||||
|
||||
func setup_toast_container():
|
||||
# 防止重复创建
|
||||
if toast_container and is_instance_valid(toast_container):
|
||||
return
|
||||
|
||||
# 创建一个CanvasLayer来确保Toast始终在最顶层
|
||||
var canvas_layer = CanvasLayer.new()
|
||||
canvas_layer.name = "ToastCanvasLayer"
|
||||
canvas_layer.layer = 100 # 设置一个很高的层级值
|
||||
|
||||
# 创建一个容器来放置所有Toast
|
||||
toast_container = Control.new()
|
||||
toast_container.name = "ToastContainer"
|
||||
toast_container.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
toast_container.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
|
||||
# 将容器添加到CanvasLayer中
|
||||
canvas_layer.add_child(toast_container)
|
||||
|
||||
# 尝试添加到main/UI节点,如果失败则添加到根节点
|
||||
var ui_node = get_node_or_null("/root/main/UI")
|
||||
if ui_node:
|
||||
ui_node.add_child.call_deferred(canvas_layer)
|
||||
print("Toast容器已添加到 main/UI 节点")
|
||||
else:
|
||||
# 如果没有UI节点,直接添加到根节点
|
||||
get_tree().root.add_child.call_deferred(canvas_layer)
|
||||
print("Toast容器已添加到根节点")
|
||||
|
||||
|
||||
func show(text: String,
|
||||
color: Color = Color.WHITE,
|
||||
duration: float = 2.0,
|
||||
fade_duration: float = 0.5) -> void:
|
||||
|
||||
# 确保容器存在且有效
|
||||
if not toast_container or not is_instance_valid(toast_container) or not toast_container.get_parent():
|
||||
setup_toast_container.call_deferred()
|
||||
# 等待容器设置完成
|
||||
await get_tree().process_frame
|
||||
await get_tree().process_frame # 额外等待一帧确保完成
|
||||
|
||||
# 再次检查容器是否有效
|
||||
if not toast_container or not is_instance_valid(toast_container):
|
||||
print("警告:Toast容器初始化失败,无法显示Toast")
|
||||
return
|
||||
|
||||
# 创建Toast UI
|
||||
var toast_panel = create_toast_ui(text, color)
|
||||
toast_container.add_child(toast_panel)
|
||||
|
||||
# 显示动画和自动消失
|
||||
show_toast_animation(toast_panel, duration, fade_duration)
|
||||
|
||||
func create_toast_ui(text: String, color: Color) -> PanelContainer:
|
||||
# 创建主容器
|
||||
var panel = PanelContainer.new()
|
||||
panel.name = "Toast_" + str(Time.get_ticks_msec())
|
||||
|
||||
# 设置样式
|
||||
var style_box = StyleBoxFlat.new()
|
||||
style_box.bg_color = Color(0, 0, 0, 0.8) # 半透明黑色背景
|
||||
style_box.corner_radius_top_left = 8
|
||||
style_box.corner_radius_top_right = 8
|
||||
style_box.corner_radius_bottom_left = 8
|
||||
style_box.corner_radius_bottom_right = 8
|
||||
style_box.content_margin_top = 12
|
||||
style_box.content_margin_bottom = 12
|
||||
style_box.content_margin_left = 16
|
||||
style_box.content_margin_right = 16
|
||||
panel.add_theme_stylebox_override("panel", style_box)
|
||||
|
||||
# 创建文本标签
|
||||
var label = Label.new()
|
||||
label.text = text
|
||||
label.modulate = color
|
||||
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
|
||||
# 设置字体大小
|
||||
label.add_theme_font_size_override("font_size", 16)
|
||||
|
||||
panel.add_child(label)
|
||||
|
||||
# 定位Toast(屏幕中央偏下)
|
||||
position_toast(panel)
|
||||
|
||||
return panel
|
||||
|
||||
func position_toast(toast_panel: PanelContainer):
|
||||
# 设置位置为屏幕中央偏下
|
||||
toast_panel.set_anchors_and_offsets_preset(Control.PRESET_CENTER)
|
||||
toast_panel.position.y += 100 # 向下偏移
|
||||
|
||||
# 调整现有Toast的位置,避免重叠
|
||||
var existing_toasts = []
|
||||
for child in toast_container.get_children():
|
||||
if child != toast_panel and child is PanelContainer:
|
||||
existing_toasts.append(child)
|
||||
|
||||
# 向上堆叠
|
||||
for i in range(existing_toasts.size()):
|
||||
var existing_toast = existing_toasts[existing_toasts.size() - 1 - i]
|
||||
var tween = create_tween()
|
||||
tween.tween_property(existing_toast, "position:y",
|
||||
existing_toast.position.y - 60, 0.3)
|
||||
|
||||
func show_toast_animation(toast_panel: PanelContainer, duration: float, fade_duration: float):
|
||||
# 初始状态:完全透明并稍微向上
|
||||
toast_panel.modulate.a = 0.0
|
||||
toast_panel.position.y += 20
|
||||
|
||||
# 淡入动画
|
||||
var fade_in_tween = create_tween()
|
||||
fade_in_tween.parallel().tween_property(toast_panel, "modulate:a", 1.0, 0.3)
|
||||
fade_in_tween.parallel().tween_property(toast_panel, "position:y",
|
||||
toast_panel.position.y - 20, 0.3)
|
||||
fade_in_tween.set_ease(Tween.EASE_OUT)
|
||||
|
||||
# 等待显示时间
|
||||
await get_tree().create_timer(duration).timeout
|
||||
|
||||
# 淡出动画
|
||||
var fade_out_tween = create_tween()
|
||||
fade_out_tween.tween_property(toast_panel, "modulate:a", 0.0, fade_duration)
|
||||
await fade_out_tween.finished
|
||||
|
||||
# 移除节点
|
||||
toast_panel.queue_free()
|
||||
|
||||
# 便捷方法
|
||||
func show_success(text: String, duration: float = 2.0):
|
||||
show(text, Color.GREEN, duration)
|
||||
|
||||
func show_error(text: String, duration: float = 3.0):
|
||||
show(text, Color.RED, duration)
|
||||
|
||||
func show_warning(text: String, duration: float = 2.5):
|
||||
show(text, Color.YELLOW, duration)
|
||||
|
||||
func show_info(text: String, duration: float = 2.0):
|
||||
show(text, Color.CYAN, duration)
|
||||
1
SproutFarm-Frontend/GlobalScript/Toast.gd.uid
Normal file
1
SproutFarm-Frontend/GlobalScript/Toast.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://336lik63ehtt
|
||||
Reference in New Issue
Block a user