大更新,太多了,具体进游戏查看详细更新内容
反正很多
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
extends Panel
|
||||
|
||||
#用户登录账号,用QQ号代替
|
||||
@onready var username_input = $username_input
|
||||
#用户登录密码
|
||||
@onready var password_input = $password_input
|
||||
#登录按钮
|
||||
@onready var login_button = $login_button
|
||||
|
||||
|
||||
func _ready():
|
||||
|
||||
pass
|
||||
|
||||
func _process(delta):
|
||||
pass
|
||||
|
||||
func _on_login_button_pressed():
|
||||
pass
|
||||
22
GUI/SMY_ProgressBar.gd
Normal file
22
GUI/SMY_ProgressBar.gd
Normal file
@@ -0,0 +1,22 @@
|
||||
extends ProgressBar
|
||||
|
||||
var target_value: float = 0.0
|
||||
var animation_speed: float = 2.0
|
||||
|
||||
func _ready():
|
||||
# 初始化进度条的颜色
|
||||
modulate = Color(0.6, 0, 0.0) # 从红色到绿色的渐变
|
||||
|
||||
func _process(delta):
|
||||
update_progress_visuals()
|
||||
|
||||
func set_target_value(new_value: float):
|
||||
value = new_value
|
||||
|
||||
func update_progress_visuals():
|
||||
# 改变进度条的颜色
|
||||
var fill_ratio = value / max_value
|
||||
modulate = Color(0.6 - fill_ratio, fill_ratio, 0.0) # 从红色到绿色的渐变
|
||||
#modulate = Color(1.0 - fill_ratio, fill_ratio, 0.0) # 从红色到绿色的渐变
|
||||
#modulate = Color(0.0, 1.0 - fill_ratio, fill_ratio) # 从蓝色到绿色的渐变
|
||||
#modulate = Color(0.0, 1.0 - fill_ratio, fill_ratio * 0.75) # 从绿色到淡蓝色的渐变
|
||||
1
GUI/SMY_ProgressBar.gd.uid
Normal file
1
GUI/SMY_ProgressBar.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://xh5tr5co5kfu
|
||||
494
GUI/crop_store_panel.gd
Normal file
494
GUI/crop_store_panel.gd
Normal file
@@ -0,0 +1,494 @@
|
||||
extends Panel
|
||||
|
||||
#种子商店面板
|
||||
#种子商店格子
|
||||
@onready var crop_grid_container : GridContainer = $ScrollContainer/Crop_Grid
|
||||
@onready var quit_button : Button = $QuitButton
|
||||
|
||||
#各种排序过滤按钮
|
||||
@onready var sort_all_button : Button = $SortContainer/Sort_All#全部
|
||||
@onready var sort_common_button : Button = $SortContainer/Sort_Common#普通
|
||||
@onready var sort_superior_button : Button = $SortContainer/Sort_Superior#优良
|
||||
@onready var sort_rare_button : Button = $SortContainer/Sort_Rare#稀有
|
||||
@onready var sort_epic_button : Button = $SortContainer/Sort_Epic#史诗
|
||||
@onready var sort_legendary_button : Button = $SortContainer/Sort_Legendary#传奇
|
||||
@onready var sort_price_button : Button = $SortContainer/Sort_Price#价格
|
||||
@onready var sort_growtime_button : Button = $SortContainer/Sort_GrowTime#生长时间
|
||||
@onready var sort_profit_button : Button = $SortContainer/Sort_Profit#收益
|
||||
@onready var sort_level_button : Button = $SortContainer/Sort_Level#等级
|
||||
|
||||
#预添加常用的面板
|
||||
@onready var main_game = get_node("/root/main")
|
||||
@onready var land_panel = get_node("/root/main/UI/LandPanel")
|
||||
@onready var crop_store_panel = get_node("/root/main/UI/PlayerBagPanel")
|
||||
@onready var player_ranking_panel = get_node("/root/main/UI/PlayerRankingPanel")
|
||||
@onready var player_bag_panel = get_node("/root/main/UI/PlayerBagPanel")
|
||||
@onready var network_manager = get_node("/root/main/UI/TCPNetworkManager")
|
||||
|
||||
# 作物图片缓存(复用主游戏的缓存系统)
|
||||
var crop_textures_cache : Dictionary = {}
|
||||
var crop_frame_counts : Dictionary = {}
|
||||
|
||||
# 当前过滤和排序设置
|
||||
var current_filter_quality = ""
|
||||
var current_sort_key = ""
|
||||
var current_sort_ascending = true
|
||||
|
||||
# 准备函数
|
||||
func _ready():
|
||||
# 连接按钮信号
|
||||
_connect_buttons()
|
||||
# 隐藏面板(初始默认隐藏)
|
||||
self.hide()
|
||||
|
||||
# 连接所有按钮信号
|
||||
func _connect_buttons():
|
||||
# 关闭按钮
|
||||
quit_button.pressed.connect(self._on_quit_button_pressed)
|
||||
|
||||
# 过滤按钮
|
||||
sort_all_button.pressed.connect(func(): _filter_by_quality(""))
|
||||
sort_common_button.pressed.connect(func(): _filter_by_quality("普通"))
|
||||
sort_superior_button.pressed.connect(func(): _filter_by_quality("优良"))
|
||||
sort_rare_button.pressed.connect(func(): _filter_by_quality("稀有"))
|
||||
sort_epic_button.pressed.connect(func(): _filter_by_quality("史诗"))
|
||||
sort_legendary_button.pressed.connect(func(): _filter_by_quality("传奇"))
|
||||
|
||||
# 排序按钮
|
||||
sort_price_button.pressed.connect(func(): _sort_by("花费"))
|
||||
sort_growtime_button.pressed.connect(func(): _sort_by("生长时间"))
|
||||
sort_profit_button.pressed.connect(func(): _sort_by("收益"))
|
||||
sort_level_button.pressed.connect(func(): _sort_by("等级"))
|
||||
|
||||
# 初始化商店
|
||||
func init_store():
|
||||
print("初始化商店...")
|
||||
|
||||
# 清空已有的作物按钮
|
||||
for child in crop_grid_container.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# 遍历可种植的作物数据并添加到商店
|
||||
print("初始化商店,显示所有作物...")
|
||||
for crop_name in main_game.can_planted_crop:
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 只显示当前等级可以种植的作物
|
||||
if crop["等级"] <= main_game.level:
|
||||
var store_btn = _create_store_button(crop_name, crop["品质"])
|
||||
crop_grid_container.add_child(store_btn)
|
||||
#print("添加商店按钮: " + crop_name)
|
||||
|
||||
print("商店初始化完成,共添加按钮: " + str(crop_grid_container.get_child_count()) + "个")
|
||||
|
||||
# 更新金钱显示
|
||||
_update_money_display()
|
||||
|
||||
# 创建商店按钮
|
||||
func _create_store_button(crop_name: String, crop_quality: String) -> Button:
|
||||
# 根据品质选择相应的按钮
|
||||
var button = null
|
||||
match crop_quality:
|
||||
"普通":
|
||||
button = main_game.green_bar.duplicate()
|
||||
"优良":
|
||||
button = main_game.orange_bar.duplicate()
|
||||
"稀有":
|
||||
button = main_game.white_blue_bar.duplicate()
|
||||
"史诗":
|
||||
button = main_game.pink_bar.duplicate()
|
||||
"传奇":
|
||||
button = main_game.black_blue_bar.duplicate()
|
||||
_: # 默认情况
|
||||
button = main_game.green_bar.duplicate()
|
||||
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 确保按钮可见并可点击
|
||||
button.visible = true
|
||||
button.disabled = false
|
||||
button.focus_mode = Control.FOCUS_ALL
|
||||
|
||||
# 设置按钮文本,显示价格
|
||||
button.text = str(crop_quality + "-" + crop_name + "\n价格: ¥" + str(crop["花费"]))
|
||||
|
||||
# 将成熟时间从秒转换为天时分秒格式
|
||||
var total_seconds = int(crop["生长时间"])
|
||||
|
||||
# 定义时间单位换算
|
||||
var SECONDS_PER_MINUTE = 60
|
||||
var SECONDS_PER_HOUR = 3600
|
||||
var SECONDS_PER_DAY = 86400
|
||||
|
||||
# 计算各时间单位
|
||||
var days = total_seconds / SECONDS_PER_DAY
|
||||
total_seconds %= SECONDS_PER_DAY
|
||||
|
||||
var hours = total_seconds / SECONDS_PER_HOUR
|
||||
total_seconds %= SECONDS_PER_HOUR
|
||||
|
||||
var minutes = total_seconds / SECONDS_PER_MINUTE
|
||||
var seconds = total_seconds % SECONDS_PER_MINUTE
|
||||
|
||||
# 构建时间字符串(只显示有值的单位)
|
||||
var time_str = ""
|
||||
if days > 0:
|
||||
time_str += str(days) + "天"
|
||||
if hours > 0:
|
||||
time_str += str(hours) + "小时"
|
||||
if minutes > 0:
|
||||
time_str += str(minutes) + "分钟"
|
||||
if seconds > 0:
|
||||
time_str += str(seconds) + "秒"
|
||||
|
||||
button.tooltip_text = str(
|
||||
"作物: " + crop_name + "\n" +
|
||||
"品质: " + crop_quality + "\n" +
|
||||
"价格: " + str(crop["花费"]) + "元\n" +
|
||||
"成熟时间: " + time_str + "\n" +
|
||||
"收获收益: " + str(crop["收益"]) + "元\n" +
|
||||
"需求等级: " + str(crop["等级"]) + "\n" +
|
||||
"耐候性: " + str(crop["耐候性"]) + "\n" +
|
||||
"经验: " + str(crop["经验"]) + "点\n" +
|
||||
"描述: " + str(crop["描述"])
|
||||
)
|
||||
|
||||
# 添加按钮事件
|
||||
button.pressed.connect(func(): _on_store_buy_pressed(crop_name))
|
||||
|
||||
# 更新按钮的作物图片
|
||||
_update_button_crop_image(button, crop_name)
|
||||
|
||||
# 如果按钮有标题标签,设置标题
|
||||
if button.has_node("Title"):
|
||||
match crop_quality:
|
||||
"普通":
|
||||
button.get_node("Title").modulate = Color.HONEYDEW#白色
|
||||
"优良":
|
||||
button.get_node("Title").modulate =Color.DODGER_BLUE#深蓝色
|
||||
"稀有":
|
||||
button.get_node("Title").modulate =Color.HOT_PINK#品红色
|
||||
"史诗":
|
||||
button.get_node("Title").modulate =Color.YELLOW#黄色
|
||||
"传奇":
|
||||
button.get_node("Title").modulate =Color.ORANGE_RED#红色
|
||||
|
||||
return button
|
||||
|
||||
# 购买种子事件处理
|
||||
func _on_store_buy_pressed(crop_name: String):
|
||||
print("购买种子: " + crop_name)
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 检查等级要求
|
||||
if main_game.level < crop["等级"]:
|
||||
Toast.show("等级不足,无法购买此种子", Color.RED)
|
||||
return
|
||||
|
||||
# 检查金钱是否足够
|
||||
if main_game.money < crop["花费"]:
|
||||
Toast.show("金钱不足,无法购买种子", Color.RED)
|
||||
return
|
||||
|
||||
# 发送购买请求到服务器
|
||||
if network_manager and network_manager.sendBuySeed(crop_name):
|
||||
# 购买请求已发送,等待服务器响应
|
||||
Toast.show("正在购买种子...", Color.YELLOW, 2.0, 1.0)
|
||||
|
||||
# 将种子添加到背包
|
||||
var found = false
|
||||
for seed_item in main_game.player_bag:
|
||||
if seed_item["name"] == crop_name:
|
||||
seed_item["count"] += 1
|
||||
found = true
|
||||
break
|
||||
|
||||
if not found:
|
||||
main_game.player_bag.append({
|
||||
"name": crop_name,
|
||||
"quality": crop["品质"],
|
||||
"count": 1
|
||||
})
|
||||
|
||||
# 显示购买成功消息
|
||||
Toast.show("购买了" + crop["品质"] + "-" + crop_name + "种子", Color.GREEN)
|
||||
|
||||
# 更新背包UI
|
||||
crop_store_panel.update_player_bag_ui()
|
||||
|
||||
# 更新金钱显示
|
||||
_update_money_display()
|
||||
|
||||
# 关闭面板
|
||||
func _on_quit_button_pressed():
|
||||
print("关闭商店面板")
|
||||
self.hide()
|
||||
|
||||
# 按品质过滤作物
|
||||
func _filter_by_quality(quality: String):
|
||||
current_filter_quality = quality
|
||||
print("过滤作物,品质: " + (quality if quality != "" else "全部"))
|
||||
_apply_filter_and_sort()
|
||||
|
||||
# 按指定键排序
|
||||
func _sort_by(sort_key: String):
|
||||
# 切换排序方向或设置新排序键
|
||||
if current_sort_key == sort_key:
|
||||
current_sort_ascending = !current_sort_ascending
|
||||
else:
|
||||
current_sort_key = sort_key
|
||||
current_sort_ascending = true
|
||||
|
||||
print("排序作物,键: " + sort_key + ",升序: " + str(current_sort_ascending))
|
||||
_apply_filter_and_sort()
|
||||
|
||||
# 应用过滤和排序
|
||||
func _apply_filter_and_sort():
|
||||
# 清空现有按钮
|
||||
for child in crop_grid_container.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# 收集符合条件的作物
|
||||
var filtered_crops = []
|
||||
for crop_name in main_game.can_planted_crop:
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 检查等级和品质过滤
|
||||
if crop["等级"] > main_game.level:
|
||||
continue
|
||||
|
||||
if current_filter_quality != "" and crop["品质"] != current_filter_quality:
|
||||
continue
|
||||
|
||||
# 添加到过滤后的列表
|
||||
filtered_crops.append({
|
||||
"name": crop_name,
|
||||
"data": crop
|
||||
})
|
||||
|
||||
# 如果有排序条件,进行排序
|
||||
if current_sort_key != "":
|
||||
filtered_crops.sort_custom(Callable(self, "_sort_crop_items"))
|
||||
|
||||
# 添加所有过滤和排序后的作物
|
||||
for crop in filtered_crops:
|
||||
var store_btn = _create_store_button(crop["name"], crop["data"]["品质"])
|
||||
crop_grid_container.add_child(store_btn)
|
||||
|
||||
# 更新金钱显示
|
||||
_update_money_display()
|
||||
|
||||
# 自定义排序函数
|
||||
func _sort_crop_items(a, b):
|
||||
if current_sort_ascending:
|
||||
return a["data"][current_sort_key] < b["data"][current_sort_key]
|
||||
else:
|
||||
return a["data"][current_sort_key] > b["data"][current_sort_key]
|
||||
|
||||
# 更新金钱显示
|
||||
func _update_money_display():
|
||||
var money_label = get_node_or_null("MoneyLabel")
|
||||
if money_label == null:
|
||||
# 创建金钱显示标签
|
||||
money_label = Label.new()
|
||||
money_label.name = "MoneyLabel"
|
||||
money_label.position = Vector2(10, 10)
|
||||
money_label.size = Vector2(300, 45)
|
||||
|
||||
# 设置标签样式
|
||||
money_label.add_theme_color_override("font_color", Color(1, 0.647, 0, 1)) # 橙色
|
||||
money_label.add_theme_font_size_override("font_size", 24)
|
||||
|
||||
add_child(money_label)
|
||||
|
||||
# 更新金钱显示
|
||||
money_label.text = "当前金钱:" + str(main_game.money) + " 元"
|
||||
print("更新商店金钱显示:" + str(main_game.money))
|
||||
|
||||
# 刷新商店内容,可以在金钱变化或等级提升后调用
|
||||
func refresh_store():
|
||||
# 清空并重新创建商店按钮
|
||||
init_store()
|
||||
|
||||
# 尝试创建过滤按钮(如果商店面板中没有这些按钮)
|
||||
_create_filter_buttons_if_needed()
|
||||
|
||||
# 如果需要,动态创建过滤按钮
|
||||
func _create_filter_buttons_if_needed():
|
||||
# 检查是否已存在过滤器容器
|
||||
var filter_container = get_node_or_null("FilterContainer")
|
||||
if filter_container == null:
|
||||
# 创建过滤器容器
|
||||
filter_container = HBoxContainer.new()
|
||||
filter_container.name = "FilterContainer"
|
||||
|
||||
# 设置容器位置和大小
|
||||
filter_container.position = Vector2(320, 10)
|
||||
filter_container.size = Vector2(770, 45)
|
||||
|
||||
add_child(filter_container)
|
||||
|
||||
# 添加过滤按钮
|
||||
_add_filter_button(filter_container, "全部", func(): _filter_by_quality(""))
|
||||
_add_filter_button(filter_container, "普通", func(): _filter_by_quality("普通"))
|
||||
_add_filter_button(filter_container, "优良", func(): _filter_by_quality("优良"))
|
||||
_add_filter_button(filter_container, "稀有", func(): _filter_by_quality("稀有"))
|
||||
_add_filter_button(filter_container, "史诗", func(): _filter_by_quality("史诗"))
|
||||
_add_filter_button(filter_container, "传奇", func(): _filter_by_quality("传奇"))
|
||||
|
||||
# 检查是否已存在排序容器
|
||||
var sort_container = get_node_or_null("SortContainer")
|
||||
if sort_container == null:
|
||||
# 创建排序容器
|
||||
sort_container = HBoxContainer.new()
|
||||
sort_container.name = "SortContainer"
|
||||
|
||||
# 设置容器位置和大小
|
||||
sort_container.position = Vector2(320, 55)
|
||||
sort_container.size = Vector2(770, 30)
|
||||
|
||||
add_child(sort_container)
|
||||
|
||||
# 添加排序按钮
|
||||
_add_filter_button(sort_container, "按价格", func(): _sort_by("花费"))
|
||||
_add_filter_button(sort_container, "按生长时间", func(): _sort_by("生长时间"))
|
||||
_add_filter_button(sort_container, "按收益", func(): _sort_by("收益"))
|
||||
_add_filter_button(sort_container, "按等级", func(): _sort_by("等级"))
|
||||
|
||||
# 添加过滤按钮
|
||||
func _add_filter_button(container, text, callback):
|
||||
var button = Button.new()
|
||||
button.text = text
|
||||
button.custom_minimum_size = Vector2(100, 0)
|
||||
button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
container.add_child(button)
|
||||
button.pressed.connect(callback)
|
||||
|
||||
# 获取作物的最后一帧图片(用于商店显示)
|
||||
func _get_crop_final_texture(crop_name: String) -> Texture2D:
|
||||
"""
|
||||
获取作物的最后一帧图片,用于商店和背包显示
|
||||
如果作物图片不存在,使用默认图片的最后一帧
|
||||
"""
|
||||
# 先尝试从主游戏的缓存中获取
|
||||
if main_game and main_game.crop_textures_cache.has(crop_name):
|
||||
var textures = main_game.crop_textures_cache[crop_name]
|
||||
if textures.size() > 0:
|
||||
return textures[textures.size() - 1] # 返回最后一帧
|
||||
|
||||
# 如果主游戏缓存中没有,自己加载
|
||||
var textures = _load_crop_textures(crop_name)
|
||||
if textures.size() > 0:
|
||||
return textures[textures.size() - 1] # 返回最后一帧
|
||||
|
||||
return null
|
||||
|
||||
# 加载作物图片序列帧(复用主游戏的逻辑)
|
||||
func _load_crop_textures(crop_name: String) -> Array:
|
||||
"""
|
||||
加载指定作物的所有序列帧图片
|
||||
"""
|
||||
if crop_textures_cache.has(crop_name):
|
||||
return crop_textures_cache[crop_name]
|
||||
|
||||
var textures = []
|
||||
var crop_path = "res://assets/作物/" + crop_name + "/"
|
||||
var default_path = "res://assets/作物/默认/"
|
||||
|
||||
# 检查作物文件夹是否存在
|
||||
if DirAccess.dir_exists_absolute(crop_path):
|
||||
# 尝试加载作物的序列帧(从0开始)
|
||||
var frame_index = 0
|
||||
while true:
|
||||
var texture_path = crop_path + str(frame_index) + ".png"
|
||||
if ResourceLoader.exists(texture_path):
|
||||
var texture = load(texture_path)
|
||||
if texture:
|
||||
textures.append(texture)
|
||||
frame_index += 1
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
if textures.size() > 0:
|
||||
print("商店加载作物 ", crop_name, " 的 ", textures.size(), " 帧图片")
|
||||
else:
|
||||
print("商店:作物 ", crop_name, " 文件夹存在但没有找到有效图片,使用默认图片")
|
||||
textures = _load_default_textures()
|
||||
else:
|
||||
print("商店:作物 ", crop_name, " 的文件夹不存在,使用默认图片")
|
||||
textures = _load_default_textures()
|
||||
|
||||
# 缓存结果
|
||||
crop_textures_cache[crop_name] = textures
|
||||
crop_frame_counts[crop_name] = textures.size()
|
||||
|
||||
return textures
|
||||
|
||||
# 加载默认图片
|
||||
func _load_default_textures() -> Array:
|
||||
"""
|
||||
加载默认作物图片
|
||||
"""
|
||||
if crop_textures_cache.has("默认"):
|
||||
return crop_textures_cache["默认"]
|
||||
|
||||
var textures = []
|
||||
var default_path = "res://assets/作物/默认/"
|
||||
|
||||
# 尝试加载默认图片序列帧
|
||||
var frame_index = 0
|
||||
while true:
|
||||
var texture_path = default_path + str(frame_index) + ".png"
|
||||
if ResourceLoader.exists(texture_path):
|
||||
var texture = load(texture_path)
|
||||
if texture:
|
||||
textures.append(texture)
|
||||
frame_index += 1
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
# 如果没有找到序列帧,尝试加载单个默认图片
|
||||
if textures.size() == 0:
|
||||
var single_texture_path = default_path + "0.png"
|
||||
if ResourceLoader.exists(single_texture_path):
|
||||
var texture = load(single_texture_path)
|
||||
if texture:
|
||||
textures.append(texture)
|
||||
|
||||
# 缓存默认图片
|
||||
crop_textures_cache["默认"] = textures
|
||||
crop_frame_counts["默认"] = textures.size()
|
||||
|
||||
print("商店加载了 ", textures.size(), " 个默认作物图片")
|
||||
return textures
|
||||
|
||||
# 更新按钮的作物图片
|
||||
func _update_button_crop_image(button: Button, crop_name: String):
|
||||
"""
|
||||
更新按钮中的作物图片
|
||||
"""
|
||||
# 检查按钮是否有CropImage节点
|
||||
var crop_image = button.get_node_or_null("CropImage")
|
||||
if not crop_image:
|
||||
print("商店按钮没有找到CropImage节点:", button.name)
|
||||
return
|
||||
|
||||
# 获取作物的最后一帧图片
|
||||
var texture = _get_crop_final_texture(crop_name)
|
||||
|
||||
if texture:
|
||||
# CropImage是Sprite2D,直接设置texture属性
|
||||
crop_image.texture = texture
|
||||
crop_image.visible = true
|
||||
print("商店更新作物图片:", crop_name)
|
||||
else:
|
||||
crop_image.visible = false
|
||||
print("商店无法获取作物图片:", crop_name)
|
||||
|
||||
# 兼容MainGame.gd中的调用,转发到_on_store_buy_pressed
|
||||
func _on_crop_selected(crop_name: String):
|
||||
_on_store_buy_pressed(crop_name)
|
||||
1
GUI/crop_store_panel.gd.uid
Normal file
1
GUI/crop_store_panel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://mtfp0ct42nrx
|
||||
126
GUI/land_panel.gd
Normal file
126
GUI/land_panel.gd
Normal file
@@ -0,0 +1,126 @@
|
||||
extends Panel
|
||||
|
||||
#获取玩家要操作的地块序号
|
||||
var selected_lot_index = 0
|
||||
|
||||
#预添加常用的面板
|
||||
@onready var main_game = get_node("/root/main")
|
||||
@onready var land_panel = get_node("/root/main/UI/LandPanel")
|
||||
@onready var crop_store_panel = get_node("/root/main/UI/PlayerBagPanel")
|
||||
@onready var player_ranking_panel = get_node("/root/main/UI/PlayerRankingPanel")
|
||||
@onready var player_bag_panel = get_node("/root/main/UI/PlayerBagPanel")
|
||||
@onready var network_manager = get_node("/root/main/UI/TCPNetworkManager")
|
||||
|
||||
@onready var quit_button :Button = $Quit_Button
|
||||
@onready var dig_button: Button = $Grid/Dig_Button
|
||||
@onready var water_button: Button = $Grid/Water_Button
|
||||
@onready var fertilize_button: Button = $Grid/Fertilize_Button
|
||||
@onready var upgrade_button: Button = $Grid/Upgrade_Button
|
||||
@onready var plant_button: Button = $Grid/Plant_Button
|
||||
@onready var remove_button: Button = $Grid/Remove_Button
|
||||
@onready var harvest_button: Button = $Grid/Harvest_Button
|
||||
|
||||
|
||||
func _ready():
|
||||
self.hide()
|
||||
quit_button.pressed.connect(self._on_quit_button_pressed)
|
||||
dig_button.pressed.connect(self._on_dig_button_pressed)
|
||||
water_button.pressed.connect(self._on_water_button_pressed)
|
||||
fertilize_button.pressed.connect(self._on_fertilize_button_pressed)
|
||||
upgrade_button.pressed.connect(self._on_upgrade_button_pressed)
|
||||
plant_button.pressed.connect(self._on_plant_button_pressed)
|
||||
remove_button.pressed.connect(self._on_remove_button_pressed)
|
||||
harvest_button.pressed.connect(self._on_harvest_button_pressed)
|
||||
dig_button.text = "开垦"+"\n花费:"+str(main_game.dig_money)
|
||||
|
||||
#开垦
|
||||
func _on_dig_button_pressed():
|
||||
# 检查是否处于访问模式
|
||||
if main_game.is_visiting_mode:
|
||||
Toast.show("访问模式下无法开垦土地", Color.ORANGE, 2.0, 1.0)
|
||||
self.hide()
|
||||
return
|
||||
|
||||
dig_button.text = "开垦"+"\n花费:"+str(main_game.dig_money)
|
||||
|
||||
if network_manager and network_manager.is_connected_to_server():
|
||||
# 使用服务器API来开垦土地
|
||||
if network_manager.sendDigGround(selected_lot_index):
|
||||
self.hide()
|
||||
#浇水
|
||||
func _on_water_button_pressed():
|
||||
# 检查是否处于访问模式
|
||||
if main_game.is_visiting_mode:
|
||||
Toast.show("访问模式下无法浇水", Color.ORANGE, 2.0, 1.0)
|
||||
self.hide()
|
||||
return
|
||||
|
||||
self.hide()
|
||||
pass
|
||||
#施肥
|
||||
func _on_fertilize_button_pressed():
|
||||
# 检查是否处于访问模式
|
||||
if main_game.is_visiting_mode:
|
||||
Toast.show("访问模式下无法施肥", Color.ORANGE, 2.0, 1.0)
|
||||
self.hide()
|
||||
return
|
||||
|
||||
self.hide()
|
||||
pass
|
||||
#升级
|
||||
func _on_upgrade_button_pressed():
|
||||
# 检查是否处于访问模式
|
||||
if main_game.is_visiting_mode:
|
||||
Toast.show("访问模式下无法升级", Color.ORANGE, 2.0, 1.0)
|
||||
self.hide()
|
||||
return
|
||||
|
||||
self.hide()
|
||||
pass
|
||||
#种植
|
||||
func _on_plant_button_pressed():
|
||||
# 检查是否处于访问模式
|
||||
if main_game.is_visiting_mode:
|
||||
Toast.show("访问模式下无法种植", Color.ORANGE, 2.0, 1.0)
|
||||
self.hide()
|
||||
return
|
||||
|
||||
player_bag_panel.show()
|
||||
self.hide()
|
||||
pass
|
||||
#铲除
|
||||
func _on_remove_button_pressed():
|
||||
# 检查是否处于访问模式
|
||||
if main_game.is_visiting_mode:
|
||||
Toast.show("访问模式下无法铲除作物", Color.ORANGE, 2.0, 1.0)
|
||||
self.hide()
|
||||
return
|
||||
|
||||
main_game.root_out_crop(selected_lot_index)
|
||||
self.hide()
|
||||
pass
|
||||
#收获
|
||||
func _on_harvest_button_pressed():
|
||||
# 检查是否处于访问模式
|
||||
if main_game.is_visiting_mode:
|
||||
Toast.show("访问模式下无法收获作物", Color.ORANGE, 2.0, 1.0)
|
||||
self.hide()
|
||||
return
|
||||
|
||||
main_game._harvest_crop(selected_lot_index)
|
||||
self.hide()
|
||||
pass
|
||||
#退出
|
||||
func _on_quit_button_pressed():
|
||||
self.hide()
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1
GUI/land_panel.gd.uid
Normal file
1
GUI/land_panel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bljtkxil64h14
|
||||
87
GUI/login.gd
87
GUI/login.gd
@@ -1,87 +0,0 @@
|
||||
extends Node
|
||||
|
||||
var http_request: HTTPRequest
|
||||
var farm_lots = []
|
||||
|
||||
@onready var harvest = $harvest
|
||||
@onready var label1 = $Label
|
||||
@onready var username_input = $Panel/username_input
|
||||
@onready var password_input = $Panel/password_input
|
||||
@onready var login_button = $Panel/login_button
|
||||
@onready var panel = $Panel
|
||||
@onready var item_list = $item_list #ItemList
|
||||
|
||||
func _ready():
|
||||
# 创建 HTTPRequest 节点
|
||||
http_request = HTTPRequest.new()
|
||||
add_child(http_request)
|
||||
# 连接信号
|
||||
http_request.connect("request_completed", Callable(self, "_on_request_completed"))
|
||||
# 连接登录按钮点击事件
|
||||
login_button.connect("pressed", Callable(self, "_on_login_button_pressed"))
|
||||
|
||||
# 登录按钮按下事件
|
||||
func _on_login_button_pressed():
|
||||
# 隐藏面板(只有在输入后才进行隐藏)
|
||||
panel.hide()
|
||||
|
||||
# 获取用户名和密码输入
|
||||
var username = username_input.text # 直接获取输入
|
||||
var password = password_input.text # 直接获取输入
|
||||
|
||||
# 打印调试信息
|
||||
print("Username entered: ", username)
|
||||
print("Password entered: ", password)
|
||||
|
||||
# 检查用户名和密码是否为空
|
||||
if username == "" or password == "":
|
||||
print("用户名和密码不能为空")
|
||||
panel.show() # 如果输入为空,显示面板
|
||||
return
|
||||
|
||||
# 构建登录请求的 URL 和参数
|
||||
var url = "https://api.shumengya.top/smyfarm/login.php"
|
||||
var body = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
|
||||
# 发送 POST 请求进行登录
|
||||
var err = http_request.request(url, [], HTTPClient.METHOD_POST, JSON.stringify(body))
|
||||
if err != OK:
|
||||
print("Error making HTTP POST request: ", err)
|
||||
|
||||
# 请求完成后的回调函数
|
||||
func _on_request_completed(result, response_code, headers, body):
|
||||
if response_code == 200:
|
||||
var json = JSON.new()
|
||||
var parse_result = json.parse(body.get_string_from_utf8())
|
||||
|
||||
if parse_result != OK:
|
||||
print("Error parsing JSON: ", json.get_error_message())
|
||||
return
|
||||
|
||||
var json_data = json.data
|
||||
|
||||
if json_data.has("error"):
|
||||
print("Error: " + str(json_data["error"]))
|
||||
panel.show() # 如果登录失败,显示面板,允许重新输入
|
||||
elif json_data.has("message"):
|
||||
print(json_data["message"])
|
||||
|
||||
# 处理登录成功
|
||||
if json_data.has("data"):
|
||||
var player_data = json_data["data"]
|
||||
print("欢迎, " + player_data["username"])
|
||||
|
||||
# 加载玩家数据,进入游戏逻辑
|
||||
_load_player_data(player_data)
|
||||
else:
|
||||
print("HTTP Request failed with response code: " + str(response_code))
|
||||
panel.show() # 请求失败,重新显示面板
|
||||
|
||||
# 加载玩家数据
|
||||
func _load_player_data(player_data):
|
||||
# 根据返回的 player_data 初始化玩家的农场状态等
|
||||
pass
|
||||
|
||||
433
GUI/login_panel.gd
Normal file
433
GUI/login_panel.gd
Normal file
@@ -0,0 +1,433 @@
|
||||
#玩家登录注册面板
|
||||
extends PanelContainer
|
||||
|
||||
#玩家登录账号,用QQ号代替
|
||||
@onready var username_input : LineEdit = $VBox/UserName/username_input
|
||||
#用户登录密码
|
||||
@onready var password_input : LineEdit = $VBox/Password1/password_input
|
||||
#登录按钮
|
||||
@onready var login_button : Button = $VBox/LoginRegister/login_button
|
||||
|
||||
#下面是注册相关的
|
||||
#注册按钮
|
||||
@onready var register_button : Button = $VBox/LoginRegister/register_button
|
||||
#注册账号时二次确认密码
|
||||
@onready var password_input_2 : LineEdit = $VBox/Password2/password_input2
|
||||
#农场名称
|
||||
@onready var farmname_input : LineEdit = $VBox/FarmName/farmname_input
|
||||
#玩家昵称
|
||||
@onready var playername_input :LineEdit = $VBox/PlayerName/playername_input
|
||||
#邮箱验证码
|
||||
@onready var verificationcode_input :LineEdit = $VBox/VerificationCode/verificationcode_input
|
||||
#发送验证码按钮
|
||||
@onready var send_button :Button = $VBox/VerificationCode/SendButton
|
||||
#状态提示标签
|
||||
@onready var status_label : Label = $VBox/status_label
|
||||
|
||||
# 记住密码选项(如果UI中有CheckBox的话)
|
||||
var remember_password : bool = true # 默认记住密码
|
||||
|
||||
# 引用主场景和全局函数
|
||||
@onready var main_game = get_node("/root/main")
|
||||
@onready var land_panel = get_node("/root/main/UI/LandPanel")
|
||||
@onready var crop_store_panel = get_node("/root/main/UI/PlayerBagPanel")
|
||||
@onready var player_ranking_panel = get_node("/root/main/UI/PlayerRankingPanel")
|
||||
@onready var player_bag_panel = get_node("/root/main/UI/PlayerBagPanel")
|
||||
@onready var tcp_network_manager = get_node("/root/main/UI/TCPNetworkManager")
|
||||
|
||||
# 准备函数
|
||||
func _ready():
|
||||
|
||||
# 连接按钮信号
|
||||
login_button.pressed.connect(self._on_login_button_pressed)
|
||||
register_button.pressed.connect(self._on_register_button_pressed)
|
||||
send_button.pressed.connect(self._on_send_button_pressed)
|
||||
|
||||
# 加载保存的登录信息
|
||||
_load_login_info()
|
||||
|
||||
# 处理登录按钮点击
|
||||
func _on_login_button_pressed():
|
||||
var user_name = username_input.text.strip_edges() # 修剪前后的空格
|
||||
var user_password = password_input.text.strip_edges()
|
||||
var farmname = farmname_input.text.strip_edges()
|
||||
|
||||
if user_name == "" or user_password == "":
|
||||
status_label.text = "用户名或密码不能为空!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
# 检查网络连接状态
|
||||
if !tcp_network_manager.client.is_client_connected():
|
||||
status_label.text = "未连接到服务器,正在尝试连接..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
# 尝试自动连接到服务器
|
||||
tcp_network_manager._on_connection_button_pressed()
|
||||
await get_tree().create_timer(1.0).timeout
|
||||
|
||||
# 再次检查连接状态
|
||||
if !tcp_network_manager.client.is_client_connected():
|
||||
status_label.text = "连接服务器失败,请检查网络设置!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
# 禁用按钮,防止重复点击
|
||||
login_button.disabled = true
|
||||
|
||||
status_label.text = "正在登录,请稍候..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
|
||||
# 如果启用了记住密码,保存登录信息
|
||||
if remember_password:
|
||||
_save_login_info(user_name, user_password)
|
||||
|
||||
tcp_network_manager.sendLoginInfo(user_name, user_password)
|
||||
|
||||
# 更新主游戏数据
|
||||
main_game.user_name = user_name
|
||||
main_game.user_password = user_password
|
||||
main_game.farmname = farmname
|
||||
|
||||
# 5秒后重新启用按钮(如果没有收到响应)
|
||||
await get_tree().create_timer(5.0).timeout
|
||||
if login_button.disabled:
|
||||
login_button.disabled = false
|
||||
status_label.text = "登录超时,请重试!"
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
# 处理验证码发送按钮点击
|
||||
func _on_send_button_pressed():
|
||||
var user_name = username_input.text.strip_edges()
|
||||
|
||||
if user_name == "":
|
||||
status_label.text = "请输入QQ号以接收验证码!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
if !is_valid_qq_number(user_name):
|
||||
status_label.text = "请输入正确的QQ号码(5-12位数字)!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
# 检查网络连接状态
|
||||
if !tcp_network_manager.client.is_client_connected():
|
||||
status_label.text = "未连接到服务器,正在尝试连接..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
# 尝试自动连接到服务器
|
||||
tcp_network_manager._on_connection_button_pressed()
|
||||
await get_tree().create_timer(1.0).timeout
|
||||
|
||||
# 再次检查连接状态
|
||||
if !tcp_network_manager.client.is_client_connected():
|
||||
status_label.text = "连接服务器失败,请检查网络设置!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
# 禁用按钮,防止重复点击
|
||||
send_button.disabled = true
|
||||
|
||||
status_label.text = "正在发送验证码,请稍候..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
|
||||
# 发送验证码请求
|
||||
tcp_network_manager.sendVerificationCodeRequest(user_name)
|
||||
|
||||
# 60秒后重新启用按钮(或收到响应后提前启用)
|
||||
var timer = 60
|
||||
while timer > 0 and send_button.disabled:
|
||||
send_button.text = "重新发送(%d)" % timer
|
||||
await get_tree().create_timer(1.0).timeout
|
||||
timer -= 1
|
||||
|
||||
if send_button.disabled:
|
||||
send_button.disabled = false
|
||||
send_button.text = "发送验证码"
|
||||
|
||||
if status_label.text == "正在发送验证码,请稍候...":
|
||||
status_label.text = "验证码发送超时,请重试!"
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
# 处理注册按钮点击
|
||||
func _on_register_button_pressed():
|
||||
var user_name = username_input.text.strip_edges()
|
||||
var user_password = password_input.text.strip_edges()
|
||||
var user_password_2 = password_input_2.text.strip_edges()
|
||||
var farmname = farmname_input.text.strip_edges()
|
||||
var player_name = playername_input.text.strip_edges()
|
||||
var verification_code = verificationcode_input.text.strip_edges()
|
||||
|
||||
if user_name == "" or user_password == "":
|
||||
status_label.text = "用户名或密码不能为空!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
if farmname == "":
|
||||
status_label.text = "农场名称不能为空!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
if user_password != user_password_2:
|
||||
status_label.text = "两次输入的密码不一致!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
if !is_valid_qq_number(user_name):
|
||||
status_label.text = "请输入正确的QQ号码(5-12位数字)!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
if verification_code == "":
|
||||
status_label.text = "请输入验证码!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
# 检查网络连接状态
|
||||
if !tcp_network_manager.client.is_client_connected():
|
||||
status_label.text = "未连接到服务器,正在尝试连接..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
# 尝试自动连接到服务器
|
||||
tcp_network_manager._on_connection_button_pressed()
|
||||
await get_tree().create_timer(1.0).timeout
|
||||
|
||||
# 再次检查连接状态
|
||||
if !tcp_network_manager.client.is_client_connected():
|
||||
status_label.text = "连接服务器失败,请检查网络设置!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
# 禁用按钮,防止重复点击
|
||||
register_button.disabled = true
|
||||
|
||||
status_label.text = "正在注册,请稍候..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
|
||||
# 发送注册请求
|
||||
tcp_network_manager.sendRegisterInfo(user_name, user_password, farmname, player_name, verification_code)
|
||||
|
||||
# 更新主游戏数据
|
||||
main_game.user_name = user_name
|
||||
main_game.user_password = user_password
|
||||
main_game.farmname = farmname
|
||||
|
||||
# 5秒后重新启用按钮(如果没有收到响应)
|
||||
await get_tree().create_timer(5.0).timeout
|
||||
if register_button.disabled:
|
||||
register_button.disabled = false
|
||||
status_label.text = "注册超时,请重试!"
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
# 处理验证码发送响应
|
||||
func _on_verification_code_response(success: bool, message: String):
|
||||
if success:
|
||||
status_label.text = message
|
||||
status_label.modulate = Color.GREEN
|
||||
else:
|
||||
status_label.text = message
|
||||
status_label.modulate = Color.RED
|
||||
send_button.disabled = false
|
||||
send_button.text = "发送验证码"
|
||||
|
||||
# 处理验证码验证响应
|
||||
func _on_verify_code_response(success: bool, message: String):
|
||||
if success:
|
||||
status_label.text = message
|
||||
status_label.modulate = Color.GREEN
|
||||
else:
|
||||
status_label.text = message
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
# 验证QQ号是否有效
|
||||
func is_valid_qq_number(qq_number: String) -> bool:
|
||||
# QQ号的标准格式是5到12位的数字
|
||||
var qq_regex = RegEx.new()
|
||||
var pattern = r"^\d{5,12}$"
|
||||
|
||||
var error = qq_regex.compile(pattern)
|
||||
if error != OK:
|
||||
status_label.text = "QQ号验证失败部错误"
|
||||
status_label.modulate = Color.RED
|
||||
return false
|
||||
|
||||
return qq_regex.search(qq_number) != null
|
||||
|
||||
# 处理登录响应
|
||||
func _on_login_response_received(success: bool, message: String, user_data: Dictionary):
|
||||
# 启用按钮
|
||||
login_button.disabled = false
|
||||
|
||||
if success:
|
||||
status_label.text = "登录成功!正在加载游戏..."
|
||||
status_label.modulate = Color.GREEN
|
||||
|
||||
# 更新主游戏数据
|
||||
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.farmname = user_data.get("farm_name", "")
|
||||
farmname_input.text = user_data.get("farm_name", "")
|
||||
|
||||
# 加载玩家背包数据
|
||||
if user_data.has("player_bag"):
|
||||
main_game.player_bag = user_data.get("player_bag", [])
|
||||
else:
|
||||
main_game.player_bag = []
|
||||
|
||||
main_game.start_game = true
|
||||
self.hide()
|
||||
|
||||
# 确保在更新数据后调用主游戏的 UI 更新函数
|
||||
main_game._update_ui()
|
||||
main_game._refresh_farm_lots()
|
||||
player_bag_panel.update_player_bag_ui()
|
||||
else:
|
||||
status_label.text = "登录失败:" + message
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
# 如果登录失败且是密码错误,可以选择清除保存的信息
|
||||
if "密码" in message or "password" in message.to_lower():
|
||||
print("登录失败,可能是密码错误。如需清除保存的登录信息,请调用_clear_login_info()")
|
||||
|
||||
# 处理注册响应
|
||||
func _on_register_response_received(success: bool, message: String):
|
||||
# 启用按钮
|
||||
register_button.disabled = false
|
||||
|
||||
if success:
|
||||
status_label.text = "注册成功!请登录游戏"
|
||||
status_label.modulate = Color.GREEN
|
||||
|
||||
# 注册成功后,如果启用了记住密码,保存登录信息
|
||||
if remember_password:
|
||||
var user_name = username_input.text.strip_edges()
|
||||
var user_password = password_input.text.strip_edges()
|
||||
_save_login_info(user_name, user_password)
|
||||
|
||||
# 清除注册相关的输入框
|
||||
password_input_2.text = ""
|
||||
verificationcode_input.text = ""
|
||||
else:
|
||||
status_label.text = "注册失败:" + message
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
# 保存登录信息到JSON文件
|
||||
func _save_login_info(user_name: String, password: String):
|
||||
var login_data = {
|
||||
"user_name": user_name,
|
||||
"password": password
|
||||
}
|
||||
|
||||
var file = FileAccess.open("user://login.json", FileAccess.WRITE)
|
||||
if file:
|
||||
var json_string = JSON.stringify(login_data, "\t")
|
||||
file.store_string(json_string)
|
||||
file.close()
|
||||
print("登录信息已保存")
|
||||
else:
|
||||
print("无法保存登录信息")
|
||||
|
||||
# 从JSON文件加载登录信息
|
||||
func _load_login_info():
|
||||
var file = FileAccess.open("user://login.json", FileAccess.READ)
|
||||
if file:
|
||||
var json_text = file.get_as_text()
|
||||
file.close()
|
||||
|
||||
var json = JSON.new()
|
||||
var parse_result = json.parse(json_text)
|
||||
if parse_result == OK:
|
||||
var login_data = json.get_data()
|
||||
if login_data.has("user_name") and login_data.has("password"):
|
||||
var saved_username = login_data.get("user_name", "")
|
||||
var saved_password = login_data.get("password", "")
|
||||
|
||||
if saved_username != "" and saved_password != "":
|
||||
username_input.text = saved_username
|
||||
password_input.text = saved_password
|
||||
status_label.text = "已加载保存的登录信息"
|
||||
status_label.modulate = Color.CYAN
|
||||
print("登录信息已加载:用户名 =", saved_username)
|
||||
else:
|
||||
status_label.text = "欢迎使用萌芽农场"
|
||||
status_label.modulate = Color.WHITE
|
||||
print("没有有效的保存登录信息")
|
||||
else:
|
||||
print("登录信息格式错误")
|
||||
else:
|
||||
print("登录信息JSON解析错误:", json.get_error_message())
|
||||
else:
|
||||
# 创建默认的登录信息文件
|
||||
_save_login_info("", "")
|
||||
status_label.text = "欢迎使用萌芽农场"
|
||||
status_label.modulate = Color.WHITE
|
||||
print("没有找到保存的登录信息,已创建默认文件")
|
||||
|
||||
# 清除保存的登录信息
|
||||
func _clear_login_info():
|
||||
var file = FileAccess.open("user://login.json", FileAccess.WRITE)
|
||||
if file:
|
||||
var empty_data = {
|
||||
"user_name": "",
|
||||
"password": ""
|
||||
}
|
||||
var json_string = JSON.stringify(empty_data, "\t")
|
||||
file.store_string(json_string)
|
||||
file.close()
|
||||
print("登录信息已清除")
|
||||
else:
|
||||
print("无法清除登录信息")
|
||||
|
||||
# 切换记住密码选项
|
||||
func toggle_remember_password():
|
||||
remember_password = !remember_password
|
||||
print("记住密码选项:", "开启" if remember_password else "关闭")
|
||||
|
||||
# 如果关闭了记住密码,清除已保存的信息
|
||||
if not remember_password:
|
||||
_clear_login_info()
|
||||
|
||||
# 检查是否有保存的登录信息
|
||||
func has_saved_login_info() -> bool:
|
||||
var file = FileAccess.open("user://login.json", FileAccess.READ)
|
||||
if file:
|
||||
var json_text = file.get_as_text()
|
||||
file.close()
|
||||
|
||||
var json = JSON.new()
|
||||
var parse_result = json.parse(json_text)
|
||||
if parse_result == OK:
|
||||
var login_data = json.get_data()
|
||||
var user_name = login_data.get("user_name", "")
|
||||
var password = login_data.get("password", "")
|
||||
return user_name != "" and password != ""
|
||||
|
||||
return false
|
||||
|
||||
# 快捷登录(使用保存的登录信息)
|
||||
func quick_login():
|
||||
if has_saved_login_info():
|
||||
var user_name = username_input.text.strip_edges()
|
||||
var user_password = password_input.text.strip_edges()
|
||||
|
||||
if user_name != "" and user_password != "":
|
||||
print("执行快捷登录...")
|
||||
_on_login_button_pressed()
|
||||
else:
|
||||
status_label.text = "保存的登录信息不完整"
|
||||
status_label.modulate = Color.ORANGE
|
||||
else:
|
||||
status_label.text = "没有保存的登录信息"
|
||||
status_label.modulate = Color.ORANGE
|
||||
|
||||
# 获取保存的用户名(用于调试或显示)
|
||||
func get_saved_username() -> String:
|
||||
var file = FileAccess.open("user://login.json", FileAccess.READ)
|
||||
if file:
|
||||
var json_text = file.get_as_text()
|
||||
file.close()
|
||||
|
||||
var json = JSON.new()
|
||||
var parse_result = json.parse(json_text)
|
||||
if parse_result == OK:
|
||||
var login_data = json.get_data()
|
||||
return login_data.get("user_name", "")
|
||||
|
||||
return ""
|
||||
1
GUI/login_panel.gd.uid
Normal file
1
GUI/login_panel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cka0r4g8tbf0
|
||||
479
GUI/player_bag_panel.gd
Normal file
479
GUI/player_bag_panel.gd
Normal file
@@ -0,0 +1,479 @@
|
||||
extends Panel
|
||||
|
||||
# 背包格子容器
|
||||
@onready var player_bag_grid_container : GridContainer = $ScrollContainer/Bag_Grid
|
||||
@onready var quit_button : Button = $QuitButton
|
||||
|
||||
#各种排序过滤按钮
|
||||
@onready var sort_all_button : Button = $SortContainer/Sort_All#全部
|
||||
@onready var sort_common_button : Button = $SortContainer/Sort_Common#普通
|
||||
@onready var sort_superior_button : Button = $SortContainer/Sort_Superior#优良
|
||||
@onready var sort_rare_button : Button = $SortContainer/Sort_Rare#稀有
|
||||
@onready var sort_epic_button : Button = $SortContainer/Sort_Epic#史诗
|
||||
@onready var sort_legendary_button : Button = $SortContainer/Sort_Legendary#传奇
|
||||
@onready var sort_price_button : Button = $SortContainer/Sort_Price#价格
|
||||
@onready var sort_growtime_button : Button = $SortContainer/Sort_GrowTime#生长时间
|
||||
@onready var sort_profit_button : Button = $SortContainer/Sort_Profit#收益
|
||||
@onready var sort_level_button : Button = $SortContainer/Sort_Level#等级
|
||||
|
||||
#预添加常用的面板
|
||||
@onready var main_game = get_node("/root/main")
|
||||
@onready var land_panel = get_node("/root/main/UI/LandPanel")
|
||||
@onready var crop_store_panel = get_node("/root/main/UI/PlayerBagPanel")
|
||||
@onready var player_ranking_panel = get_node("/root/main/UI/PlayerRankingPanel")
|
||||
@onready var player_bag_panel = get_node("/root/main/UI/PlayerBagPanel")
|
||||
@onready var network_manager = get_node("/root/main/UI/TCPNetworkManager")
|
||||
|
||||
# 作物图片缓存(复用主游戏的缓存系统)
|
||||
var crop_textures_cache : Dictionary = {}
|
||||
var crop_frame_counts : Dictionary = {}
|
||||
|
||||
# 当前选择的地块索引,从MainGame获取
|
||||
var selected_lot_index : int = -1
|
||||
|
||||
# 当前过滤和排序设置
|
||||
var current_filter_quality = ""
|
||||
var current_sort_key = ""
|
||||
var current_sort_ascending = true
|
||||
|
||||
# 准备函数
|
||||
func _ready():
|
||||
# 连接按钮信号
|
||||
_connect_buttons()
|
||||
|
||||
# 隐藏面板(初始默认隐藏)
|
||||
self.hide()
|
||||
|
||||
# 连接所有按钮信号
|
||||
func _connect_buttons():
|
||||
# 关闭按钮
|
||||
quit_button.pressed.connect(self._on_quit_button_pressed)
|
||||
|
||||
# 过滤按钮
|
||||
sort_all_button.pressed.connect(func(): _filter_by_quality(""))
|
||||
sort_common_button.pressed.connect(func(): _filter_by_quality("普通"))
|
||||
sort_superior_button.pressed.connect(func(): _filter_by_quality("优良"))
|
||||
sort_rare_button.pressed.connect(func(): _filter_by_quality("稀有"))
|
||||
sort_epic_button.pressed.connect(func(): _filter_by_quality("史诗"))
|
||||
sort_legendary_button.pressed.connect(func(): _filter_by_quality("传奇"))
|
||||
|
||||
# 排序按钮
|
||||
sort_price_button.pressed.connect(func(): _sort_by("花费"))
|
||||
sort_growtime_button.pressed.connect(func(): _sort_by("生长时间"))
|
||||
sort_profit_button.pressed.connect(func(): _sort_by("收益"))
|
||||
sort_level_button.pressed.connect(func(): _sort_by("等级"))
|
||||
|
||||
# 初始化玩家背包
|
||||
func init_player_bag():
|
||||
# 清空玩家背包格子
|
||||
for child in player_bag_grid_container.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# 显示背包中的种子
|
||||
update_player_bag_ui()
|
||||
|
||||
# 更新玩家背包UI
|
||||
func update_player_bag_ui():
|
||||
# 清空玩家背包格子
|
||||
for child in player_bag_grid_container.get_children():
|
||||
child.queue_free()
|
||||
#print("更新背包UI,背包中物品数量:", main_game.player_bag.size())
|
||||
|
||||
# 应用过滤和排序
|
||||
var filtered_seeds = _get_filtered_and_sorted_seeds()
|
||||
|
||||
# 为背包中的每个过滤后的种子创建按钮
|
||||
for seed_item in filtered_seeds:
|
||||
var crop_name = seed_item["name"]
|
||||
var crop_quality = seed_item["quality"]
|
||||
var crop_count = seed_item["count"]
|
||||
#print("背包物品:", crop_name, " 数量:", crop_count)
|
||||
# 创建种子按钮
|
||||
var button = _create_crop_button(crop_name, crop_quality)
|
||||
# 更新按钮文本显示数量
|
||||
button.text = str(crop_quality + "-" + crop_name + "\n数量:" + str(crop_count))
|
||||
|
||||
# 根据是否处于访问模式连接不同的事件
|
||||
if main_game.is_visiting_mode:
|
||||
# 访问模式下,点击种子只显示信息,不能种植
|
||||
button.pressed.connect(func(): _on_visit_seed_selected(crop_name, crop_count))
|
||||
else:
|
||||
# 正常模式下,连接种植事件
|
||||
button.pressed.connect(func(): _on_bag_seed_selected(crop_name))
|
||||
|
||||
player_bag_grid_container.add_child(button)
|
||||
|
||||
# 获取过滤和排序后的种子列表
|
||||
func _get_filtered_and_sorted_seeds():
|
||||
var filtered_seeds = []
|
||||
|
||||
# 收集符合条件的种子
|
||||
for seed_item in main_game.player_bag:
|
||||
# 品质过滤
|
||||
if current_filter_quality != "" and seed_item["quality"] != current_filter_quality:
|
||||
continue
|
||||
|
||||
# 获取种子对应的作物数据
|
||||
var crop_data = null
|
||||
if main_game.can_planted_crop.has(seed_item["name"]):
|
||||
crop_data = main_game.can_planted_crop[seed_item["name"]]
|
||||
|
||||
# 添加到过滤后的列表
|
||||
filtered_seeds.append({
|
||||
"name": seed_item["name"],
|
||||
"quality": seed_item["quality"],
|
||||
"count": seed_item["count"],
|
||||
"data": crop_data
|
||||
})
|
||||
|
||||
# 如果有排序条件且数据可用,进行排序
|
||||
if current_sort_key != "":
|
||||
filtered_seeds.sort_custom(Callable(self, "_sort_seed_items"))
|
||||
|
||||
return filtered_seeds
|
||||
|
||||
# 自定义排序函数
|
||||
func _sort_seed_items(a, b):
|
||||
# 检查是否有有效数据用于排序
|
||||
if a["data"] == null or b["data"] == null:
|
||||
# 如果某一项没有数据,将其排在后面
|
||||
if a["data"] == null and b["data"] != null:
|
||||
return false
|
||||
if a["data"] != null and b["data"] == null:
|
||||
return true
|
||||
# 如果都没有数据,按名称排序
|
||||
return a["name"] < b["name"]
|
||||
|
||||
# 确保排序键存在于数据中
|
||||
if !a["data"].has(current_sort_key) or !b["data"].has(current_sort_key):
|
||||
print("警告: 排序键 ", current_sort_key, " 在某些种子数据中不存在")
|
||||
return false
|
||||
|
||||
# 执行排序
|
||||
if current_sort_ascending:
|
||||
return a["data"][current_sort_key] < b["data"][current_sort_key]
|
||||
else:
|
||||
return a["data"][current_sort_key] > b["data"][current_sort_key]
|
||||
|
||||
# 按品质过滤种子
|
||||
func _filter_by_quality(quality: String):
|
||||
current_filter_quality = quality
|
||||
print("过滤种子,品质: " + (quality if quality != "" else "全部"))
|
||||
update_player_bag_ui()
|
||||
|
||||
# 按指定键排序
|
||||
func _sort_by(sort_key: String):
|
||||
# 切换排序方向或设置新排序键
|
||||
if current_sort_key == sort_key:
|
||||
current_sort_ascending = !current_sort_ascending
|
||||
else:
|
||||
current_sort_key = sort_key
|
||||
current_sort_ascending = true
|
||||
|
||||
print("排序种子,键: " + sort_key + ",升序: " + str(current_sort_ascending))
|
||||
update_player_bag_ui()
|
||||
|
||||
# 创建作物按钮
|
||||
func _create_crop_button(crop_name: String, crop_quality: String) -> Button:
|
||||
# 根据品质选择相应的进度条
|
||||
var button = null
|
||||
#普通 Color.HONEYDEW#白色
|
||||
#优良 Color.DODGER_BLUE#深蓝色
|
||||
#稀有 Color.HOT_PINK#品红色
|
||||
#史诗 Color.YELLOW#黄色
|
||||
#传奇 Color.ORANGE_RED#红色
|
||||
#空地 Color.GREEN#绿色
|
||||
#未开垦 Color.WEB_GRAY#深褐色
|
||||
match crop_quality:
|
||||
"普通":
|
||||
button = main_game.green_bar.duplicate()
|
||||
"优良":
|
||||
button = main_game.orange_bar.duplicate()
|
||||
"稀有":
|
||||
button = main_game.white_blue_bar.duplicate()
|
||||
"史诗":
|
||||
button = main_game.pink_bar.duplicate()
|
||||
"传奇":
|
||||
button = main_game.black_blue_bar.duplicate()
|
||||
_: # 默认情况
|
||||
button = main_game.green_bar.duplicate()
|
||||
|
||||
# 确保按钮可见并可点击
|
||||
button.visible = true
|
||||
button.disabled = false
|
||||
button.focus_mode = Control.FOCUS_ALL
|
||||
|
||||
# 设置按钮文本
|
||||
button.text = str(crop_quality + "-" + crop_name)
|
||||
|
||||
# 添加工具提示 (tooltip)
|
||||
if main_game.can_planted_crop.has(crop_name):
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 将成熟时间从秒转换为天时分秒格式
|
||||
var total_seconds = int(crop["生长时间"])
|
||||
|
||||
# 定义时间单位换算
|
||||
var SECONDS_PER_MINUTE = 60
|
||||
var SECONDS_PER_HOUR = 3600
|
||||
var SECONDS_PER_DAY = 86400
|
||||
|
||||
# 计算各时间单位
|
||||
var days = total_seconds / SECONDS_PER_DAY
|
||||
total_seconds %= SECONDS_PER_DAY
|
||||
|
||||
var hours = total_seconds / SECONDS_PER_HOUR
|
||||
total_seconds %= SECONDS_PER_HOUR
|
||||
|
||||
var minutes = total_seconds / SECONDS_PER_MINUTE
|
||||
var seconds = total_seconds % SECONDS_PER_MINUTE
|
||||
|
||||
# 构建时间字符串(只显示有值的单位)
|
||||
var time_str = ""
|
||||
if days > 0:
|
||||
time_str += str(days) + "天"
|
||||
if hours > 0:
|
||||
time_str += str(hours) + "小时"
|
||||
if minutes > 0:
|
||||
time_str += str(minutes) + "分钟"
|
||||
if seconds > 0:
|
||||
time_str += str(seconds) + "秒"
|
||||
|
||||
button.tooltip_text = str(
|
||||
"作物: " + crop_name + "\n" +
|
||||
"品质: " + crop_quality + "\n" +
|
||||
"价格: " + str(crop["花费"]) + "元\n" +
|
||||
"成熟时间: " + time_str + "\n" +
|
||||
"收获收益: " + str(crop["收益"]) + "元\n" +
|
||||
"需求等级: " + str(crop["等级"]) + "\n" +
|
||||
"耐候性: " + str(crop["耐候性"]) + "\n" +
|
||||
"经验: " + str(crop["经验"]) + "点\n" +
|
||||
"描述: " + str(crop["描述"])
|
||||
)
|
||||
|
||||
# 如果按钮有标题标签,设置标题
|
||||
if button.has_node("Title"):
|
||||
button.get_node("Title").text = crop_quality
|
||||
match crop_quality:
|
||||
"普通":
|
||||
button.get_node("Title").modulate = Color.HONEYDEW#白色
|
||||
"优良":
|
||||
button.get_node("Title").modulate =Color.DODGER_BLUE#深蓝色
|
||||
"稀有":
|
||||
button.get_node("Title").modulate =Color.HOT_PINK#品红色
|
||||
"史诗":
|
||||
button.get_node("Title").modulate =Color.YELLOW#黄色
|
||||
"传奇":
|
||||
button.get_node("Title").modulate =Color.ORANGE_RED#红色
|
||||
|
||||
# 更新按钮的作物图片
|
||||
_update_button_crop_image(button, crop_name)
|
||||
|
||||
return button
|
||||
|
||||
# 从背包中选择种子并种植
|
||||
func _on_bag_seed_selected(crop_name):
|
||||
# 检查是否处于访问模式
|
||||
if main_game.is_visiting_mode:
|
||||
Toast.show("访问模式下无法种植", Color.ORANGE, 2.0, 1.0)
|
||||
return
|
||||
|
||||
# 从主场景获取当前选择的地块索引
|
||||
selected_lot_index = main_game.selected_lot_index
|
||||
|
||||
if selected_lot_index != -1:
|
||||
# 检查背包中是否有这个种子
|
||||
var seed_index = -1
|
||||
for i in range(len(main_game.player_bag)):
|
||||
if main_game.player_bag[i]["name"] == crop_name:
|
||||
seed_index = i
|
||||
break
|
||||
#print("选择种子:", crop_name, ",背包索引:", seed_index)
|
||||
|
||||
if seed_index != -1 and main_game.player_bag[seed_index]["count"] > 0:
|
||||
# 种植种子并从背包中减少数量
|
||||
_plant_crop_from_bag(selected_lot_index, crop_name, seed_index)
|
||||
main_game.selected_lot_index = -1
|
||||
self.hide()
|
||||
|
||||
# 访问模式下的种子点击处理
|
||||
func _on_visit_seed_selected(crop_name, crop_count):
|
||||
# 显示种子信息
|
||||
var info_text = ""
|
||||
|
||||
if main_game.can_planted_crop.has(crop_name):
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
var quality = crop.get("品质", "未知")
|
||||
var price = crop.get("花费", 0)
|
||||
var grow_time = crop.get("生长时间", 0)
|
||||
var profit = crop.get("收益", 0)
|
||||
var level_req = crop.get("等级", 1)
|
||||
|
||||
# 将成熟时间转换为可读格式
|
||||
var time_str = ""
|
||||
var total_seconds = int(grow_time)
|
||||
var hours = total_seconds / 3600
|
||||
var minutes = (total_seconds % 3600) / 60
|
||||
var seconds = total_seconds % 60
|
||||
|
||||
if hours > 0:
|
||||
time_str += str(hours) + "小时"
|
||||
if minutes > 0:
|
||||
time_str += str(minutes) + "分钟"
|
||||
if seconds > 0:
|
||||
time_str += str(seconds) + "秒"
|
||||
|
||||
info_text = quality + "-" + crop_name + " (数量: " + str(crop_count) + ")\n"
|
||||
info_text += "价格: " + str(price) + "元, 收益: " + str(profit) + "元\n"
|
||||
info_text += "成熟时间: " + time_str + ", 需求等级: " + str(level_req)
|
||||
else:
|
||||
info_text = crop_name + " (数量: " + str(crop_count) + ")"
|
||||
|
||||
Toast.show(info_text, Color.CYAN, 3.0, 1.0)
|
||||
print("查看种子信息: ", info_text)
|
||||
|
||||
# 从背包种植作物
|
||||
func _plant_crop_from_bag(index, crop_name, seed_index):
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 检查是否有效的种子索引,防止越界访问
|
||||
if seed_index < 0 or seed_index >= main_game.player_bag.size():
|
||||
#print("错误:无效的种子索引 ", seed_index)
|
||||
return
|
||||
|
||||
# 发送种植请求到服务器
|
||||
|
||||
if network_manager and network_manager.sendPlantCrop(index, crop_name):
|
||||
# 种植请求已发送,等待服务器响应
|
||||
Toast.show("正在发送种植请求", Color.YELLOW, 2.0, 1.0)
|
||||
# 关闭背包面板
|
||||
hide()
|
||||
|
||||
# 关闭面板
|
||||
func _on_quit_button_pressed():
|
||||
self.hide()
|
||||
|
||||
# 获取作物的最后一帧图片(用于背包显示)
|
||||
func _get_crop_final_texture(crop_name: String) -> Texture2D:
|
||||
"""
|
||||
获取作物的最后一帧图片,用于背包显示
|
||||
如果作物图片不存在,使用默认图片的最后一帧
|
||||
"""
|
||||
# 先尝试从主游戏的缓存中获取
|
||||
if main_game and main_game.crop_textures_cache.has(crop_name):
|
||||
var textures = main_game.crop_textures_cache[crop_name]
|
||||
if textures.size() > 0:
|
||||
return textures[textures.size() - 1] # 返回最后一帧
|
||||
|
||||
# 如果主游戏缓存中没有,自己加载
|
||||
var textures = _load_crop_textures(crop_name)
|
||||
if textures.size() > 0:
|
||||
return textures[textures.size() - 1] # 返回最后一帧
|
||||
|
||||
return null
|
||||
|
||||
# 加载作物图片序列帧(复用主游戏的逻辑)
|
||||
func _load_crop_textures(crop_name: String) -> Array:
|
||||
"""
|
||||
加载指定作物的所有序列帧图片
|
||||
"""
|
||||
if crop_textures_cache.has(crop_name):
|
||||
return crop_textures_cache[crop_name]
|
||||
|
||||
var textures = []
|
||||
var crop_path = "res://assets/作物/" + crop_name + "/"
|
||||
var default_path = "res://assets/作物/默认/"
|
||||
|
||||
# 检查作物文件夹是否存在
|
||||
if DirAccess.dir_exists_absolute(crop_path):
|
||||
# 尝试加载作物的序列帧(从0开始)
|
||||
var frame_index = 0
|
||||
while true:
|
||||
var texture_path = crop_path + str(frame_index) + ".png"
|
||||
if ResourceLoader.exists(texture_path):
|
||||
var texture = load(texture_path)
|
||||
if texture:
|
||||
textures.append(texture)
|
||||
frame_index += 1
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
if textures.size() > 0:
|
||||
print("背包加载作物 ", crop_name, " 的 ", textures.size(), " 帧图片")
|
||||
else:
|
||||
print("背包:作物 ", crop_name, " 文件夹存在但没有找到有效图片,使用默认图片")
|
||||
textures = _load_default_textures()
|
||||
else:
|
||||
print("背包:作物 ", crop_name, " 的文件夹不存在,使用默认图片")
|
||||
textures = _load_default_textures()
|
||||
|
||||
# 缓存结果
|
||||
crop_textures_cache[crop_name] = textures
|
||||
crop_frame_counts[crop_name] = textures.size()
|
||||
|
||||
return textures
|
||||
|
||||
# 加载默认图片
|
||||
func _load_default_textures() -> Array:
|
||||
"""
|
||||
加载默认作物图片
|
||||
"""
|
||||
if crop_textures_cache.has("默认"):
|
||||
return crop_textures_cache["默认"]
|
||||
|
||||
var textures = []
|
||||
var default_path = "res://assets/作物/默认/"
|
||||
|
||||
# 尝试加载默认图片序列帧
|
||||
var frame_index = 0
|
||||
while true:
|
||||
var texture_path = default_path + str(frame_index) + ".png"
|
||||
if ResourceLoader.exists(texture_path):
|
||||
var texture = load(texture_path)
|
||||
if texture:
|
||||
textures.append(texture)
|
||||
frame_index += 1
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
# 如果没有找到序列帧,尝试加载单个默认图片
|
||||
if textures.size() == 0:
|
||||
var single_texture_path = default_path + "0.png"
|
||||
if ResourceLoader.exists(single_texture_path):
|
||||
var texture = load(single_texture_path)
|
||||
if texture:
|
||||
textures.append(texture)
|
||||
|
||||
# 缓存默认图片
|
||||
crop_textures_cache["默认"] = textures
|
||||
crop_frame_counts["默认"] = textures.size()
|
||||
|
||||
print("背包加载了 ", textures.size(), " 个默认作物图片")
|
||||
return textures
|
||||
|
||||
# 更新按钮的作物图片
|
||||
func _update_button_crop_image(button: Button, crop_name: String):
|
||||
"""
|
||||
更新按钮中的作物图片
|
||||
"""
|
||||
# 检查按钮是否有CropImage节点
|
||||
var crop_image = button.get_node_or_null("CropImage")
|
||||
if not crop_image:
|
||||
print("背包按钮没有找到CropImage节点:", button.name)
|
||||
return
|
||||
|
||||
# 获取作物的最后一帧图片
|
||||
var texture = _get_crop_final_texture(crop_name)
|
||||
|
||||
if texture:
|
||||
# CropImage是Sprite2D,直接设置texture属性
|
||||
crop_image.texture = texture
|
||||
crop_image.visible = true
|
||||
print("背包更新作物图片:", crop_name)
|
||||
else:
|
||||
crop_image.visible = false
|
||||
print("背包无法获取作物图片:", crop_name)
|
||||
1
GUI/player_bag_panel.gd.uid
Normal file
1
GUI/player_bag_panel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cgr332wsx63a8
|
||||
71
GUI/player_ranking_item.tscn
Normal file
71
GUI/player_ranking_item.tscn
Normal file
@@ -0,0 +1,71 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://crd28qnymob7"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://c3vng0nal1wr8" path="res://assets/Test/g.png" id="1_sgoxp"]
|
||||
[ext_resource type="Script" uid="uid://0d2j5m6j2ema" path="res://Components/HTTPTextureRect.gd" id="2_ky0k8"]
|
||||
|
||||
[node name="player_ranking_item" type="VBoxContainer"]
|
||||
offset_right = 1152.0
|
||||
offset_bottom = 82.0
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SerialNumber" type="Label" parent="HBox"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "1."
|
||||
|
||||
[node name="PlayerAvatar" type="TextureRect" parent="HBox"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("1_sgoxp")
|
||||
expand_mode = 3
|
||||
script = ExtResource("2_ky0k8")
|
||||
metadata/_custom_type_script = "uid://0d2j5m6j2ema"
|
||||
|
||||
[node name="PlayerName" type="Label" parent="HBox"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "树萌芽"
|
||||
|
||||
[node name="PlayerMoney" type="Label" parent="HBox"]
|
||||
modulate = Color(1, 1, 0, 1)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "钱币:999"
|
||||
|
||||
[node name="SeedNum" type="Label" parent="HBox"]
|
||||
modulate = Color(0, 1, 0, 1)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "种子数:999"
|
||||
|
||||
[node name="PlayerLevel" type="Label" parent="HBox"]
|
||||
modulate = Color(0, 1, 1, 1)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "等级:999"
|
||||
|
||||
[node name="VisitButton" type="Button" parent="HBox"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "访问"
|
||||
|
||||
[node name="HBox2" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="LastLoginTime" type="Label" parent="HBox2"]
|
||||
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"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_font_sizes/font_size = 20
|
||||
text = "累计在线时长:99时60分60秒"
|
||||
110
GUI/player_ranking_panel.gd
Normal file
110
GUI/player_ranking_panel.gd
Normal file
@@ -0,0 +1,110 @@
|
||||
extends Panel
|
||||
|
||||
@onready var player_ranking_list : VBoxContainer = $Scroll/PlayerList
|
||||
@onready var refresh_button : Button = $RefreshButton
|
||||
@onready var quit_button : Button = $QuitButton
|
||||
|
||||
#预添加常用的面板
|
||||
@onready var main_game = get_node("/root/main")
|
||||
@onready var land_panel = get_node("/root/main/UI/LandPanel")
|
||||
@onready var crop_store_panel = get_node("/root/main/UI/PlayerBagPanel")
|
||||
@onready var player_ranking_panel = get_node("/root/main/UI/PlayerRankingPanel")
|
||||
@onready var player_bag_panel = get_node("/root/main/UI/PlayerBagPanel")
|
||||
@onready var network_manager = get_node("/root/main/UI/TCPNetworkManager")
|
||||
|
||||
#下面这是每个玩家要展示的信息,直接获取服务器玩家数据json文件来实现
|
||||
#模板用于复制创建新的玩家条目
|
||||
@onready var player_info_template : VBoxContainer = $Scroll/PlayerList/player_ranking_item
|
||||
|
||||
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()
|
||||
|
||||
# 处理玩家排行榜响应
|
||||
func handle_player_rankings_response(data):
|
||||
# 检查响应是否成功
|
||||
if not data.get("success", false):
|
||||
print("获取玩家排行榜失败:", data.get("message", "未知错误"))
|
||||
return
|
||||
|
||||
# 清除现有的玩家条目(除了模板)
|
||||
for child in player_ranking_list.get_children():
|
||||
if child != player_info_template:
|
||||
child.queue_free()
|
||||
|
||||
# 添加玩家条目
|
||||
var players = data.get("players", [])
|
||||
for player_data in players:
|
||||
add_player_entry(player_data)
|
||||
|
||||
# 添加单个玩家条目
|
||||
func add_player_entry(player_data):
|
||||
# 复制模板
|
||||
var player_entry = player_info_template.duplicate()
|
||||
player_entry.visible = true
|
||||
player_ranking_list.add_child(player_entry)
|
||||
|
||||
# 设置玩家信息
|
||||
var player_name = player_entry.get_node("HBox/PlayerName")
|
||||
var player_level = player_entry.get_node("HBox/PlayerLevel")
|
||||
var player_money = player_entry.get_node("HBox/PlayerMoney")
|
||||
var player_seed_num = player_entry.get_node("HBox/SeedNum")
|
||||
var player_online_time = player_entry.get_node("HBox2/OnlineTime")
|
||||
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 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_online_time.text = "游玩时间: " + player_data.get("total_login_time", "0时0分0秒")
|
||||
player_last_login_time.text = "最后登录: " + player_data.get("last_login_time", "未知")
|
||||
|
||||
# 尝试加载玩家头像(使用用户名/QQ号加载头像,而不是显示名)
|
||||
if username.is_valid_int():
|
||||
player_avatar.load_from_url("http://q1.qlogo.cn/g?b=qq&nk=" + username + "&s=100")
|
||||
|
||||
# 设置访问按钮
|
||||
visit_button.pressed.connect(func(): _on_visit_player_pressed(username))
|
||||
|
||||
# 访问玩家按钮点击
|
||||
func _on_visit_player_pressed(username):
|
||||
print("访问玩家:", username)
|
||||
|
||||
# 发送访问玩家请求
|
||||
if network_manager and network_manager.has_method("sendVisitPlayer"):
|
||||
var success = network_manager.sendVisitPlayer(username)
|
||||
if success:
|
||||
print("已发送访问玩家请求:", username)
|
||||
else:
|
||||
print("发送访问玩家请求失败,网络未连接")
|
||||
else:
|
||||
print("网络管理器不可用")
|
||||
|
||||
# 刷新按钮点击
|
||||
func _on_refresh_button_pressed():
|
||||
request_player_rankings()
|
||||
|
||||
# 退出按钮点击
|
||||
func _on_quit_button_pressed():
|
||||
self.hide()
|
||||
|
||||
# 添加到main.gd中调用
|
||||
func _handle_player_rankings_response(data):
|
||||
handle_player_rankings_response(data)
|
||||
1
GUI/player_ranking_panel.gd.uid
Normal file
1
GUI/player_ranking_panel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://fk4q3x6uqydd
|
||||
Reference in New Issue
Block a user