1
This commit is contained in:
2025-06-23 16:09:04 +08:00
parent 94f09b8dd9
commit 12fbe9debf
757 changed files with 11656 additions and 13580 deletions

87
GUI/AcceptDialog.gd Normal file
View File

@@ -0,0 +1,87 @@
extends AcceptDialog
@export var dialog_min_size := Vector2(400, 200)
@export var ok_text := "确认"
@export var cancel_text := "取消"
func _ready() -> void:
# 设置弹窗最小尺寸
self.set("rect_min_size", dialog_min_size)
# 设置标题和内容(可通过函数修改)
set_dialog_title("默认标题")
set_dialog_content("默认内容")
# 添加取消按钮
var cancel_btn = self.add_cancel_button(cancel_text)
_customize_button(cancel_btn)
# 获取并设置确认按钮
var ok_btn = self.get_ok_button()
ok_btn.text = ok_text
_customize_button(ok_btn)
# 设置按钮样式属性
self.add_theme_constant_override("buttons_min_height", 40)
self.add_theme_constant_override("buttons_min_width", 120)
self.add_theme_constant_override("buttons_separation", 16)
# 添加样式美化
_apply_custom_theme()
func set_dialog_position(new_position :Vector2):
self.position = new_position
pass
func set_dialog_title(title: String) -> void:
self.title = title
func set_dialog_content(content: String) -> void:
self.dialog_text = content
func set_ok_text(text: String) -> void:
ok_text = text
get_ok_button().text = text
func set_cancel_text(text: String) -> void:
cancel_text = text
# 注意add_cancel_button 只能调用一次,想动态更新需要重建按钮
func _customize_button(button: Button) -> void:
button.custom_minimum_size = Vector2(120, 40)
button.add_theme_color_override("font_color", Color.WHITE)
button.add_theme_color_override("font_color_pressed", Color.WHITE)
button.add_theme_color_override("font_color_hover", Color.WHITE)
button.add_theme_color_override("bg_color", Color("3c82f6")) # 蓝色
button.add_theme_color_override("bg_color_hover", Color("2563eb"))
button.add_theme_color_override("bg_color_pressed", Color("1e40af"))
button.add_theme_color_override("bg_color_disabled", Color("94a3b8"))
func _apply_custom_theme() -> void:
# 设置面板背景颜色
var panel_style := StyleBoxFlat.new()
panel_style.bg_color = Color("f8fafc") # very light gray
panel_style.set_border_width_all(2)
panel_style.border_color = Color("cbd5e1")
self.add_theme_stylebox_override("panel", panel_style) # ✅ 修正方法名
# 设置文字颜色(内容部分)
var label = self.get_label()
label.add_theme_color_override("font_color", Color("1e293b")) # 深灰蓝
# 确认按钮点击
func _on_confirmed() -> void:
print("确认按钮被点击")
# 取消按钮点击
func _on_canceled() -> void:
print("取消按钮被点击")

1
GUI/AcceptDialog.gd.uid Normal file
View File

@@ -0,0 +1 @@
uid://ce8xcp770tolo

15
GUI/AcceptDialog.tscn Normal file
View File

@@ -0,0 +1,15 @@
[gd_scene load_steps=2 format=3 uid="uid://btp1h6hic2sin"]
[ext_resource type="Script" path="res://GUI/AcceptDialog.gd" id="1_yc5jp"]
[node name="AcceptDialog" type="AcceptDialog"]
auto_translate_mode = 1
title = "是否购买"
initial_position = 1
size = Vector2i(300, 200)
visible = true
ok_button_text = "确定"
script = ExtResource("1_yc5jp")
[connection signal="canceled" from="." to="." method="_on_canceled"]
[connection signal="confirmed" from="." to="." method="_on_confirmed"]

422
GUI/DailyCheckInPanel.gd Normal file
View File

@@ -0,0 +1,422 @@
extends Panel
class_name DailyCheckInPanel
## 每日签到系统 - 后端对接版本
## 功能:与服务器对接的签到系统,支持实时数据同步
## 奖励平衡性已根据 crop_data.json 调整
# =============================================================================
# 信号定义 - 用于与后端系统通信
# =============================================================================
signal check_in_completed(rewards: Dictionary) # 签到完成信号
signal reward_claimed(reward_type: String, amount: int) # 奖励领取信号
signal check_in_data_loaded(data: Dictionary) # 签到数据加载完成信号
signal check_in_failed(error_message: String) # 签到失败信号
# =============================================================================
# 节点引用
# =============================================================================
@onready var daily_check_in_history: RichTextLabel = $Scroll/DailyCheckInHistory
@onready var daily_check_in_reward: RichTextLabel = $DailyCheckInReward
@onready var daily_check_in_button: Button = $DailyCheckInButton
# =============================================================================
# 数据存储
# =============================================================================
var check_in_data: Dictionary = {}
var today_date: String
var consecutive_days: int = 0
var has_checked_in_today: bool = false
# 网络管理器引用
var network_manager
var main_game
# =============================================================================
# 奖励配置系统 - 根据 crop_data.json 平衡调整
# =============================================================================
var reward_configs: Dictionary = {
"coins": {
"min": 200,
"max": 500,
"name": "钱币",
"color": "#FFD700",
"icon": "💰"
},
"exp": {
"min": 50,
"max": 120,
"name": "经验",
"color": "#00BFFF",
"icon": ""
},
# 种子配置根据 crop_data.json 的作物等级和价值设定
"seeds": {
"普通": [
{"name": "小麦", "color": "#F4A460", "icon": "🌱", "rarity_color": "#FFFFFF"},
{"name": "胡萝卜", "color": "#FFA500", "icon": "🌱", "rarity_color": "#FFFFFF"},
{"name": "土豆", "color": "#D2691E", "icon": "🌱", "rarity_color": "#FFFFFF"},
{"name": "稻谷", "color": "#DAA520", "icon": "🌱", "rarity_color": "#FFFFFF"}
],
"优良": [
{"name": "玉米", "color": "#FFD700", "icon": "🌱", "rarity_color": "#00FF00"},
{"name": "番茄", "color": "#FF6347", "icon": "🌱", "rarity_color": "#00FF00"},
{"name": "洋葱", "color": "#DDA0DD", "icon": "🌱", "rarity_color": "#00FF00"},
{"name": "大豆", "color": "#8FBC8F", "icon": "🌱", "rarity_color": "#00FF00"},
{"name": "豌豆", "color": "#90EE90", "icon": "🌱", "rarity_color": "#00FF00"},
{"name": "黄瓜", "color": "#32CD32", "icon": "🌱", "rarity_color": "#00FF00"},
{"name": "大白菜", "color": "#F0FFF0", "icon": "🌱", "rarity_color": "#00FF00"}
],
"稀有": [
{"name": "草莓", "color": "#FF69B4", "icon": "🌱", "rarity_color": "#0080FF"},
{"name": "花椰菜", "color": "#F5F5DC", "icon": "🌱", "rarity_color": "#0080FF"},
{"name": "柿子", "color": "#FF4500", "icon": "🌱", "rarity_color": "#0080FF"},
{"name": "蓝莓", "color": "#4169E1", "icon": "🌱", "rarity_color": "#0080FF"},
{"name": "树莓", "color": "#DC143C", "icon": "🌱", "rarity_color": "#0080FF"}
],
"史诗": [
{"name": "葡萄", "color": "#9370DB", "icon": "🌱", "rarity_color": "#8A2BE2"},
{"name": "南瓜", "color": "#FF8C00", "icon": "🌱", "rarity_color": "#8A2BE2"},
{"name": "芦笋", "color": "#9ACD32", "icon": "🌱", "rarity_color": "#8A2BE2"},
{"name": "茄子", "color": "#9400D3", "icon": "🌱", "rarity_color": "#8A2BE2"},
{"name": "向日葵", "color": "#FFD700", "icon": "🌱", "rarity_color": "#8A2BE2"},
{"name": "蕨菜", "color": "#228B22", "icon": "🌱", "rarity_color": "#8A2BE2"}
],
"传奇": [
{"name": "西瓜", "color": "#FF69B4", "icon": "🌱", "rarity_color": "#FF8C00"},
{"name": "甘蔗", "color": "#DDA0DD", "icon": "🌱", "rarity_color": "#FF8C00"},
{"name": "香草", "color": "#98FB98", "icon": "🌱", "rarity_color": "#FF8C00"},
{"name": "甜菜", "color": "#DC143C", "icon": "🌱", "rarity_color": "#FF8C00"},
{"name": "人参", "color": "#DAA520", "icon": "🌱", "rarity_color": "#FF8C00"},
{"name": "富贵竹", "color": "#32CD32", "icon": "🌱", "rarity_color": "#FF8C00"},
{"name": "芦荟", "color": "#9ACD32", "icon": "🌱", "rarity_color": "#FF8C00"},
{"name": "哈密瓜", "color": "#FFB6C1", "icon": "🌱", "rarity_color": "#FF8C00"}
]
}
}
# =============================================================================
# 系统初始化
# =============================================================================
func _ready() -> void:
_initialize_system()
func _initialize_system() -> void:
"""初始化签到系统"""
daily_check_in_reward.hide()
today_date = Time.get_date_string_from_system()
# 获取网络管理器和主游戏引用
network_manager = get_node("/root/main/UI/TCPNetworkManager")
main_game = get_node("/root/main")
_update_display()
_check_daily_status()
# 从服务器加载签到数据
if network_manager and network_manager.is_connected_to_server():
network_manager.sendGetCheckInData()
# =============================================================================
# 网络后端交互方法
# =============================================================================
## 处理服务器签到响应
func handle_daily_check_in_response(response: Dictionary) -> void:
var success = response.get("success", false)
var message = response.get("message", "")
if success:
var rewards = response.get("rewards", {})
consecutive_days = response.get("consecutive_days", 0)
has_checked_in_today = true
# 显示奖励
_show_reward_animation(rewards)
# 更新按钮状态
_set_button_state(false, "已签到", Color(0.7, 0.7, 0.7, 1))
# 发送完成信号
check_in_completed.emit(rewards)
# 发送奖励信号
for reward_type in rewards.keys():
if reward_type == "seeds":
for seed_reward in rewards.seeds:
reward_claimed.emit("seed_" + seed_reward.name, seed_reward.quantity)
elif reward_type in ["coins", "exp", "bonus_coins", "bonus_exp"]:
reward_claimed.emit(reward_type, rewards[reward_type])
Toast.show(message, Color.GREEN)
print("签到成功: ", message)
else:
has_checked_in_today = response.get("has_checked_in", false)
_set_button_state(false, "已签到", Color(0.7, 0.7, 0.7, 1)) if has_checked_in_today else _set_button_state(true, "签到", Color(1, 1, 0.52549, 1))
check_in_failed.emit(message)
Toast.show(message, Color.RED)
print("签到失败: ", message)
## 处理服务器签到数据响应
func handle_check_in_data_response(response: Dictionary) -> void:
var success = response.get("success", false)
if success:
check_in_data = response.get("check_in_data", {})
consecutive_days = response.get("consecutive_days", 0)
has_checked_in_today = response.get("has_checked_in_today", false)
today_date = response.get("current_date", Time.get_date_string_from_system())
# 更新显示
_update_display()
_check_daily_status()
# 发送数据加载完成信号
check_in_data_loaded.emit(check_in_data)
print("签到数据加载成功,连续签到:", consecutive_days, "")
else:
print("加载签到数据失败")
# =============================================================================
# 核心业务逻辑
# =============================================================================
## 检查今日签到状态
func _check_daily_status() -> void:
if has_checked_in_today:
_set_button_state(false, "已签到", Color(0.7, 0.7, 0.7, 1))
else:
_set_button_state(true, "签到", Color(1, 1, 0.52549, 1))
## 设置按钮状态
func _set_button_state(enabled: bool, text: String, color: Color) -> void:
daily_check_in_button.disabled = not enabled
daily_check_in_button.text = text
daily_check_in_button.modulate = color
## 执行签到
func execute_check_in() -> void:
if has_checked_in_today:
Toast.show("今日已签到,请明日再来", Color.ORANGE)
return
if not network_manager or not network_manager.is_connected_to_server():
Toast.show("未连接到服务器,无法签到", Color.RED)
return
# 发送签到请求到服务器
network_manager.sendDailyCheckIn()
daily_check_in_button.disabled = true
daily_check_in_button.text = "签到中..."
# 3秒后重新启用按钮防止网络超时
await get_tree().create_timer(3.0).timeout
if daily_check_in_button.disabled and daily_check_in_button.text == "签到中...":
daily_check_in_button.disabled = false
daily_check_in_button.text = "签到"
## 显示奖励动画
func _show_reward_animation(rewards: Dictionary) -> void:
daily_check_in_reward.text = _format_reward_text(rewards)
daily_check_in_reward.show()
# 创建动画效果
var tween = create_tween()
tween.parallel().tween_method(_animate_reward_display, 0.0, 1.0, 0.5)
## 奖励显示动画
func _animate_reward_display(progress: float) -> void:
daily_check_in_reward.modulate.a = progress
var scale = 0.8 + (0.2 * progress)
daily_check_in_reward.scale = Vector2(scale, scale)
# =============================================================================
# UI显示格式化
# =============================================================================
## 格式化奖励显示文本
func _format_reward_text(rewards: Dictionary) -> String:
var text = ""
# 显示连续签到信息
text += "[center][color=#FF69B4]🔥 连续签到第%d天 🔥[/color][/center]\n" % consecutive_days
if consecutive_days > 1:
var multiplier = 1.0 + (consecutive_days - 1) * 0.1
multiplier = min(multiplier, 3.0)
text += "[center][color=#90EE90]奖励倍数: %.1fx[/color][/center]\n\n" % multiplier
else:
text += "\n"
# 基础奖励
if rewards.has("coins"):
text += "[color=%s]%s +%d %s[/color]\n" % [
reward_configs.coins.color,
reward_configs.coins.icon,
rewards.coins,
reward_configs.coins.name
]
if rewards.has("exp"):
text += "[color=%s]%s +%d %s[/color]\n" % [
reward_configs.exp.color,
reward_configs.exp.icon,
rewards.exp,
reward_configs.exp.name
]
# 种子奖励
if rewards.has("seeds") and rewards.seeds.size() > 0:
for seed_reward in rewards.seeds:
var seed_name = seed_reward.name
var quantity = seed_reward.quantity
var quality = seed_reward.quality
# 从配置中找到对应的种子信息
var seed_info = _get_seed_info(seed_name, quality)
if seed_info:
text += "[color=%s]%s[/color] [color=%s]%s[/color] x%d [color=%s](%s)[/color]\n" % [
seed_info.color, seed_info.icon, seed_info.color, seed_name, quantity, seed_info.rarity_color, quality
]
# 连续签到额外奖励
if rewards.has("bonus_coins"):
text += "\n[color=#FFD700]🎁 连续签到奖励:[/color]\n"
text += "[color=%s]%s +%d %s[/color] [color=#FFD700]✨[/color]\n" % [
reward_configs.coins.color,
reward_configs.coins.icon,
rewards.bonus_coins,
reward_configs.coins.name
]
if rewards.has("bonus_exp"):
if not rewards.has("bonus_coins"):
text += "\n[color=#FFD700]🎁 连续签到奖励:[/color]\n"
text += "[color=%s]%s +%d %s[/color] [color=#FFD700]✨[/color]\n" % [
reward_configs.exp.color,
reward_configs.exp.icon,
rewards.bonus_exp,
reward_configs.exp.name
]
# 下一个奖励预告
var next_bonus_day = 0
if consecutive_days < 3:
next_bonus_day = 3
elif consecutive_days < 7:
next_bonus_day = 7
elif consecutive_days < 14:
next_bonus_day = 14
elif consecutive_days < 21:
next_bonus_day = 21
if next_bonus_day > 0:
var days_needed = next_bonus_day - consecutive_days
text += "\n[center][color=#87CEEB]再签到%d天可获得特殊奖励![/color][/center]" % days_needed
return text
## 获取种子信息
func _get_seed_info(seed_name: String, quality: String) -> Dictionary:
if quality in reward_configs.seeds:
for seed in reward_configs.seeds[quality]:
if seed.name == seed_name:
return seed
return {}
## 格式化历史记录文本
func _format_history_text(date: String, rewards: Dictionary) -> String:
var text = "[color=#87CEEB]📅 %s[/color] " % date
var reward_parts = []
if rewards.has("coins"):
reward_parts.append("[color=%s]%s %d[/color]" % [
reward_configs.coins.color,
reward_configs.coins.name,
rewards.coins
])
if rewards.has("exp"):
reward_parts.append("[color=%s]%s %d[/color]" % [
reward_configs.exp.color,
reward_configs.exp.name,
rewards.exp
])
if rewards.has("seeds") and rewards.seeds.size() > 0:
for seed_reward in rewards.seeds:
var seed_name = seed_reward.name
var quantity = seed_reward.quantity
var quality = seed_reward.quality
var seed_info = _get_seed_info(seed_name, quality)
if seed_info:
reward_parts.append("[color=%s]%s x%d[/color]" % [
seed_info.color, seed_name, quantity
])
text += " ".join(reward_parts)
return text
## 更新显示内容
func _update_display() -> void:
var history_text = "[center][color=#FFB6C1]📋 签到历史[/color][/center]\n"
# 显示连续签到状态
if consecutive_days > 0:
history_text += "[center][color=#FF69B4]🔥 当前连续签到: %d天[/color][/center]\n" % consecutive_days
if consecutive_days >= 30:
history_text += "[center][color=#FFD700]⭐ 已达到最高连击等级! ⭐[/color][/center]\n"
else:
history_text += "[center][color=#DDDDDD]还未开始连续签到[/color][/center]\n"
history_text += "\n"
if check_in_data.size() == 0:
history_text += "[center][color=#DDDDDD]暂无签到记录[/color][/center]"
else:
# 按日期排序显示历史记录
var sorted_dates = check_in_data.keys()
sorted_dates.sort()
sorted_dates.reverse() # 最新的在前
for date in sorted_dates:
var day_data = check_in_data[date]
var rewards = day_data.get("rewards", {})
var day_consecutive = day_data.get("consecutive_days", 1)
history_text += _format_history_text(date, rewards)
history_text += " [color=#90EE90](连续%d天)[/color]\n" % day_consecutive
history_text += "-----------------------------------------------------------------------------------------------------------------\n"
daily_check_in_history.text = history_text
# =============================================================================
# 事件处理
# =============================================================================
## 关闭面板按钮
func _on_quit_button_pressed() -> void:
self.hide()
## 签到按钮
func _on_daily_check_in_button_pressed() -> void:
execute_check_in()
# =============================================================================
# 公共接口方法 - 供主游戏调用
# =============================================================================
## 刷新签到数据
func refresh_check_in_data() -> void:
if network_manager and network_manager.is_connected_to_server():
network_manager.sendGetCheckInData()
## 获取当前签到状态
func get_check_in_status() -> Dictionary:
return {
"has_checked_in_today": has_checked_in_today,
"consecutive_days": consecutive_days,
"today_date": today_date
}

View File

@@ -0,0 +1 @@
uid://c0jfbtkh0mj5b

View File

@@ -0,0 +1,76 @@
[gd_scene load_steps=2 format=3 uid="uid://smypui0vyso5"]
[ext_resource type="Script" uid="uid://c0jfbtkh0mj5b" path="res://游戏弹窗模板/DailyCheckInPanel.gd" id="1_fj7a7"]
[node name="DailyCheckInPanel" type="Panel"]
offset_right = 600.0
offset_bottom = 720.0
script = ExtResource("1_fj7a7")
[node name="Title" type="Label" parent="."]
layout_mode = 0
offset_top = -1.0
offset_right = 600.0
offset_bottom = 41.0
theme_override_colors/font_color = Color(0.624759, 0.8051, 0.828302, 1)
theme_override_font_sizes/font_size = 35
text = "📅每日签到📅"
horizontal_alignment = 1
[node name="Label" type="Label" parent="."]
modulate = Color(0.642982, 0.510828, 1, 1)
layout_mode = 0
offset_top = 419.0
offset_right = 600.0
offset_bottom = 468.0
theme_override_font_sizes/font_size = 30
text = "🎉签到奖励🎉"
horizontal_alignment = 1
vertical_alignment = 1
[node name="QuitButton" type="Button" parent="."]
custom_minimum_size = Vector2(57, 57)
layout_mode = 0
offset_left = 543.0
offset_top = 1.0
offset_right = 600.0
offset_bottom = 58.0
theme_override_font_sizes/font_size = 35
text = "X"
[node name="DailyCheckInButton" type="Button" parent="."]
modulate = Color(1, 1, 0.52549, 1)
custom_minimum_size = Vector2(150, 70)
layout_mode = 0
offset_left = 243.0
offset_top = 649.0
offset_right = 393.0
offset_bottom = 719.0
theme_override_font_sizes/font_size = 35
text = "签到"
[node name="Scroll" type="ScrollContainer" parent="."]
layout_mode = 0
offset_top = 58.0
offset_right = 600.0
offset_bottom = 419.0
[node name="DailyCheckInHistory" type="RichTextLabel" parent="Scroll"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
bbcode_enabled = true
threaded = true
[node name="DailyCheckInReward" type="RichTextLabel" parent="."]
layout_mode = 0
offset_top = 481.0
offset_right = 600.0
offset_bottom = 649.0
theme_override_font_sizes/normal_font_size = 20
bbcode_enabled = true
text = "+500 经验,+400 钱币,+5 普通-番茄种子,+1 传奇-火龙果种子 "
horizontal_alignment = 1
[connection signal="pressed" from="QuitButton" to="." method="_on_quit_button_pressed"]
[connection signal="pressed" from="DailyCheckInButton" to="." method="_on_daily_check_in_button_pressed"]

10
GUI/GameAboutPanel.gd Normal file
View File

@@ -0,0 +1,10 @@
extends Panel
func _ready() -> void:
self.show()
pass
func _on_quit_button_pressed() -> void:
self.hide()
pass

View File

@@ -0,0 +1 @@
uid://bob7a4vhw4nl3

9
GUI/GameSettingPanel.gd Normal file
View File

@@ -0,0 +1,9 @@
extends Panel
func _ready() -> void:
self.hide()
pass
func _on_quit_button_pressed() -> void:
self.hide()
pass

View File

@@ -0,0 +1 @@
uid://ct7rhywlql4y4

162
GUI/GameUpdatePanel.gd Normal file
View File

@@ -0,0 +1,162 @@
extends Panel
@onready var contents: RichTextLabel = $Scroll/Contents #更新内容
@onready var refresh_button: Button = $RefreshButton #刷新按钮
# HTTP请求节点
var http_request: HTTPRequest
# API配置
const API_URL = "http://47.108.90.0:5003/api/game/mengyafarm/updates"
func _ready() -> void:
self.hide()
# 创建HTTPRequest节点
http_request = HTTPRequest.new()
add_child(http_request)
# 连接HTTP请求完成信号
http_request.request_completed.connect(_on_request_completed)
# 连接刷新按钮信号
refresh_button.pressed.connect(_on_refresh_button_pressed)
# 初始加载更新数据
load_updates()
func _on_quit_button_pressed() -> void:
HidePanel()
func _on_refresh_button_pressed() -> void:
load_updates()
func load_updates() -> void:
# 禁用刷新按钮,防止重复请求
refresh_button.disabled = true
refresh_button.text = "刷新中..."
# 显示加载中
contents.text = "[center][color=yellow]正在加载更新信息...[/color][/center]"
# 发起HTTP请求
var error = http_request.request(API_URL)
if error != OK:
_show_error("网络请求失败,错误代码: " + str(error))
func _on_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void:
# 恢复刷新按钮
refresh_button.disabled = false
refresh_button.text = "刷新"
# 检查请求结果
if result != HTTPRequest.RESULT_SUCCESS:
_show_error("网络连接失败")
return
if response_code != 200:
_show_error("服务器响应错误 (HTTP " + str(response_code) + ")")
return
# 解析JSON数据
var json_text = body.get_string_from_utf8()
if json_text.is_empty():
_show_error("服务器返回空数据")
return
var json = JSON.new()
var parse_result = json.parse(json_text)
if parse_result != OK:
_show_error("数据解析失败")
return
var data = json.data
if not data.has("updates"):
_show_error("数据格式错误")
return
# 显示更新内容
display_updates(data.updates)
func _show_error(error_message: String) -> void:
refresh_button.disabled = false
refresh_button.text = "刷新"
contents.text = "[center][color=red]" + error_message + "\n\n请检查网络连接或稍后重试[/color][/center]"
func display_updates(updates: Array) -> void:
if updates.is_empty():
contents.text = "[center][color=gray]暂无更新信息[/color][/center]"
return
var update_text = ""
for i in range(updates.size()):
var update = updates[i]
# 检查必要字段
if not update.has("title") or not update.has("version") or not update.has("content"):
continue
# 更新标题
update_text += "[color=cyan][font_size=22][b]" + str(update.title) + "[/b][/font_size][/color]\n"
# 版本和时间信息
update_text += "[color=green]版本: " + str(update.version) + "[/color]"
if update.has("timestamp"):
var formatted_time = _format_time(str(update.timestamp))
update_text += " [color=gray]时间: " + formatted_time + "[/color]"
if update.has("game_name"):
update_text += " [color=gray]游戏: " + str(update.game_name) + "[/color]"
update_text += "\n\n"
# 更新内容
var content = str(update.content)
# 处理换行符
content = content.replace("\\r\\n", "\n").replace("\\n", "\n")
# 高亮特殊符号
content = content.replace("", "[color=green]✓[/color]")
content = content.replace("修复:", "[color=yellow]修复:[/color]")
content = content.replace("添加", "[color=cyan]添加[/color]")
content = content.replace("修改", "[color=orange]修改[/color]")
update_text += "[color=white]" + content + "[/color]\n"
# 添加分隔线(除了最后一个更新)
if i < updates.size() - 1:
update_text += "\n[color=gray]" + "".repeat(60) + "[/color]\n\n"
contents.text = update_text
# 简单的时间格式化
func _format_time(timestamp: String) -> String:
var parts = timestamp.split(" ")
if parts.size() >= 2:
var date_parts = parts[0].split("-")
var time_parts = parts[1].split(":")
if date_parts.size() >= 3 and time_parts.size() >= 2:
return date_parts[1] + "" + date_parts[2] + "" + time_parts[0] + ":" + time_parts[1]
return timestamp
# 显示面板时自动刷新
func ShowPanel() -> void:
self.show()
load_updates()
# 隐藏面板时取消正在进行的请求
func HidePanel() -> void:
self.hide()
if http_request and http_request.get_http_client_status() != HTTPClient.STATUS_DISCONNECTED:
http_request.cancel_request()
# 恢复按钮状态
if refresh_button:
refresh_button.disabled = false
refresh_button.text = "刷新"

View File

@@ -0,0 +1 @@
uid://kj7v1uxk2i6h

584
GUI/LuckyDrawPanel.gd Normal file
View File

@@ -0,0 +1,584 @@
extends Panel
class_name LuckyDrawPanel
## 幸运抽奖系统 - 后端对接版本
## 功能:与服务器对接的抽奖系统,支持实时数据同步和平衡调整
## 奖励平衡性已根据 crop_data.json 调整
# =============================================================================
# 信号定义 - 用于与后端系统通信
# =============================================================================
signal draw_completed(rewards: Array, draw_type: String) # 抽奖完成信号
signal reward_obtained(reward_type: String, amount: int) # 奖励获得信号
signal draw_failed(error_message: String) # 抽奖失败信号
# =============================================================================
# 节点引用
# =============================================================================
#这个展示抽奖获得的奖励
@onready var lucky_draw_reward: RichTextLabel = $LuckyDrawReward
#这个是展示有哪些奖励选项最多15个奖励就在这里面随机挑选
@onready var grid: GridContainer = $Grid
#这个是奖励模板
@onready var reward_item: RichTextLabel = $Grid/RewardItem
# =============================================================================
# 数据存储
# =============================================================================
var reward_templates: Array[RichTextLabel] = []
var current_rewards: Array = []
var network_manager = null
var main_game = null
# 15种不同的模板颜色
var template_colors: Array[Color] = [
Color(1.0, 0.8, 0.8, 1.0), # 淡红色
Color(0.8, 1.0, 0.8, 1.0), # 淡绿色
Color(0.8, 0.8, 1.0, 1.0), # 淡蓝色
Color(1.0, 1.0, 0.8, 1.0), # 淡黄色
Color(1.0, 0.8, 1.0, 1.0), # 淡紫色
Color(0.8, 1.0, 1.0, 1.0), # 淡青色
Color(1.0, 0.9, 0.8, 1.0), # 淡橙色
Color(0.9, 0.8, 1.0, 1.0), # 淡紫蓝色
Color(0.8, 1.0, 0.9, 1.0), # 淡薄荷色
Color(1.0, 0.8, 0.9, 1.0), # 淡粉色
Color(0.9, 1.0, 0.8, 1.0), # 淡柠檬色
Color(0.8, 0.9, 1.0, 1.0), # 淡天蓝色
Color(1.0, 0.95, 0.8, 1.0), # 淡香槟色
Color(0.85, 0.8, 1.0, 1.0), # 淡薰衣草色
Color(0.95, 1.0, 0.85, 1.0) # 淡春绿色
]
# =============================================================================
# 基础奖励配置 - 根据 crop_data.json 调整
# =============================================================================
var base_rewards: Dictionary = {
"coins": {"name": "金币", "icon": "💰", "color": "#FFD700"},
"exp": {"name": "经验", "icon": "", "color": "#00BFFF"},
"empty": {"name": "谢谢惠顾", "icon": "😅", "color": "#CCCCCC"}
}
# 根据 crop_data.json 动态构建的种子奖励
var seed_rewards: Dictionary = {}
# 抽奖费用配置
var draw_costs: Dictionary = {
"single": 800,
"five": 3600, # 800 * 5 * 0.9 = 3600
"ten": 6400 # 800 * 10 * 0.8 = 6400
}
# =============================================================================
# 奖励池配置 - 根据后端数据动态更新
# =============================================================================
var server_reward_pools: Dictionary = {}
# =============================================================================
# 系统初始化
# =============================================================================
func _ready() -> void:
_initialize_system()
func _initialize_system() -> void:
"""初始化抽奖系统"""
# 获取网络管理器和主游戏引用
network_manager = get_node("/root/main/UI/TCPNetworkManager")
main_game = get_node("/root/main")
# 连接信号
if main_game:
draw_completed.connect(main_game._on_lucky_draw_completed)
draw_failed.connect(main_game._on_lucky_draw_failed)
lucky_draw_reward.hide()
_load_crop_data_and_build_rewards()
_generate_reward_templates()
_update_template_display()
func _load_crop_data_and_build_rewards() -> void:
"""从主游戏加载作物数据并构建种子奖励"""
if main_game and main_game.has_method("get_crop_data"):
var crop_data = main_game.get_crop_data()
if crop_data:
_build_seed_rewards_from_crop_data(crop_data)
func _build_seed_rewards_from_crop_data(crop_data: Dictionary) -> void:
"""根据 crop_data.json 构建种子奖励配置"""
seed_rewards.clear()
for crop_name in crop_data.keys():
var crop_info = crop_data[crop_name]
# 跳过测试作物和不能购买的作物
if crop_name == "测试作物" or not crop_info.get("能否购买", true):
continue
var quality = crop_info.get("品质", "普通")
var rarity_color = _get_rarity_color(quality)
seed_rewards[crop_name] = {
"icon": "🌱",
"color": rarity_color,
"rarity": quality,
"level": crop_info.get("等级", 1),
"cost": crop_info.get("花费", 50)
}
func _get_rarity_color(rarity: String) -> String:
"""根据稀有度获取颜色"""
match rarity:
"普通":
return "#90EE90"
"优良":
return "#87CEEB"
"稀有":
return "#DDA0DD"
"史诗":
return "#9932CC"
"传奇":
return "#FF8C00"
_:
return "#FFFFFF"
# =============================================================================
# 核心功能
# =============================================================================
## 生成15个奖励模板
func _generate_reward_templates() -> void:
# 清空现有模板
for child in grid.get_children():
if child != reward_item:
child.queue_free()
reward_templates.clear()
# 生成15个模板包括原有的一个
for i in range(15):
var template: RichTextLabel
if i == 0:
# 使用原有的模板
template = reward_item
else:
# 创建新的模板
template = reward_item.duplicate()
grid.add_child(template)
# 设置不同的颜色
template.self_modulate = template_colors[i]
template.bbcode_enabled = true
template.threaded = true
reward_templates.append(template)
## 更新模板显示
func _update_template_display() -> void:
var sample_rewards = _generate_sample_rewards()
for i in range(reward_templates.size()):
var template = reward_templates[i]
if i < sample_rewards.size():
var reward = sample_rewards[i]
template.text = _format_template_text(reward)
template.show()
else:
template.hide()
## 生成示例奖励显示
func _generate_sample_rewards() -> Array:
var sample_rewards = []
# 添加基础奖励示例
sample_rewards.append({"type": "coins", "amount_range": [100, 300], "rarity": "普通"})
sample_rewards.append({"type": "exp", "amount_range": [50, 150], "rarity": "普通"})
sample_rewards.append({"type": "empty", "name": "谢谢惠顾", "rarity": "空奖"})
# 添加各品质种子示例
var quality_examples = ["普通", "优良", "稀有", "史诗", "传奇"]
for quality in quality_examples:
var example_seeds = []
for seed_name in seed_rewards.keys():
if seed_rewards[seed_name].rarity == quality:
example_seeds.append(seed_name)
if example_seeds.size() > 0:
var seed_name = example_seeds[0] # 取第一个作为示例
sample_rewards.append({
"type": "seed",
"name": seed_name,
"rarity": quality,
"amount_range": [1, 3] if quality != "传奇" else [1, 1]
})
# 添加礼包示例
sample_rewards.append({"type": "package", "name": "成长套餐", "rarity": "优良"})
sample_rewards.append({"type": "package", "name": "稀有礼包", "rarity": "稀有"})
sample_rewards.append({"type": "package", "name": "传奇大礼包", "rarity": "传奇"})
# 添加高级奖励示例
sample_rewards.append({"type": "coins", "amount_range": [1000, 2000], "rarity": "史诗"})
sample_rewards.append({"type": "exp", "amount_range": [500, 1000], "rarity": "传奇"})
return sample_rewards.slice(0, 15) # 只取前15个
## 格式化模板文本
func _format_template_text(reward: Dictionary) -> String:
var text = "[center]"
match reward.type:
"empty":
text += "[color=%s]%s[/color]\n" % [base_rewards.empty.color, base_rewards.empty.icon]
text += "[color=%s]%s[/color]" % [base_rewards.empty.color, reward.get("name", "谢谢惠顾")]
"package":
var rarity_color = _get_rarity_color(reward.get("rarity", "普通"))
text += "[color=%s]🎁[/color]\n" % [rarity_color]
text += "[color=%s]%s[/color]\n" % [rarity_color, reward.get("name", "礼包")]
text += "[color=#CCCCCC](%s)[/color]" % reward.get("rarity", "普通")
"coins":
var rarity_color = _get_rarity_color(reward.get("rarity", "普通"))
text += "[color=%s]%s[/color]\n" % [rarity_color, base_rewards.coins.icon]
if reward.has("amount_range"):
text += "[color=%s]%d-%d[/color]\n" % [rarity_color, reward.amount_range[0], reward.amount_range[1]]
text += "[color=%s]%s[/color]" % [rarity_color, base_rewards.coins.name]
"exp":
var rarity_color = _get_rarity_color(reward.get("rarity", "普通"))
text += "[color=%s]%s[/color]\n" % [rarity_color, base_rewards.exp.icon]
if reward.has("amount_range"):
text += "[color=%s]%d-%d[/color]\n" % [rarity_color, reward.amount_range[0], reward.amount_range[1]]
text += "[color=%s]%s[/color]" % [rarity_color, base_rewards.exp.name]
"seed":
if reward.has("name") and reward.name in seed_rewards:
var seed_info = seed_rewards[reward.name]
text += "[color=%s]%s[/color]\n" % [seed_info.color, seed_info.icon]
text += "[color=%s]%s[/color]\n" % [seed_info.color, reward.name]
if reward.has("amount_range"):
text += "[color=%s]x%d-%d[/color]\n" % [seed_info.color, reward.amount_range[0], reward.amount_range[1]]
text += "[color=#CCCCCC](%s)[/color]" % seed_info.rarity
else:
text += "[color=#90EE90]🌱[/color]\n"
text += "[color=#90EE90]种子[/color]"
text += "[/center]"
return text
## 执行网络抽奖
func _perform_network_draw(draw_type: String) -> void:
"""通过网络请求执行抽奖"""
if not network_manager or not network_manager.is_connected_to_server():
_show_error_message("网络未连接,无法进行抽奖")
return
# 检查费用
var cost = draw_costs.get(draw_type, 800)
if main_game and main_game.money < cost:
_show_error_message("金币不足,需要 %d 金币" % cost)
return
# 发送抽奖请求
var success = network_manager.sendLuckyDraw(draw_type)
if not success:
_show_error_message("发送抽奖请求失败")
return
# 显示等待动画
_show_waiting_animation(draw_type)
## 显示等待动画
func _show_waiting_animation(draw_type: String) -> void:
"""显示抽奖等待动画"""
# 禁用抽奖按钮
_set_draw_buttons_enabled(false)
# 隐藏结果区域
lucky_draw_reward.hide()
# 播放期待动画
_play_anticipation_animation()
## 处理服务器抽奖响应
func handle_lucky_draw_response(response: Dictionary) -> void:
"""处理来自服务器的抽奖响应"""
# 停止期待动画
_stop_anticipation_animation()
# 重新启用按钮
_set_draw_buttons_enabled(true)
if response.get("success", false):
var rewards = response.get("rewards", [])
var draw_type = response.get("draw_type", "single")
var cost = response.get("cost", 0)
# 显示抽奖结果
_show_server_draw_results(rewards, draw_type, cost)
# 发送信号
draw_completed.emit(rewards, draw_type)
else:
var error_message = response.get("message", "抽奖失败")
_show_error_message(error_message)
draw_failed.emit(error_message)
## 显示服务器返回的抽奖结果
func _show_server_draw_results(rewards: Array, draw_type: String, cost: int) -> void:
"""显示服务器返回的抽奖结果"""
current_rewards = rewards
# 显示结果动画已在handle_lucky_draw_response中停止
var result_text = _format_server_draw_results(rewards, draw_type, cost)
lucky_draw_reward.text = result_text
lucky_draw_reward.show()
# 播放结果动画
_play_result_animation()
## 格式化服务器抽奖结果文本
func _format_server_draw_results(rewards: Array, draw_type: String, cost: int) -> String:
var type_names = {
"single": "单抽",
"five": "五连抽",
"ten": "十连抽"
}
var text = "[center][color=#FFD700]🎊 %s结果 🎊[/color][/center]\n" % type_names.get(draw_type, draw_type)
text += "[center][color=#87CEEB]消费 %d 金币[/color][/center]\n" % cost
# 统计稀有度
var stats = _count_server_reward_rarity(rewards)
# 显示稀有度统计
var stat_parts = []
if stats.legendary > 0:
stat_parts.append("[color=#FF8C00]🏆传奇x%d[/color]" % stats.legendary)
if stats.epic > 0:
stat_parts.append("[color=#9932CC]💎史诗x%d[/color]" % stats.epic)
if stats.rare > 0:
stat_parts.append("[color=#DDA0DD]⭐稀有x%d[/color]" % stats.rare)
if stats.package > 0:
stat_parts.append("[color=#FF69B4]🎁礼包x%d[/color]" % stats.package)
if stat_parts.size() > 0:
text += "[center]%s[/center]\n" % " ".join(stat_parts)
text += "\n"
# 显示具体奖励
for reward in rewards:
text += _format_single_server_reward(reward) + "\n"
# 鼓励文案
if stats.empty_only:
text += "[center][color=#87CEEB]💪 别灰心,下次一定能中大奖![/color][/center]"
elif stats.legendary > 0:
text += "[center][color=#FF8C00]🎉 恭喜获得传奇奖励![/color][/center]"
elif stats.epic > 0:
text += "[center][color=#9932CC]✨ 史诗奖励,运气不错![/color][/center]"
return text
## 统计服务器奖励稀有度
func _count_server_reward_rarity(rewards: Array) -> Dictionary:
var stats = {
"legendary": 0,
"epic": 0,
"rare": 0,
"package": 0,
"empty": 0,
"empty_only": false
}
for reward in rewards:
var rarity = reward.get("rarity", "普通")
match rarity:
"传奇":
stats.legendary += 1
"史诗":
stats.epic += 1
"稀有":
stats.rare += 1
"空奖":
stats.empty += 1
if reward.get("type") == "package":
stats.package += 1
stats.empty_only = (stats.empty == rewards.size() and rewards.size() == 1)
return stats
## 格式化单个服务器奖励显示
func _format_single_server_reward(reward: Dictionary) -> String:
var text = ""
var reward_type = reward.get("type", "")
var rarity = reward.get("rarity", "普通")
var rarity_color = _get_rarity_color(rarity)
match reward_type:
"empty":
var reward_name = reward.get("name", "空奖励")
text = "[color=%s]😅 %s[/color]" % [rarity_color, reward_name]
"package":
var reward_name = reward.get("name", "礼包")
text = "[color=%s]🎁 %s[/color]\n" % [rarity_color, reward_name]
text += "[color=#DDDDDD]内含:[/color] "
var content_parts = []
if reward.has("contents"):
for content in reward.contents:
var part = _format_package_content(content)
if part != "":
content_parts.append(part)
text += " ".join(content_parts)
"coins":
var amount = reward.get("amount", 0)
text = "[color=%s]💰 金币 +%d[/color]" % [rarity_color, amount]
"exp":
var amount = reward.get("amount", 0)
text = "[color=%s]⭐ 经验 +%d[/color]" % [rarity_color, amount]
"seed":
var reward_name = reward.get("name", "种子")
var amount = reward.get("amount", 0)
text = "[color=%s]🌱 %s x%d[/color] [color=#CCCCCC](%s)[/color]" % [
rarity_color, reward_name, amount, rarity
]
_:
text = "[color=#CCCCCC]未知奖励[/color]"
return text
## 格式化礼包内容
func _format_package_content(content: Dictionary) -> String:
var content_type = content.get("type", "")
var amount = content.get("amount", 0)
match content_type:
"coins":
return "[color=#FFD700]💰%d[/color]" % amount
"exp":
return "[color=#00BFFF]⭐%d[/color]" % amount
"seed":
var seed_name = content.get("name", "种子")
return "[color=#90EE90]🌱%sx%d[/color]" % [seed_name, amount]
_:
return ""
## 播放期待动画(简化版)
func _play_anticipation_animation() -> void:
"""播放期待动画"""
# 停止之前的动画
_stop_anticipation_animation()
# 创建简单的闪烁动画
anticipation_tween = create_tween()
anticipation_tween.set_loops()
for template in reward_templates:
if template.visible:
anticipation_tween.parallel().tween_method(
func(progress: float): _anticipation_flash(template, progress),
0.0, 1.0, 0.5
)
var anticipation_tween: Tween = null
func _anticipation_flash(template: RichTextLabel, progress: float) -> void:
"""期待动画闪烁效果"""
var flash_intensity = 1.0 + sin(progress * PI * 2) * 0.3
template.modulate = Color(flash_intensity, flash_intensity, flash_intensity, 1.0)
## 停止期待动画
func _stop_anticipation_animation() -> void:
"""停止期待动画"""
if anticipation_tween:
anticipation_tween.kill()
anticipation_tween = null
# 恢复所有模板的正常颜色
for i in range(reward_templates.size()):
var template = reward_templates[i]
template.modulate = Color.WHITE
## 播放结果动画
func _play_result_animation() -> void:
var tween = create_tween()
# 奖励区域动画
lucky_draw_reward.modulate.a = 0.0
lucky_draw_reward.scale = Vector2(0.8, 0.8)
tween.parallel().tween_property(lucky_draw_reward, "modulate:a", 1.0, 0.5)
tween.parallel().tween_property(lucky_draw_reward, "scale", Vector2(1.0, 1.0), 0.5)
## 显示错误信息
func _show_error_message(message: String) -> void:
"""显示错误信息"""
lucky_draw_reward.text = "[center][color=#FF6B6B]❌ %s[/color][/center]" % message
lucky_draw_reward.show()
# 2秒后隐藏错误信息
await get_tree().create_timer(2.0).timeout
lucky_draw_reward.hide()
# =============================================================================
# 事件处理
# =============================================================================
## 关闭面板
func _on_quit_button_pressed() -> void:
self.hide()
## 单次抽奖
func _on_lucky_draw_button_pressed() -> void:
_perform_network_draw("single")
## 五连抽
func _on_five_lucky_draw_button_pressed() -> void:
_perform_network_draw("five")
## 十连抽
func _on_ten_lucky_draw_button_pressed() -> void:
_perform_network_draw("ten")
## 设置抽奖按钮可用状态
func _set_draw_buttons_enabled(enabled: bool) -> void:
var buttons = [
$HBox/LuckyDrawButton,
$HBox/FiveLuckyDrawButton,
$HBox/TenLuckyDrawButton
]
for button in buttons:
if button:
button.disabled = not enabled
# =============================================================================
# 公共接口方法
# =============================================================================
## 获取当前奖励结果
func get_current_rewards() -> Array:
return current_rewards
## 清空抽奖结果
func clear_draw_results() -> void:
current_rewards.clear()
lucky_draw_reward.hide()
## 刷新奖励显示(当作物数据更新时调用)
func refresh_reward_display() -> void:
"""刷新奖励显示"""
_load_crop_data_and_build_rewards()
_update_template_display()

View File

@@ -0,0 +1 @@
uid://65e0rl31fx0i

101
GUI/LuckyDrawPanel.tscn Normal file
View File

@@ -0,0 +1,101 @@
[gd_scene load_steps=2 format=3 uid="uid://bndf1e4sgdjr6"]
[ext_resource type="Script" uid="uid://65e0rl31fx0i" path="res://GUI/LuckyDrawPanel.gd" id="1_dcmen"]
[node name="LuckyDrawPanel" type="Panel"]
offset_right = 600.0
offset_bottom = 720.0
script = ExtResource("1_dcmen")
[node name="Title" type="Label" parent="."]
layout_mode = 0
offset_top = -1.0
offset_right = 600.0
offset_bottom = 58.0
theme_override_colors/font_color = Color(0.624759, 0.8051, 0.828302, 1)
theme_override_font_sizes/font_size = 35
text = "幸运抽奖"
horizontal_alignment = 1
vertical_alignment = 1
[node name="Label" type="Label" parent="."]
modulate = Color(0.642982, 0.510828, 1, 1)
layout_mode = 0
offset_top = 419.0
offset_right = 600.0
offset_bottom = 468.0
theme_override_font_sizes/font_size = 30
text = "🎉获得奖励🎉"
horizontal_alignment = 1
vertical_alignment = 1
[node name="QuitButton" type="Button" parent="."]
custom_minimum_size = Vector2(57, 57)
layout_mode = 0
offset_left = 543.0
offset_top = 1.0
offset_right = 600.0
offset_bottom = 58.0
theme_override_font_sizes/font_size = 35
text = "X"
[node name="LuckyDrawReward" type="RichTextLabel" parent="."]
layout_mode = 0
offset_top = 481.0
offset_right = 600.0
offset_bottom = 649.0
theme_override_font_sizes/normal_font_size = 20
bbcode_enabled = true
text = "+500 经验,+400 钱币,+5 普通-番茄种子,+1 传奇-火龙果种子 "
horizontal_alignment = 1
[node name="Grid" type="GridContainer" parent="."]
layout_mode = 0
offset_top = 58.0
offset_right = 600.0
offset_bottom = 419.0
columns = 5
[node name="RewardItem" type="RichTextLabel" parent="Grid"]
custom_minimum_size = Vector2(120, 120)
layout_mode = 2
text = "+50钱币
+100经验
+4番茄种子
+3火龙果种子"
horizontal_alignment = 1
vertical_alignment = 1
threaded = true
[node name="HBox" type="HBoxContainer" parent="."]
layout_mode = 0
offset_top = 649.0
offset_right = 600.0
offset_bottom = 719.0
alignment = 1
[node name="FiveLuckyDrawButton" type="Button" parent="HBox"]
modulate = Color(0.623529, 1, 0.996078, 1)
custom_minimum_size = Vector2(150, 70)
layout_mode = 2
theme_override_font_sizes/font_size = 35
text = "五连抽"
[node name="TenLuckyDrawButton" type="Button" parent="HBox"]
modulate = Color(0.690196, 1, 0.52549, 1)
custom_minimum_size = Vector2(150, 70)
layout_mode = 2
theme_override_font_sizes/font_size = 35
text = "十连抽"
[node name="LuckyDrawButton" type="Button" parent="HBox"]
modulate = Color(1, 1, 0.52549, 1)
custom_minimum_size = Vector2(150, 70)
layout_mode = 2
theme_override_font_sizes/font_size = 35
text = "抽奖"
[connection signal="pressed" from="QuitButton" to="." method="_on_quit_button_pressed"]
[connection signal="pressed" from="HBox/FiveLuckyDrawButton" to="." method="_on_five_lucky_draw_button_pressed"]
[connection signal="pressed" from="HBox/TenLuckyDrawButton" to="." method="_on_ten_lucky_draw_button_pressed"]
[connection signal="pressed" from="HBox/LuckyDrawButton" to="." method="_on_lucky_draw_button_pressed"]

42
GUI/MainMenuPanel.gd Normal file
View File

@@ -0,0 +1,42 @@
extends Control
#各种面板
@onready var game_about_panel: Panel = $GameAboutPanel
@onready var game_update_panel: Panel = $GameUpdatePanel
@onready var game_setting_panel: Panel = $GameSettingPanel
@onready var game_version_label: Label = $GUI/GameVersionLabel
@export var smy :TextureRect
func _ready():
game_version_label.text = "版本号:"+GlobalVariables.client_version
pass
func SetGameVersionLabel(version :String):
game_version_label.text = version
pass
#开始游戏
func _on_start_game_button_pressed() -> void:
get_tree().change_scene_to_file('res://MainGame.tscn')
pass
#游戏设置
func _on_game_setting_button_pressed() -> void:
game_setting_panel.show()
pass
#游戏更新
func _on_game_update_button_pressed() -> void:
game_update_panel.ShowPanel( )
pass
#游戏关于
func _on_game_about_button_pressed() -> void:
game_about_panel.show()
pass
#游戏结束
func _on_exit_button_pressed() -> void:
get_tree().quit()
pass

1
GUI/MainMenuPanel.gd.uid Normal file
View File

@@ -0,0 +1 @@
uid://badqjgdfhg7vt

268
GUI/MainMenuPanel.tscn Normal file
View File

@@ -0,0 +1,268 @@
[gd_scene load_steps=9 format=3 uid="uid://bypjb28h4ntdr"]
[ext_resource type="Script" uid="uid://badqjgdfhg7vt" path="res://GUI/MainMenuPanel.gd" id="1_wpehy"]
[ext_resource type="Texture2D" uid="uid://bhdqkhf0y2ply" path="res://assets/UI/背景1.jpg" id="2_fys16"]
[ext_resource type="Script" path="res://GUI/GameSettingPanel.gd" id="2_n0pjj"]
[ext_resource type="Texture2D" uid="uid://4kvddwqlodpg" path="res://assets/logo_title/logo1.png" id="3_sr106"]
[ext_resource type="Script" path="res://GUI/GameAboutPanel.gd" id="3_y0inj"]
[ext_resource type="Script" uid="uid://kj7v1uxk2i6h" path="res://GUI/GameUpdatePanel.gd" id="4_fys16"]
[ext_resource type="Texture2D" uid="uid://b5of6puh4efui" path="res://assets/杂项/柚小青装饰品.png" id="5_eghpk"]
[ext_resource type="Texture2D" uid="uid://cuuqapjbrsdy7" path="res://assets/UI/QQ群.jpg" id="5_y0inj"]
[node name="MainMenuPanel" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_right = -2.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_wpehy")
[node name="Background" type="TextureRect" parent="."]
self_modulate = Color(1, 1, 1, 0.34902)
layout_mode = 0
offset_left = -131.0
offset_top = -24.0
offset_right = 1568.0
offset_bottom = 734.0
texture = ExtResource("2_fys16")
[node name="GUI" type="Control" parent="."]
anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0
[node name="GameLogo" type="TextureRect" parent="GUI"]
layout_mode = 0
offset_left = 450.0
offset_top = -24.0
offset_right = 1730.0
offset_bottom = 696.0
scale = Vector2(0.4, 0.4)
texture = ExtResource("3_sr106")
stretch_mode = 2
[node name="RichTextLabel" type="RichTextLabel" parent="GUI"]
visible = false
layout_mode = 0
offset_right = 1398.0
offset_bottom = 88.0
theme_override_font_sizes/normal_font_size = 40
bbcode_enabled = true
text = "萌芽农场"
horizontal_alignment = 1
vertical_alignment = 1
[node name="GameVersionLabel" type="Label" parent="GUI"]
layout_mode = 0
offset_top = 676.0
offset_right = 188.0
offset_bottom = 718.0
theme_override_font_sizes/font_size = 30
text = "版本号v1.0.1"
[node name="AddGroupLabel" type="Label" parent="GUI"]
self_modulate = Color(1, 1, 0, 1)
layout_mode = 0
offset_left = 896.0
offset_top = 205.0
offset_right = 1226.0
offset_bottom = 247.0
theme_override_font_sizes/font_size = 30
text = "加群获取最新开发动态!"
[node name="QQGroupImage" type="TextureRect" parent="GUI/AddGroupLabel"]
layout_mode = 0
offset_left = 17.0
offset_top = 43.0
offset_right = 952.0
offset_bottom = 1229.0
scale = Vector2(0.3, 0.3)
texture = ExtResource("5_y0inj")
[node name="YouXiaoQing" type="TextureRect" parent="GUI/AddGroupLabel"]
layout_mode = 0
offset_left = 298.0
offset_top = 82.0
offset_right = 1233.0
offset_bottom = 1268.0
scale = Vector2(0.14, 0.14)
texture = ExtResource("5_eghpk")
[node name="VBox" type="VBoxContainer" parent="."]
layout_mode = 0
offset_top = 248.0
offset_right = 1398.0
offset_bottom = 720.0
[node name="StartGameButton" type="Button" parent="VBox"]
custom_minimum_size = Vector2(168, 63)
layout_mode = 2
size_flags_horizontal = 4
theme_override_font_sizes/font_size = 40
text = "开始游戏"
[node name="GameSettingButton" type="Button" parent="VBox"]
custom_minimum_size = Vector2(168, 63)
layout_mode = 2
size_flags_horizontal = 4
theme_override_font_sizes/font_size = 40
text = "设置"
[node name="GameUpdateButton" type="Button" parent="VBox"]
custom_minimum_size = Vector2(168, 63)
layout_mode = 2
size_flags_horizontal = 4
theme_override_font_sizes/font_size = 40
text = "游戏更新"
[node name="GameAboutButton" type="Button" parent="VBox"]
custom_minimum_size = Vector2(168, 63)
layout_mode = 2
size_flags_horizontal = 4
theme_override_font_sizes/font_size = 40
text = "关于"
[node name="ExitButton" type="Button" parent="VBox"]
custom_minimum_size = Vector2(168, 63)
layout_mode = 2
size_flags_horizontal = 4
theme_override_font_sizes/font_size = 40
text = "退出游戏"
[node name="GameSettingPanel" type="Panel" parent="."]
visible = false
layout_mode = 0
offset_right = 1398.0
offset_bottom = 720.0
script = ExtResource("2_n0pjj")
[node name="Title" type="Label" parent="GameSettingPanel"]
layout_mode = 0
offset_right = 1398.0
offset_bottom = 80.0
theme_override_font_sizes/font_size = 45
text = "游戏设置"
horizontal_alignment = 1
vertical_alignment = 1
[node name="QuitButton" type="Button" parent="GameSettingPanel"]
custom_minimum_size = Vector2(60, 60)
layout_mode = 0
offset_left = 1340.0
offset_right = 1400.0
offset_bottom = 60.0
theme_override_font_sizes/font_size = 35
text = "X"
[node name="Scroll" type="ScrollContainer" parent="GameSettingPanel"]
layout_mode = 0
offset_top = 80.0
offset_right = 1400.0
offset_bottom = 720.0
[node name="Contents" type="RichTextLabel" parent="GameSettingPanel/Scroll"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="GameAboutPanel" type="Panel" parent="."]
layout_mode = 0
offset_right = 1398.0
offset_bottom = 720.0
script = ExtResource("3_y0inj")
[node name="Title" type="Label" parent="GameAboutPanel"]
layout_mode = 0
offset_right = 1398.0
offset_bottom = 80.0
theme_override_font_sizes/font_size = 45
text = "关于"
horizontal_alignment = 1
vertical_alignment = 1
[node name="QuitButton" type="Button" parent="GameAboutPanel"]
custom_minimum_size = Vector2(60, 60)
layout_mode = 0
offset_left = 1340.0
offset_right = 1400.0
offset_bottom = 60.0
theme_override_font_sizes/font_size = 35
text = "X"
[node name="Scroll" type="ScrollContainer" parent="GameAboutPanel"]
layout_mode = 0
offset_top = 80.0
offset_right = 1400.0
offset_bottom = 720.0
[node name="Contents" type="RichTextLabel" parent="GameAboutPanel/Scroll"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_font_sizes/normal_font_size = 30
text = "玩法介绍:
1.版本要匹配,服务器版本一直在更新,请及时下载最新版客户端,否者无法登录游戏
2.游戏目前适配Windows和安卓平台未来也会适配Linux桌面版IOS应该会有吧...?
3.电脑Windows平台按住wsad或者方向键可以移动视角鼠标滚轮可以缩放视角安卓则为拖动和双指缩放
3.注册账号一定一定要用QQ号目前游戏的所有登录服务都是围绕着腾讯QQ来验证注册时会向您输入的QQ号对应的QQ邮箱发送一封注册邮件。
4.不要一上来就把钱用完了(比如某某人一上来就十连抽),可以去偷别人的菜
致谢名单:
虚空领主:(美术抠图)
豆包:(万能的美术)"
[node name="GameUpdatePanel" type="Panel" parent="."]
visible = false
layout_mode = 0
offset_right = 1398.0
offset_bottom = 720.0
script = ExtResource("4_fys16")
[node name="Scroll" type="ScrollContainer" parent="GameUpdatePanel"]
layout_mode = 0
offset_top = 80.0
offset_right = 1400.0
offset_bottom = 720.0
[node name="Contents" type="RichTextLabel" parent="GameUpdatePanel/Scroll"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
bbcode_enabled = true
[node name="Title" type="Label" parent="GameUpdatePanel"]
layout_mode = 0
offset_right = 1398.0
offset_bottom = 80.0
theme_override_font_sizes/font_size = 45
text = "游戏更新"
horizontal_alignment = 1
vertical_alignment = 1
[node name="QuitButton" type="Button" parent="GameUpdatePanel"]
custom_minimum_size = Vector2(60, 60)
layout_mode = 0
offset_left = 1340.0
offset_right = 1400.0
offset_bottom = 60.0
theme_override_font_sizes/font_size = 35
text = "X"
[node name="RefreshButton" type="Button" parent="GameUpdatePanel"]
custom_minimum_size = Vector2(60, 60)
layout_mode = 0
offset_right = 78.0
offset_bottom = 60.0
theme_override_font_sizes/font_size = 35
text = "刷新"
[connection signal="pressed" from="VBox/StartGameButton" to="." method="_on_start_game_button_pressed"]
[connection signal="pressed" from="VBox/GameSettingButton" to="." method="_on_game_setting_button_pressed"]
[connection signal="pressed" from="VBox/GameUpdateButton" to="." method="_on_game_update_button_pressed"]
[connection signal="pressed" from="VBox/GameAboutButton" to="." method="_on_game_about_button_pressed"]
[connection signal="pressed" from="VBox/ExitButton" to="." method="_on_exit_button_pressed"]
[connection signal="pressed" from="GameSettingPanel/QuitButton" to="GameSettingPanel" method="_on_quit_button_pressed"]
[connection signal="pressed" from="GameAboutPanel/QuitButton" to="GameAboutPanel" method="_on_quit_button_pressed"]
[connection signal="pressed" from="GameUpdatePanel/QuitButton" to="GameUpdatePanel" method="_on_quit_button_pressed"]

464
GUI/OneClickPlantPanel.gd Normal file
View File

@@ -0,0 +1,464 @@
extends Panel
#一键种植面板
#通过不断地调用土地面板的种植功能来实现一键种植,减少玩家重复性工作
#执行间隔为0.25秒
#目前分为
#全屏种植从序列号0开始依次种植玩家选定植物直到玩家种子用完为止或者完成种植
#行种植:需要玩家点击某个地块,然后从该行从左到右依次种植
#列种植:需要玩家点击某个地块,然后从该列从上到下依次种植
#九宫格种植:需要玩家点击某个地块,然后从该地块上下左右四周九个方向各自种植一个植物
#十字法种植:需要玩家点击某个地块,然后从上下左右四个方向各自种植一个植物
#注意,无论点击的是已经种植的地块,未开垦地块还是空地地块都不影响,因为点击只是为了确认一个具体位置
#然后在一键种植过程中,如果遇到已种植地块,未开垦地块,还是这个方向根本就没有地块等非法操作,没有关系直接跳过即可
#为了方便你确认位置和方向我的客户端地块排列是10行4-8列目前是但不确定以后会不会更改排布你最好留个接口
#你可以参考一下一键收获功能的原理实现
#注意注意,以上操作都是在客户端完成,服务端不要添加什么操作
#默认一键种植收费为种植作物的总和价格的20%+基础费用500
#注意钱不够的问题
@onready var full_screen_plant_btn: Button = $Grid/FullScreenPlantBtn #全屏种植
@onready var one_row_plant_btn: Button = $Grid/OneRowPlantBtn #行种植
@onready var one_column_plant_btn: Button = $Grid/OneColumnPlantBtn #列种植
@onready var nine_square_plant_btn: Button = $Grid/NineSquarePlantBtn #九宫格种植
@onready var cross_plant_btn: Button = $Grid/CrossPlantBtn #十字法种植
# 引用主游戏和其他面板
@onready var main_game = get_node("/root/main")
@onready var player_bag_panel = get_node("/root/main/UI/PlayerBagPanel")
@onready var network_manager = get_node("/root/main/UI/TCPNetworkManager")
# 种植配置
# 注意:地块的实际布局可能与代码设想的不同,这里提供可配置的接口
const GRID_COLUMNS = 10 # 地块列数配置接口,可根据需要调整
const GRID_ROWS_MIN = 4 # 最小行数
const GRID_ROWS_MAX = 8 # 最大行数
const BASE_COST = 500 # 基础费用
const COST_RATE = 0.2 # 种植成本比例20%
const PLANT_INTERVAL = 0.25 # 种植间隔时间
# 种植状态变量
var is_planting = false
var selected_crop_name = ""
var selected_crop_count = 0
var plant_timer = 0.0
var plant_queue = [] # 种植队列,存储要种植的地块索引
var current_plant_index = 0
# 等待用户点击地块的状态
var is_waiting_for_lot_selection = false
var pending_plant_type = ""
func _ready():
self.hide()
# 连接按钮信号
full_screen_plant_btn.pressed.connect(_on_full_screen_plant_pressed)
one_row_plant_btn.pressed.connect(_on_one_row_plant_pressed)
one_column_plant_btn.pressed.connect(_on_one_column_plant_pressed)
nine_square_plant_btn.pressed.connect(_on_nine_square_plant_pressed)
cross_plant_btn.pressed.connect(_on_cross_plant_pressed)
# 设置按钮提示文本
_setup_button_tooltips()
func _process(delta):
if is_planting:
plant_timer += delta
if plant_timer >= PLANT_INTERVAL:
plant_timer = 0.0
_process_plant_queue()
# 全屏种植按钮处理
func _on_full_screen_plant_pressed():
_request_crop_selection("全屏种植", "选择要种植的作物进行全屏种植")
# 行种植按钮处理
func _on_one_row_plant_pressed():
_start_lot_selection_mode("行种植")
# 列种植按钮处理
func _on_one_column_plant_pressed():
_start_lot_selection_mode("列种植")
# 九宫格种植按钮处理
func _on_nine_square_plant_pressed():
_start_lot_selection_mode("九宫格种植")
# 十字法种植按钮处理
func _on_cross_plant_pressed():
_start_lot_selection_mode("十字法种植")
# 开始地块选择模式
func _start_lot_selection_mode(plant_type: String):
is_waiting_for_lot_selection = true
pending_plant_type = plant_type
# 隐藏一键种植面板
self.hide()
# 显示提示信息
var tip_message = ""
match plant_type:
"行种植":
tip_message = "请点击一个地块来确定要种植的行"
"列种植":
tip_message = "请点击一个地块来确定要种植的列"
"九宫格种植":
tip_message = "请点击一个地块来确定九宫格种植的中心位置"
"十字法种植":
tip_message = "请点击一个地块来确定十字法种植的中心位置"
_:
tip_message = "请点击一个地块"
Toast.show(tip_message + "按ESC键取消", Color.CYAN)
print("进入地块选择模式:%s" % plant_type)
# 处理地块选择从MainGame调用
func on_lot_selected(lot_index: int):
if not is_waiting_for_lot_selection:
return false # 不是等待地块选择状态返回false让MainGame正常处理
# 退出地块选择模式
is_waiting_for_lot_selection = false
# 设置选择的地块索引
main_game.selected_lot_index = lot_index
# 开始作物选择
_request_crop_selection(pending_plant_type, "选择要种植的作物进行" + pending_plant_type)
# 清空待处理的种植类型
pending_plant_type = ""
return true # 返回true表示已处理了地块选择
# 请求作物选择
func _request_crop_selection(plant_type: String, tip_message: String):
# 检查背包是否有种子
if main_game.player_bag.size() == 0:
Toast.show("背包中没有种子,请先去商店购买", Color.RED)
return
var has_seeds = false
for item in main_game.player_bag:
if item["count"] > 0:
has_seeds = true
break
if not has_seeds:
Toast.show("背包中没有可用的种子", Color.RED)
return
Toast.show(tip_message, Color.CYAN)
self.hide()
# 设置背包面板的种植模式回调
player_bag_panel.set_planting_mode(plant_type, self)
player_bag_panel.show()
# 背包选择作物回调函数
func on_crop_selected(crop_name: String, plant_type: String):
selected_crop_name = crop_name
# 检查背包中的作物数量
selected_crop_count = _get_crop_count_in_bag(crop_name)
if selected_crop_count <= 0:
Toast.show("背包中没有 " + crop_name + " 种子", Color.RED)
return
print("开始准备一键种植:")
print(" 选择作物:%s" % crop_name)
print(" 种植模式:%s" % plant_type)
print(" 背包数量:%d" % selected_crop_count)
# 根据种植类型生成种植队列
match plant_type:
"全屏种植":
_prepare_full_screen_plant()
"行种植":
_prepare_row_plant()
"列种植":
_prepare_column_plant()
"九宫格种植":
_prepare_nine_square_plant()
"十字法种植":
_prepare_cross_plant()
_:
Toast.show("未知的种植模式:" + plant_type, Color.RED)
print("错误:未知的种植模式:%s" % plant_type)
# 获取背包中指定作物的数量
func _get_crop_count_in_bag(crop_name: String) -> int:
for item in main_game.player_bag:
if item["name"] == crop_name:
return item["count"]
return 0
# 准备全屏种植
func _prepare_full_screen_plant():
plant_queue.clear()
# 从序列号0开始依次添加可种植的地块
for i in range(len(main_game.farm_lots)):
if _can_plant_at_index(i):
plant_queue.append(i)
_start_planting("全屏种植")
# 准备行种植
func _prepare_row_plant():
plant_queue.clear()
var target_row = _get_row_from_index(main_game.selected_lot_index)
# 添加同一行的所有可种植地块(从左到右)
for i in range(len(main_game.farm_lots)):
if _get_row_from_index(i) == target_row and _can_plant_at_index(i):
plant_queue.append(i)
_start_planting("行种植")
# 准备列种植
func _prepare_column_plant():
plant_queue.clear()
var target_column = _get_column_from_index(main_game.selected_lot_index)
# 添加同一列的所有可种植地块(从上到下)
for i in range(len(main_game.farm_lots)):
if _get_column_from_index(i) == target_column and _can_plant_at_index(i):
plant_queue.append(i)
_start_planting("列种植")
# 准备九宫格种植
func _prepare_nine_square_plant():
plant_queue.clear()
var center_row = _get_row_from_index(main_game.selected_lot_index)
var center_column = _get_column_from_index(main_game.selected_lot_index)
# 九宫格的相对位置偏移
var offsets = [
[-1, -1], [-1, 0], [-1, 1],
[0, -1], [0, 0], [0, 1],
[1, -1], [1, 0], [1, 1]
]
for offset in offsets:
var row = center_row + offset[0]
var column = center_column + offset[1]
var index = _get_index_from_row_column(row, column)
if index != -1 and _can_plant_at_index(index):
plant_queue.append(index)
_start_planting("九宫格种植")
# 准备十字法种植
func _prepare_cross_plant():
plant_queue.clear()
var center_row = _get_row_from_index(main_game.selected_lot_index)
var center_column = _get_column_from_index(main_game.selected_lot_index)
# 十字法的相对位置偏移
var offsets = [
[0, 0], # 中心
[-1, 0], # 上
[1, 0], # 下
[0, -1], # 左
[0, 1] # 右
]
for offset in offsets:
var row = center_row + offset[0]
var column = center_column + offset[1]
var index = _get_index_from_row_column(row, column)
if index != -1 and _can_plant_at_index(index):
plant_queue.append(index)
_start_planting("十字法种植")
# 开始种植
func _start_planting(plant_type: String):
if plant_queue.size() == 0:
Toast.show("没有可种植的地块", Color.YELLOW)
return
# 限制种植数量不超过背包中的种子数量
var max_plantable = min(plant_queue.size(), selected_crop_count)
if max_plantable < plant_queue.size():
plant_queue = plant_queue.slice(0, max_plantable)
# 计算总费用
var crop_data = main_game.can_planted_crop.get(selected_crop_name, {})
var crop_price = crop_data.get("花费", 0)
var total_crop_cost = crop_price * plant_queue.size()
var service_fee = int(total_crop_cost * COST_RATE) + BASE_COST
var total_cost = service_fee # 只收取服务费,种子费用由种植时扣除
print("一键种植费用计算:")
print(" 作物:%s,单价:%d" % [selected_crop_name, crop_price])
print(" 种植数量:%d 个地块" % plant_queue.size())
print(" 作物总成本:%d" % total_crop_cost)
print(" 服务费率:%.1f%%" % (COST_RATE * 100))
print(" 基础费用:%d" % BASE_COST)
print(" 总服务费:%d" % total_cost)
print(" 玩家当前金钱:%d" % main_game.money)
# 检查金钱是否足够支付服务费
if main_game.money < total_cost:
Toast.show("金钱不足!%s需要服务费 %d 元(当前:%d 元)" % [plant_type, total_cost, main_game.money], Color.RED)
return
# 扣除服务费
main_game.money -= total_cost
main_game._update_ui()
# 开始种植
is_planting = true
current_plant_index = 0
plant_timer = 0.0
# 更新按钮状态为种植中
_update_buttons_planting_state(true)
Toast.show("开始%s,预计种植 %d 个地块,服务费 %d" % [plant_type, plant_queue.size(), total_cost], Color.GREEN)
print("开始%s,种植队列: %s" % [plant_type, str(plant_queue)])
# 处理种植队列
func _process_plant_queue():
if current_plant_index >= plant_queue.size():
# 种植完成
_finish_planting()
return
var lot_index = plant_queue[current_plant_index]
# 检查是否还有种子和该地块是否仍可种植
if _get_crop_count_in_bag(selected_crop_name) > 0 and _can_plant_at_index(lot_index):
# 执行种植
_plant_at_index(lot_index)
current_plant_index += 1
# 完成种植
func _finish_planting():
is_planting = false
var planted_count = current_plant_index
var success_count = min(planted_count, selected_crop_count)
# 恢复按钮状态
_update_buttons_planting_state(false)
Toast.show("一键种植完成!成功种植 %d 个地块" % success_count, Color.GREEN)
print("一键种植完成,成功种植了 %d 个地块" % success_count)
# 清空队列
plant_queue.clear()
current_plant_index = 0
# 在指定索引处种植
func _plant_at_index(lot_index: int):
if network_manager and network_manager.sendPlantCrop(lot_index, selected_crop_name):
print("发送种植请求:地块 %d,作物 %s" % [lot_index, selected_crop_name])
else:
print("发送种植请求失败:地块 %d" % lot_index)
# 检查指定索引的地块是否可以种植
func _can_plant_at_index(index: int) -> bool:
if index < 0 or index >= len(main_game.farm_lots):
return false
var lot = main_game.farm_lots[index]
# 必须是已开垦且未种植的地块
return lot.get("is_diged", false) and not lot.get("is_planted", false)
# 根据索引获取行号
func _get_row_from_index(index: int) -> int:
if index < 0:
return -1
return index / GRID_COLUMNS
# 根据索引获取列号
func _get_column_from_index(index: int) -> int:
if index < 0:
return -1
return index % GRID_COLUMNS
# 根据行列号获取索引
func _get_index_from_row_column(row: int, column: int) -> int:
if row < 0 or column < 0 or column >= GRID_COLUMNS:
return -1
var index = row * GRID_COLUMNS + column
if index >= len(main_game.farm_lots):
return -1
return index
# 设置按钮提示文本
func _setup_button_tooltips():
full_screen_plant_btn.tooltip_text = "从第一个地块开始依次种植选定作物,直到种子用完或地块种完\n费用种植总成本的20% + 500元基础费"
one_row_plant_btn.tooltip_text = "在选定地块所在的行中从左到右依次种植\n点击此按钮后,再点击农场中的任意地块确定行位置\n费用种植总成本的20% + 500元基础费"
one_column_plant_btn.tooltip_text = "在选定地块所在的列中从上到下依次种植\n点击此按钮后,再点击农场中的任意地块确定列位置\n费用种植总成本的20% + 500元基础费"
nine_square_plant_btn.tooltip_text = "以选定地块为中心的3x3九宫格范围内种植\n点击此按钮后,再点击农场中的任意地块确定中心位置\n费用种植总成本的20% + 500元基础费"
cross_plant_btn.tooltip_text = "以选定地块为中心的十字形(上下左右+中心)种植\n点击此按钮后,再点击农场中的任意地块确定中心位置\n费用种植总成本的20% + 500元基础费"
# 更新按钮状态
func _update_buttons_planting_state(planting: bool):
if planting:
# 种植中,禁用所有种植按钮
full_screen_plant_btn.disabled = true
one_row_plant_btn.disabled = true
one_column_plant_btn.disabled = true
nine_square_plant_btn.disabled = true
cross_plant_btn.disabled = true
full_screen_plant_btn.text = "种植中..."
one_row_plant_btn.text = "种植中..."
one_column_plant_btn.text = "种植中..."
nine_square_plant_btn.text = "种植中..."
cross_plant_btn.text = "种植中..."
else:
# 种植完成,恢复按钮状态
full_screen_plant_btn.disabled = false
one_row_plant_btn.disabled = false
one_column_plant_btn.disabled = false
nine_square_plant_btn.disabled = false
cross_plant_btn.disabled = false
full_screen_plant_btn.text = "全屏种植"
one_row_plant_btn.text = "行种植"
one_column_plant_btn.text = "列种植"
nine_square_plant_btn.text = "九宫格种植"
cross_plant_btn.text = "十字法种植"
# 取消地块选择模式
func cancel_lot_selection():
if is_waiting_for_lot_selection:
is_waiting_for_lot_selection = false
pending_plant_type = ""
Toast.show("已取消地块选择", Color.YELLOW)
print("用户取消了地块选择")
# 重新显示一键种植面板
self.show()
# 停止当前种植过程
func stop_planting():
if is_planting:
is_planting = false
Toast.show("一键种植已停止", Color.YELLOW)
print("用户停止了一键种植")
_finish_planting()
#这个不用管
func _on_quit_button_pressed() -> void:
# 如果正在种植,先停止种植
if is_planting:
stop_planting()
# 如果正在等待地块选择,取消选择
elif is_waiting_for_lot_selection:
cancel_lot_selection()
return # cancel_lot_selection已经重新显示了面板不需要hide
self.hide()
pass

View File

@@ -0,0 +1 @@
uid://rlk8e51pibtm

View File

@@ -73,6 +73,10 @@ func init_store():
for crop_name in main_game.can_planted_crop:
var crop = main_game.can_planted_crop[crop_name]
# 检查是否可以购买
if not crop.get("能否购买", true):
continue
# 只显示当前等级可以种植的作物
if crop["等级"] <= main_game.level:
var store_btn = _create_store_button(crop_name, crop["品质"])
@@ -192,8 +196,6 @@ func _on_store_buy_pressed(crop_name: String):
# 发送购买请求到服务器
if network_manager and network_manager.sendBuySeed(crop_name):
# 购买请求已发送,等待服务器响应
Toast.show("正在购买种子...", Color.YELLOW, 2.0, 1.0)
# 将种子添加到背包
var found = false
@@ -253,6 +255,10 @@ func _apply_filter_and_sort():
for crop_name in main_game.can_planted_crop:
var crop = main_game.can_planted_crop[crop_name]
# 检查是否可以购买
if not crop.get("能否购买", true):
continue
# 检查等级和品质过滤
if crop["等级"] > main_game.level:
continue
@@ -400,7 +406,7 @@ func _load_crop_textures(crop_name: String) -> Array:
# 尝试加载作物的序列帧从0开始
var frame_index = 0
while true:
var texture_path = crop_path + str(frame_index) + ".png"
var texture_path = crop_path + str(frame_index) + ".webp"
if ResourceLoader.exists(texture_path):
var texture = load(texture_path)
if texture:
@@ -440,7 +446,7 @@ func _load_default_textures() -> Array:
# 尝试加载默认图片序列帧
var frame_index = 0
while true:
var texture_path = default_path + str(frame_index) + ".png"
var texture_path = default_path + str(frame_index) + ".webp"
if ResourceLoader.exists(texture_path):
var texture = load(texture_path)
if texture:
@@ -453,7 +459,7 @@ func _load_default_textures() -> Array:
# 如果没有找到序列帧,尝试加载单个默认图片
if textures.size() == 0:
var single_texture_path = default_path + "0.png"
var single_texture_path = default_path + "0.webp"
if ResourceLoader.exists(single_texture_path):
var texture = load(single_texture_path)
if texture:

View File

@@ -39,13 +39,79 @@ func _ready():
_update_button_texts()
# 显示面板时更新按钮状态
func show_panel():
self.show()
_update_button_texts()
_update_button_availability()
# 更新按钮可用性
func _update_button_availability():
if main_game.is_visiting_mode:
# 访问模式下禁用一些按钮
dig_button.hide()
remove_button.hide()
upgrade_button.hide()
plant_button.hide()
# 启用允许的按钮
water_button.show()
fertilize_button.show()
harvest_button.show()
else:
# 自己农场模式下启用所有按钮
dig_button.show()
remove_button.show()
upgrade_button.show()
plant_button.show()
water_button.show()
fertilize_button.show()
harvest_button.show()
# 更新按钮文本
func _update_button_texts():
dig_button.text = "开垦"+"\n"+str(main_game.dig_money)
remove_button.text = "铲除"+"\n¥500"
water_button.text = "浇水"+"\n¥50"
fertilize_button.text = "施肥"+"\n¥150"
upgrade_button.text = "升级"+"\n¥1000"
# 根据是否访问模式显示不同的按钮文本
if main_game.is_visiting_mode:
water_button.text = "帮助浇水"+"\n¥50"
fertilize_button.text = "帮助施肥"+"\n¥150"
harvest_button.text = "偷菜"
else:
dig_button.text = "开垦"+"\n"+str(main_game.dig_money)
remove_button.text = "铲除"+"\n¥500"
water_button.text = "浇水"+"\n¥50"
fertilize_button.text = "施肥"+"\n¥150"
# 升级按钮动态显示
_update_upgrade_button_text()
harvest_button.text = "收获"
# 更新升级按钮文本
func _update_upgrade_button_text():
if not main_game or not main_game.farm_lots:
upgrade_button.text = "升级\n¥1000"
return
if selected_lot_index >= 0 and selected_lot_index < main_game.farm_lots.size():
var lot = main_game.farm_lots[selected_lot_index]
var current_level = int(lot.get("土地等级", 0)) # 确保是整数
var upgrade_config = {
0: {"cost": 1000, "name": "黄土地"},
1: {"cost": 2000, "name": "红土地"},
2: {"cost": 4000, "name": "紫土地"},
3: {"cost": 8000, "name": "黑土地"}
}
if current_level >= 4:
upgrade_button.text = "已满级"
elif upgrade_config.has(current_level):
var config = upgrade_config[current_level]
upgrade_button.text = "升级到\n" + config["name"] + "\n" + str(config["cost"])
else:
upgrade_button.text = "等级异常\n" + str(current_level)
else:
upgrade_button.text = "选择地块"
#开垦
func _on_dig_button_pressed():
@@ -72,7 +138,6 @@ func _on_dig_button_pressed():
# 发送开垦土地请求到服务器
if network_manager and network_manager.is_connected_to_server():
if network_manager.sendDigGround(selected_lot_index):
Toast.show("正在开垦土地...", Color.YELLOW, 1.5, 1.0)
self.hide()
else:
Toast.show("发送开垦请求失败", Color.RED, 2.0, 1.0)
@@ -80,18 +145,20 @@ func _on_dig_button_pressed():
else:
Toast.show("网络未连接,无法开垦土地", Color.RED, 2.0, 1.0)
self.hide()
#浇水
func _on_water_button_pressed():
# 检查是否处于访问模式
if main_game.is_visiting_mode:
Toast.show("访问模式下无法浇水", Color.ORANGE, 2.0, 1.0)
self.hide()
return
# 检查玩家金钱是否足够
# 检查玩家金钱是否足够(无论是否访问模式都检查自己的钱)
var water_cost = 50
if main_game.money < water_cost:
Toast.show("金钱不足,浇水需要 " + str(water_cost) + " 金钱", Color.RED, 2.0, 1.0)
var my_money = main_game.money
# 如果是访问模式,需要检查自己的原始金钱数据
if main_game.is_visiting_mode:
my_money = main_game.original_player_data.get("money", 0)
if my_money < water_cost:
var action_text = "帮助浇水" if main_game.is_visiting_mode else "浇水"
Toast.show("金钱不足," + action_text + "需要 " + str(water_cost) + " 金钱", Color.RED, 2.0, 1.0)
self.hide()
return
@@ -115,34 +182,47 @@ func _on_water_button_pressed():
return
# 检查是否已经浇过水
if lot.get("已浇水", false):
Toast.show("今天已经浇过水了", Color.ORANGE, 2.0, 1.0)
var current_time = Time.get_unix_time_from_system()
var last_water_time = lot.get("浇水时间", 0)
var water_cooldown = 3600 # 1小时冷却时间
if current_time - last_water_time < water_cooldown:
var remaining_time = water_cooldown - (current_time - last_water_time)
var remaining_minutes = int(remaining_time / 60)
var remaining_seconds = int(remaining_time) % 60
Toast.show("浇水冷却中,还需等待 " + str(remaining_minutes) + " 分钟 " + str(remaining_seconds) + "", Color.ORANGE, 2.0, 1.0)
self.hide()
return
# 发送浇水请求到服务器
var target_username = ""
if main_game.is_visiting_mode:
target_username = main_game.visited_player_data.get("user_name", "")
if network_manager and network_manager.is_connected_to_server():
if network_manager.sendWaterCrop(selected_lot_index):
Toast.show("正在浇水...", Color.YELLOW, 1.5, 1.0)
if network_manager.sendWaterCrop(selected_lot_index, target_username):
self.hide()
else:
Toast.show("发送浇水请求失败", Color.RED, 2.0, 1.0)
self.hide()
else:
Toast.show("网络未连接,无法浇水", Color.RED, 2.0, 1.0)
var action_text = "帮助浇水" if main_game.is_visiting_mode else "浇水"
Toast.show("网络未连接,无法" + action_text, Color.RED, 2.0, 1.0)
self.hide()
#施肥
func _on_fertilize_button_pressed():
# 检查是否处于访问模式
if main_game.is_visiting_mode:
Toast.show("访问模式下无法施肥", Color.ORANGE, 2.0, 1.0)
self.hide()
return
# 检查玩家金钱是否足够
# 检查玩家金钱是否足够(无论是否访问模式都检查自己的钱)
var fertilize_cost = 150
if main_game.money < fertilize_cost:
Toast.show("金钱不足,施肥需要 " + str(fertilize_cost) + " 金钱", Color.RED, 2.0, 1.0)
var my_money = main_game.money
# 如果是访问模式,需要检查自己的原始金钱数据
if main_game.is_visiting_mode:
my_money = main_game.original_player_data.get("money", 0)
if my_money < fertilize_cost:
var action_text = "帮助施肥" if main_game.is_visiting_mode else "施肥"
Toast.show("金钱不足," + action_text + "需要 " + str(fertilize_cost) + " 金钱", Color.RED, 2.0, 1.0)
self.hide()
return
@@ -172,16 +252,21 @@ func _on_fertilize_button_pressed():
return
# 发送施肥请求到服务器
var target_username = ""
if main_game.is_visiting_mode:
target_username = main_game.visited_player_data.get("user_name", "")
if network_manager and network_manager.is_connected_to_server():
if network_manager.sendFertilizeCrop(selected_lot_index):
Toast.show("正在施肥...", Color.YELLOW, 1.5, 1.0)
if network_manager.sendFertilizeCrop(selected_lot_index, target_username):
self.hide()
else:
Toast.show("发送施肥请求失败", Color.RED, 2.0, 1.0)
self.hide()
else:
Toast.show("网络未连接,无法施肥", Color.RED, 2.0, 1.0)
var action_text = "帮助施肥" if main_game.is_visiting_mode else "施肥"
Toast.show("网络未连接,无法" + action_text, Color.RED, 2.0, 1.0)
self.hide()
#升级
func _on_upgrade_button_pressed():
# 检查是否处于访问模式
@@ -190,31 +275,61 @@ func _on_upgrade_button_pressed():
self.hide()
return
# 检查玩家金钱是否足够
var upgrade_cost = 1000
if main_game.money < upgrade_cost:
Toast.show("金钱不足,升级土地需要 " + str(upgrade_cost) + " 金钱", Color.RED, 2.0, 1.0)
# 检查地块索引是否有效
if selected_lot_index < 0 or selected_lot_index >= main_game.farm_lots.size():
Toast.show("无效的地块选择", Color.RED, 2.0, 1.0)
self.hide()
return
# 检查地块是否已开垦
# 获取地块数据
var lot = main_game.farm_lots[selected_lot_index]
# 检查地块是否已开垦
if not lot.get("is_diged", false):
Toast.show("此地块尚未开垦", Color.ORANGE, 2.0, 1.0)
self.hide()
return
# 检查土地是否已经升级
var current_level = lot.get("土地等级", 0)
if current_level >= 1:
Toast.show("此土地已经升级过了", Color.ORANGE, 2.0, 1.0)
# 获取当前土地等级和升级配置
var current_level = int(lot.get("土地等级", 0)) # 确保是整数
print("当前选择地块索引: ", selected_lot_index)
print("当前土地等级: ", current_level, " (类型: ", typeof(current_level), ")")
var upgrade_config = {
0: {"cost": 1000, "name": "黄土地", "speed": "2倍"},
1: {"cost": 2000, "name": "红土地", "speed": "4倍"},
2: {"cost": 4000, "name": "紫土地", "speed": "6倍"},
3: {"cost": 8000, "name": "黑土地", "speed": "10倍"}
}
# 检查是否已达到最高等级
if current_level >= 4:
Toast.show("此土地已达到最高等级(黑土地)", Color.ORANGE, 2.0, 1.0)
self.hide()
return
# 检查土地等级是否有效
if not upgrade_config.has(current_level):
Toast.show("土地等级数据异常,当前等级: " + str(current_level), Color.RED, 2.0, 1.0)
print("土地等级异常,当前等级: ", current_level, ",可用等级: ", upgrade_config.keys())
self.hide()
return
var config = upgrade_config[current_level]
var upgrade_cost = config["cost"]
var next_name = config["name"]
var speed_info = config["speed"]
# 检查玩家金钱是否足够
if main_game.money < upgrade_cost:
Toast.show("金钱不足,升级到" + next_name + "需要 " + str(upgrade_cost) + " 金钱", Color.RED, 2.0, 1.0)
self.hide()
return
# 发送升级请求到服务器
if network_manager and network_manager.is_connected_to_server():
print("发送升级请求,地块索引: ", selected_lot_index, ",当前等级: ", current_level)
if network_manager.sendUpgradeLand(selected_lot_index):
Toast.show("正在升级土地...", Color.YELLOW, 1.5, 1.0)
self.hide()
else:
Toast.show("发送升级请求失败", Color.RED, 2.0, 1.0)
@@ -222,6 +337,7 @@ func _on_upgrade_button_pressed():
else:
Toast.show("网络未连接,无法升级土地", Color.RED, 2.0, 1.0)
self.hide()
#种植
func _on_plant_button_pressed():
# 检查是否处于访问模式
@@ -258,7 +374,6 @@ func _on_remove_button_pressed():
# 发送铲除作物请求到服务器
if network_manager and network_manager.is_connected_to_server():
if network_manager.sendRemoveCrop(selected_lot_index):
Toast.show("正在铲除作物...", Color.YELLOW, 1.5, 1.0)
self.hide()
else:
Toast.show("发送铲除请求失败", Color.RED, 2.0, 1.0)
@@ -267,17 +382,39 @@ func _on_remove_button_pressed():
Toast.show("网络未连接,无法铲除作物", Color.RED, 2.0, 1.0)
self.hide()
pass
#收获
func _on_harvest_button_pressed():
# 检查是否处于访问模式
if main_game.is_visiting_mode:
Toast.show("访问模式下无法收获作物", Color.ORANGE, 2.0, 1.0)
# 检查地块状态
var lot = main_game.farm_lots[selected_lot_index]
if not lot.get("is_planted", false) or lot.get("crop_type", "") == "":
Toast.show("此地块没有种植作物", Color.ORANGE, 2.0, 1.0)
self.hide()
return
main_game._harvest_crop(selected_lot_index)
self.hide()
# 检查作物是否成熟
if lot.get("grow_time", 0) < lot.get("max_grow_time", 1) and not lot.get("is_dead", false):
Toast.show("作物尚未成熟", Color.ORANGE, 2.0, 1.0)
self.hide()
return
# 发送收获请求到服务器
var target_username = ""
if main_game.is_visiting_mode:
target_username = main_game.visited_player_data.get("user_name", "")
if network_manager and network_manager.is_connected_to_server():
if network_manager.sendHarvestCrop(selected_lot_index, target_username):
self.hide()
else:
Toast.show("发送收获请求失败", Color.RED, 2.0, 1.0)
self.hide()
else:
var action_text = "偷菜" if main_game.is_visiting_mode else "收获"
Toast.show("网络未连接,无法" + action_text, Color.RED, 2.0, 1.0)
self.hide()
pass
#退出
func _on_quit_button_pressed():
self.hide()

View File

@@ -65,14 +65,16 @@ func _on_login_button_pressed():
status_label.text = "未连接到服务器,正在尝试连接..."
status_label.modulate = Color.YELLOW
# 尝试自动连接到服务器
tcp_network_manager._on_connection_button_pressed()
await get_tree().create_timer(1.0).timeout
tcp_network_manager.connect_to_current_server()
await get_tree().create_timer(2.0).timeout
# 再次检查连接状态
if !tcp_network_manager.client.is_client_connected():
status_label.text = "连接服务器失败,请检查网络设置!"
status_label.modulate = Color.RED
return
status_label.text = "连接服务器失败,正在尝试其他服务器..."
status_label.modulate = Color.YELLOW
# 等待自动服务器切换完成
await get_tree().create_timer(3.0).timeout
# 禁用按钮,防止重复点击
login_button.disabled = true
@@ -116,14 +118,16 @@ func _on_send_button_pressed():
status_label.text = "未连接到服务器,正在尝试连接..."
status_label.modulate = Color.YELLOW
# 尝试自动连接到服务器
tcp_network_manager._on_connection_button_pressed()
await get_tree().create_timer(1.0).timeout
tcp_network_manager.connect_to_current_server()
await get_tree().create_timer(2.0).timeout
# 再次检查连接状态
if !tcp_network_manager.client.is_client_connected():
status_label.text = "连接服务器失败,请检查网络设置!"
status_label.modulate = Color.RED
return
status_label.text = "连接服务器失败,正在尝试其他服务器..."
status_label.modulate = Color.YELLOW
# 等待自动服务器切换完成
await get_tree().create_timer(3.0).timeout
# 禁用按钮,防止重复点击
send_button.disabled = true
@@ -192,14 +196,16 @@ func _on_register_button_pressed():
status_label.text = "未连接到服务器,正在尝试连接..."
status_label.modulate = Color.YELLOW
# 尝试自动连接到服务器
tcp_network_manager._on_connection_button_pressed()
await get_tree().create_timer(1.0).timeout
tcp_network_manager.connect_to_current_server()
await get_tree().create_timer(2.0).timeout
# 再次检查连接状态
if !tcp_network_manager.client.is_client_connected():
status_label.text = "连接服务器失败,请检查网络设置!"
status_label.modulate = Color.RED
return
status_label.text = "连接服务器失败,正在尝试其他服务器..."
status_label.modulate = Color.YELLOW
# 等待自动服务器切换完成
await get_tree().create_timer(3.0).timeout
# 禁用按钮,防止重复点击
register_button.disabled = true
@@ -271,11 +277,15 @@ func _on_login_response_received(success: bool, message: String, user_data: Dict
status_label.text = "登录成功!正在加载游戏..."
status_label.modulate = Color.GREEN
# 保存登录数据到主游戏
main_game.login_data = user_data.duplicate()
# 更新主游戏数据
main_game.experience = user_data.get("experience", 0)
main_game.farm_lots = user_data.get("farm_lots", [])
main_game.level = user_data.get("level", 1)
main_game.money = user_data.get("money", 0)
main_game.stamina = user_data.get("体力值", 20)
main_game.show_farm_name.text = "农场名称:"+user_data.get("farm_name", "")
main_game.show_player_name.text = "玩家昵称:"+user_data.get("player_name", "")
farmname_input.text = user_data.get("farm_name", "")
@@ -293,6 +303,9 @@ func _on_login_response_received(success: bool, message: String, user_data: Dict
main_game._update_ui()
main_game._refresh_farm_lots()
player_bag_panel.update_player_bag_ui()
# 调用主游戏的登录成功处理函数
main_game.handle_login_success(user_data)
else:
status_label.text = "登录失败:" + message
status_label.modulate = Color.RED

View File

@@ -36,6 +36,11 @@ var current_filter_quality = ""
var current_sort_key = ""
var current_sort_ascending = true
# 一键种植模式相关变量
var is_planting_mode = false
var planting_type = ""
var one_click_plant_panel = null
# 准备函数
func _ready():
# 连接按钮信号
@@ -278,6 +283,16 @@ func _on_bag_seed_selected(crop_name):
Toast.show("访问模式下无法种植", Color.ORANGE, 2.0, 1.0)
return
# 检查是否是一键种植模式
if is_planting_mode:
# 一键种植模式下,回调给一键种植面板
if one_click_plant_panel and one_click_plant_panel.has_method("on_crop_selected"):
one_click_plant_panel.on_crop_selected(crop_name, planting_type)
# 退出种植模式
_exit_planting_mode()
self.hide()
return
# 从主场景获取当前选择的地块索引
selected_lot_index = main_game.selected_lot_index
@@ -344,13 +359,28 @@ func _plant_crop_from_bag(index, crop_name, seed_index):
# 发送种植请求到服务器
if network_manager and network_manager.sendPlantCrop(index, crop_name):
# 种植请求已发送,等待服务器响应
Toast.show("正在发送种植请求", Color.YELLOW, 2.0, 1.0)
# 关闭背包面板
hide()
# 设置种植模式
func set_planting_mode(plant_type: String, plant_panel):
is_planting_mode = true
planting_type = plant_type
one_click_plant_panel = plant_panel
print("进入种植模式:", plant_type)
# 退出种植模式
func _exit_planting_mode():
is_planting_mode = false
planting_type = ""
one_click_plant_panel = null
print("退出种植模式")
# 关闭面板
func _on_quit_button_pressed():
# 退出种植模式(如果当前在种植模式下)
if is_planting_mode:
_exit_planting_mode()
self.hide()
# 获取作物的最后一帧图片(用于背包显示)
@@ -389,7 +419,7 @@ func _load_crop_textures(crop_name: String) -> Array:
# 尝试加载作物的序列帧从0开始
var frame_index = 0
while true:
var texture_path = crop_path + str(frame_index) + ".png"
var texture_path = crop_path + str(frame_index) + ".webp"
if ResourceLoader.exists(texture_path):
var texture = load(texture_path)
if texture:
@@ -429,7 +459,7 @@ func _load_default_textures() -> Array:
# 尝试加载默认图片序列帧
var frame_index = 0
while true:
var texture_path = default_path + str(frame_index) + ".png"
var texture_path = default_path + str(frame_index) + ".webp"
if ResourceLoader.exists(texture_path):
var texture = load(texture_path)
if texture:
@@ -442,7 +472,7 @@ func _load_default_textures() -> Array:
# 如果没有找到序列帧,尝试加载单个默认图片
if textures.size() == 0:
var single_texture_path = default_path + "0.png"
var single_texture_path = default_path + ".webp"
if ResourceLoader.exists(single_texture_path):
var texture = load(single_texture_path)
if texture:

View File

@@ -60,13 +60,21 @@ text = "访问"
layout_mode = 2
[node name="LastLoginTime" type="Label" parent="HBox2"]
modulate = Color(0.811765, 1, 0.811765, 1)
layout_mode = 2
size_flags_horizontal = 3
theme_override_font_sizes/font_size = 20
text = "最后在线2025年12时09分35秒"
[node name="OnlineTime" type="Label" parent="HBox2"]
modulate = Color(0.784314, 0.733333, 0.521569, 1)
layout_mode = 2
size_flags_horizontal = 3
theme_override_font_sizes/font_size = 20
text = "累计在线时长99时60分60秒"
[node name="IsOnlineTime" type="Label" parent="HBox2"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_font_sizes/font_size = 20
text = "正在检测中..."

View File

@@ -3,6 +3,8 @@ extends Panel
@onready var player_ranking_list : VBoxContainer = $Scroll/PlayerList
@onready var refresh_button : Button = $RefreshButton
@onready var quit_button : Button = $QuitButton
@onready var register_player_num: Label = $RegisterPlayerNum #显示注册总人数
#预添加常用的面板
@onready var main_game = get_node("/root/main")
@@ -19,35 +21,72 @@ extends Panel
func _ready() -> void:
# 隐藏模板
player_info_template.visible = false
# 连接按钮信号
refresh_button.pressed.connect(_on_refresh_button_pressed)
quit_button.pressed.connect(_on_quit_button_pressed)
# 初始加载排行榜
request_player_rankings()
# 请求玩家排行榜数据
func request_player_rankings():
if network_manager:
network_manager.sendGetPlayerRankings()
if not network_manager:
print("网络管理器不可用")
register_player_num.text = "网络管理器不可用"
register_player_num.modulate = Color.RED
return false
if not network_manager.is_connected_to_server():
print("未连接到服务器")
register_player_num.text = "未连接服务器"
register_player_num.modulate = Color.RED
return false
var success = network_manager.sendGetPlayerRankings()
if not success:
print("发送排行榜请求失败")
register_player_num.text = "请求发送失败"
register_player_num.modulate = Color.RED
return false
return true
# 处理玩家排行榜响应
func handle_player_rankings_response(data):
# 重新启用刷新按钮
refresh_button.disabled = false
refresh_button.text = "刷新"
# 检查响应是否成功
if not data.get("success", false):
print("获取玩家排行榜失败:", data.get("message", "未知错误"))
register_player_num.text = "获取注册人数失败"
register_player_num.modulate = Color.RED
Toast.show("获取排行榜失败:" + data.get("message", "未知错误"), Color.RED)
return
# 显示注册总人数和在线人数
var total_registered = data.get("total_registered_players", 0)
var players_list = data.get("players", [])
var online_count = 0
for player in players_list:
if player.get("is_online", false):
online_count += 1
register_player_num.text = "总人数:" + str(int(total_registered)) + "| 在线:" + str(online_count)
register_player_num.modulate = Color.CYAN
# 清除现有的玩家条目(除了模板)
for child in player_ranking_list.get_children():
if child != player_info_template:
child.queue_free()
# 添加玩家条目
var players = data.get("players", [])
var players = players_list
for player_data in players:
add_player_entry(player_data)
print("排行榜数据已更新,显示", players.size(), "个玩家,注册总人数:", total_registered)
Toast.show("排行榜已刷新!显示 " + str(players.size()) + " 个玩家", Color.GREEN)
# 添加单个玩家条目
func add_player_entry(player_data):
@@ -65,17 +104,28 @@ func add_player_entry(player_data):
var player_last_login_time = player_entry.get_node("HBox2/LastLoginTime")
var player_avatar = player_entry.get_node("HBox/PlayerAvatar")
var visit_button = player_entry.get_node("HBox/VisitButton")
var player_is_online_time = player_entry.get_node("HBox2/IsOnlineTime")
# 填充数据
var username = player_data.get("user_name", "未知")
var display_name = player_data.get("player_name", username)
player_name.text = display_name
player_level.text = "等级: " + str(player_data.get("level", 0))
player_money.text = "金币: " + str(player_data.get("money", 0))
player_seed_num.text = "种子: " + str(player_data.get("seed_count", 0))
#都是整数,不要乱用浮点数
player_level.text = "等级: " + str(int(player_data.get("level", 0)))
player_money.text = "金币: " + str(int(player_data.get("money", 0)))
player_seed_num.text = "种子: " + str(int(player_data.get("seed_count", 0)))
player_online_time.text = "游玩时间: " + player_data.get("total_login_time", "0时0分0秒")
player_last_login_time.text = "最后登录: " + player_data.get("last_login_time", "未知")
# 设置在线状态显示
var is_online = player_data.get("is_online", false)
if is_online:
player_is_online_time.text = "🟢 在线"
player_is_online_time.modulate = Color.GREEN
else:
player_is_online_time.text = "🔴 离线"
player_is_online_time.modulate = Color.GRAY
# 尝试加载玩家头像(使用用户名/QQ号加载头像而不是显示名
if username.is_valid_int():
player_avatar.load_from_url("http://q1.qlogo.cn/g?b=qq&nk=" + username + "&s=100")
@@ -87,19 +137,55 @@ func add_player_entry(player_data):
func _on_visit_player_pressed(username):
print("访问玩家:", username)
# 检查网络连接
if not network_manager or not network_manager.is_connected_to_server():
Toast.show("未连接服务器,无法访问玩家", Color.RED)
return
# 检查是否尝试访问自己
if main_game and main_game.user_name == username:
Toast.show("不能访问自己的农场", Color.ORANGE)
return
# 发送访问玩家请求
if network_manager and network_manager.has_method("sendVisitPlayer"):
var success = network_manager.sendVisitPlayer(username)
if success:
Toast.show("正在访问 " + username + " 的农场...", Color.YELLOW)
print("已发送访问玩家请求:", username)
else:
Toast.show("发送访问请求失败", Color.RED)
print("发送访问玩家请求失败,网络未连接")
else:
Toast.show("网络管理器不可用", Color.RED)
print("网络管理器不可用")
# 刷新按钮点击
func _on_refresh_button_pressed():
# 检查网络连接
if not network_manager or not network_manager.is_connected_to_server():
register_player_num.text = "未连接服务器,无法刷新"
register_player_num.modulate = Color.RED
Toast.show("未连接服务器,无法刷新排行榜", Color.RED)
return
# 显示加载状态
register_player_num.text = "正在刷新注册人数..."
register_player_num.modulate = Color.YELLOW
refresh_button.disabled = true
refresh_button.text = "刷新中..."
# 请求排行榜数据
request_player_rankings()
# 5秒后重新启用按钮防止卡住
await get_tree().create_timer(5.0).timeout
if refresh_button.disabled:
refresh_button.disabled = false
refresh_button.text = "刷新"
if register_player_num.text == "正在刷新注册人数...":
register_player_num.text = "刷新超时,请重试"
register_player_num.modulate = Color.RED
# 退出按钮点击
func _on_quit_button_pressed():