Files
Sprout-Farm/main.gd
2024-12-03 21:35:56 +08:00

616 lines
22 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends Node
# 变量定义
@onready var grid_container = $GridContainer # 农场地块的 GridContainer
@onready var crop_item = $CropItem
@onready var crop_list = $CropList # 作物选择的 ItemList
@onready var show_money = $money # 显示当前剩余的钱
@onready var show_experience = $experience # 显示当前玩家的经验
@onready var show_level = $level # 显示当前玩家的等级
@onready var toast = $ToastShow
@onready var toast2 = $ToastShow2
@onready var land_panel = $Land_Panel
@onready var dig_button = $Land_Panel/VBox/HBox/Dig_button
@onready var crop_grid_container = $ScrollContainer/Crop_GridContainer
@onready var green_bar = $Copy_Nodes/Green #普通
@onready var white_blue_bar = $Copy_Nodes/White_Blue #稀有
@onready var orange_bar = $Copy_Nodes/Orange #优良
@onready var pink_bar = $Copy_Nodes/Pink #史诗
@onready var black_blue_bar = $Copy_Nodes/Black_Blue #传奇
@onready var red_bar = $Copy_Nodes/Red #神圣
#----------------网络联机部分--------------------------
#用户登录账号用QQ号代替
@onready var username_input = $LoginPanel/username_input
#用户登录密码
@onready var password_input = $LoginPanel/password_input
#登录按钮
@onready var login_button = $LoginPanel/login_button
#----------------网络联机部分--------------------------
@onready var tip = $tip
var money: int = 500 # 默认每个人初始为100元
var experience: float = 0.0 # 初始每个玩家的经验为0
var grow_speed: float = 1 # 作物生长速度
var level: int = 1 # 初始玩家等级为1
var farm_lots = [] # 用于保存每个地块的状态
var dig_index = 0
var dig_money = 1000
var climate_death_timer = 0
var blink_speed: float = 1 # 每秒闪烁的次数
var is_blink_on: bool = false # 是否闪烁状态
var blink_counter: float = 0.0 # 计数器,用于控制闪烁
var can_planted_crop = {
#玩家点击空地块时可以种植的作物
#品质有 普通,优良,稀有,史诗,传奇,品质会影响作物的颜色
#耐候性:种植的过程中可能会死亡
#等级:需要玩家达到相应等级才能种植
#经验:收获时可以获得的经验,经验到达某一程度,玩家会升等级
#基础作物
# 基础作物
"测试作物": {"花费": 1, "生长时间": 3, "收益": 9999, "品质": "普通", "描述": "测试作物", "耐候性": 10, "等级": 1, "经验": 999}, # 1分钟
"小麦": {"花费": 120, "生长时间": 120, "收益": 100, "品质": "普通", "描述": "基础作物,品质较低,适合新手种植", "耐候性": 10, "等级": 1, "经验": 10}, # 1分钟
"稻谷": {"花费": 100, "生长时间": 240, "收益": 120, "品质": "普通", "描述": "适合大规模种植的基础作物", "耐候性": 10, "等级": 1, "经验": 10}, # 2分钟
"玉米": {"花费": 70, "生长时间": 600, "收益": 90, "品质": "普通", "描述": "营养丰富的优良作物,适合稍有经验的玩家", "耐候性": 15, "等级": 2, "经验": 15}, # 5分钟
"土豆": {"花费": 75, "生长时间": 360, "收益": 90, "品质": "普通", "描述": "容易种植的耐寒作物", "耐候性": 12, "等级": 1, "经验": 10}, # 3分钟
"胡萝卜": {"花费": 60, "生长时间": 480, "收益": 80, "品质": "普通", "描述": "适合新手的健康作物", "耐候性": 12, "等级": 1, "经验": 10}, # 4分钟
# 中级作物
"草莓": {"花费": 120, "生长时间": 960, "收益": 150, "品质": "优良", "描述": "营养丰富的果实,收益不错", "耐候性": 14, "等级": 2, "经验": 20}, # 8分钟
"番茄": {"花费": 100, "生长时间": 720, "收益": 130, "品质": "优良", "描述": "常见作物,适合小规模种植", "耐候性": 12, "等级": 2, "经验": 15}, # 6分钟
"大豆": {"花费": 90, "生长时间": 840, "收益": 110, "品质": "优良", "描述": "富含蛋白质的基础作物", "耐候性": 11, "等级": 2, "经验": 12}, # 7分钟
# 高级作物
"蓝莓": {"花费": 150, "生长时间": 1200, "收益": 200, "品质": "稀有", "描述": "较为稀有的作物,市场价值较高", "耐候性": 18, "等级": 3, "经验": 25}, # 10分钟
"洋葱": {"花费": 85, "生长时间": 600, "收益": 105, "品质": "稀有", "描述": "烹饪常用的作物,适合中级种植", "耐候性": 10, "等级": 2, "经验": 10}, # 5分钟
"南瓜": {"花费": 180, "生长时间": 1440, "收益": 250, "品质": "稀有", "描述": "秋季收获的高收益作物", "耐候性": 20, "等级": 4, "经验": 30}, # 12分钟
"葡萄": {"花费": 200, "生长时间": 1200, "收益": 300, "品质": "稀有", "描述": "需要特殊管理的高收益作物", "耐候性": 15, "等级": 4, "经验": 35}, # 10分钟
"柿子": {"花费": 160, "生长时间": 1080, "收益": 240, "品质": "稀有", "描述": "富含营养的秋季作物", "耐候性": 18, "等级": 3, "经验": 28}, # 9分钟
"花椰菜": {"花费": 130, "生长时间": 960, "收益": 170, "品质": "稀有", "描述": "耐寒的高品质作物,适合经验丰富的玩家", "耐候性": 17, "等级": 3, "经验": 22}, # 8分钟
"芦笋": {"花费": 200, "生长时间": 1560, "收益": 280, "品质": "稀有", "描述": "市场需求量高的稀有作物", "耐候性": 15, "等级": 4, "经验": 30}, # 13分钟
# 史诗作物
"香草": {"花费": 250, "生长时间": 1800, "收益": 400, "品质": "史诗", "描述": "非常稀有且收益极高的作物", "耐候性": 22, "等级": 5, "经验": 40}, # 15分钟
"西瓜": {"花费": 240, "生长时间": 2400, "收益": 420, "品质": "史诗", "描述": "夏季丰产的高价值作物", "耐候性": 21, "等级": 5, "经验": 45}, # 20分钟
"甜菜": {"花费": 220, "生长时间": 2160, "收益": 350, "品质": "史诗", "描述": "营养丰富的根茎作物,收益较高", "耐候性": 20, "等级": 5, "经验": 38}, # 18分钟
"甘蔗": {"花费": 260, "生长时间": 3000, "收益": 450, "品质": "史诗", "描述": "需要充足水源的高价值作物", "耐候性": 18, "等级": 5, "经验": 50}, # 25分钟
# 传奇作物
"龙果": {"花费": 400, "生长时间": 4800, "收益": 600, "品质": "传奇", "描述": "极为稀有的热带作物,产量和价值都极高", "耐候性": 25, "等级": 6, "经验": 60}, # 40分钟
"松露": {"花费": 500, "生长时间": 7200, "收益": 700, "品质": "传奇", "描述": "极其珍贵的地下作物,市场价格极高", "耐候性": 23, "等级": 7, "经验": 80}, # 60分钟
"人参": {"花费": 450, "生长时间": 6600, "收益": 650, "品质": "传奇", "描述": "需要耐心等待的珍贵药材", "耐候性": 22, "等级": 6, "经验": 75}, # 55分钟
"金橘": {"花费": 420, "生长时间": 4800, "收益": 620, "品质": "传奇", "描述": "少见的耐寒果树,市场需求量极大", "耐候性": 26, "等级": 7, "经验": 70} # 40分钟
};
var selected_lot_index = -1 # 当前被选择的地块索引
#电脑版路径Windows或者Linux
#var game_path = "C:/Users/shumengya/Desktop/smyfarm/save.txt"
#
var game_path = "/storage/emulated/0/萌芽农场/保存.txt"
var save_time = 10
var farm_thread: Thread
# 准备阶段
func _ready():
farm_thread = Thread.new()
# 使用 Callable 创建可调用对象,指向当前对象的 _thread_update_farm_lots 方法
var callable = Callable(self, "_thread_update_farm_lots")
# 启动线程
var error = farm_thread.start(callable)
if error != OK:
print("Failed to start thread: ", error)
OS.request_permissions()
toast.Toast("快去偷其他人的菜吧!", Color.GREEN)
# 初始化农场地块
_init_farm_lots(40)
_update_farm_lots()
# 连接点击事件
#crop_list.connect("item_selected", Callable(self, "_on_crop_selected"))
# 初始隐藏作物选择列表
#crop_list.hide()
crop_grid_container.hide()
# 更新初始显示
_update_ui()
# 初始化作物选择列表
_init_crop_list2()
_load_game()
# 初始化农场地块
func _init_farm_lots(num_lots):
for i in range(num_lots):
farm_lots.append({
"is_diged": false, # 是否开垦
"is_planted": false, # 是否种植
"is_dead": false, # 是否作物已死亡
"crop_type": "", # 作物类型
"grow_time": 0, # 生长时间
"max_grow_time": 5 # 作物需要的最大生长时间假设5秒成熟
})
# 初始化作物选择列表
# 初始化作物选择列表
func _init_crop_list():
crop_list.clear()
for crop_name in can_planted_crop:
var crop = can_planted_crop[crop_name]
if crop["等级"] <= level: # 只显示当前等级可以种植的作物
# 添加作物项
crop_list.add_item(crop_name)
# 随机生成颜色
#var random_color = Color(randf(), randf(), randf())
# 设置作物项的自定义背景颜色
var item_index = crop_list.get_item_count() - 1 # 获取当前项的索引
#crop_list.set_item_custom_bg_color(item_index, random_color)
if crop["品质"] == "普通":
crop_list.set_item_custom_bg_color(item_index, Color.GAINSBORO)
pass
elif crop["品质"] == "优良":
crop_list.set_item_custom_bg_color(item_index, Color.DODGER_BLUE)
pass
elif crop["品质"] == "稀有":
crop_list.set_item_custom_bg_color(item_index,Color.PURPLE )
pass
elif crop["品质"] == "史诗":
crop_list.set_item_custom_bg_color(item_index,Color.YELLOW )
pass
elif crop["品质"] == "传奇":
crop_list.set_item_custom_bg_color(item_index, Color.ORANGE_RED)
pass
# 如果需要设置文本颜色,可以使用下面的代码(可选)
# crop_list.set_item_custom_color(item_index, Color.WHITE) # 设置文本颜色
# 初始化作物选择列表
func _init_crop_list2():
for child in crop_grid_container.get_children():
child.queue_free()
for crop_name in can_planted_crop:
var crop = can_planted_crop[crop_name]
var level_btn = null
var level6_btn = red_bar.duplicate()
if crop["等级"] <= level: # 只显示当前等级可以种植的作物
if crop["品质"] == "普通":
level_btn = green_bar.duplicate()
level_btn.connect("pressed", Callable(self, "_on_crop_selected").bind(crop_name))
level_btn.text = str(crop_name)
crop_grid_container.add_child(level_btn)
pass
elif crop["品质"] == "优良":
level_btn = white_blue_bar.duplicate()
level_btn.connect("pressed", Callable(self, "_on_crop_selected").bind(crop_name))
level_btn.text = str(crop_name)
crop_grid_container.add_child(level_btn)
pass
elif crop["品质"] == "稀有":
level_btn = orange_bar.duplicate()
level_btn.connect("pressed", Callable(self, "_on_crop_selected").bind(crop_name))
level_btn.text = str(crop_name)
crop_grid_container.add_child(level_btn)
pass
elif crop["品质"] == "史诗":
level_btn = pink_bar.duplicate()
level_btn.connect("pressed", Callable(self, "_on_crop_selected").bind(crop_name))
level_btn.text = str(crop_name)
crop_grid_container.add_child(level_btn)
pass
elif crop["品质"] == "传奇":
level_btn = black_blue_bar.duplicate()
level_btn.connect("pressed", Callable(self, "_on_crop_selected").bind(crop_name))
level_btn.text = str(crop_name)
crop_grid_container.add_child(level_btn)
pass
# 如果需要设置文本颜色,可以使用下面的代码(可选)
# crop_list.set_item_custom_color(item_index, Color.WHITE) # 设置文本颜色
pass
# 更新农场地块状态到 GridContainer
func _update_farm_lots(): #每一秒更新一次状态
for child in grid_container.get_children():
child.queue_free()
for j in 5:
if farm_lots[j]["is_diged"] == false:
farm_lots[j]["is_diged"] = true
pass
pass
for i in range(len(farm_lots)):
var lot = farm_lots[i]
var button = crop_item.duplicate()
var label = button.get_node("Label")
var progressbar = button.get_node("ProgressBar")
pass
if lot["is_diged"] == true:
dig_money = (i+1) * 1000
dig_button.text = "开垦"+"["+str(dig_money)+"]"
if lot["is_planted"] == true:
#寒冷环境配置,作物随机概率死亡
climate_death_timer += 1
if climate_death_timer >= 60 :
if random_probability(can_planted_crop[lot["crop_type"]]["耐候性"]):
lot["is_dead"] = true
pass
climate_death_timer = 0
pass
#如果作物已死亡!
if lot["is_dead"] == true:
print("["+farm_lots[i]["crop_type"]+"]"+"已死亡!")
label.modulate = Color.NAVY_BLUE
label.text = "["+farm_lots[i]["crop_type"]+"已死亡"+"]"
pass
#否者作物正常生长
else:
#label.text = lot["crop_type"] + " (" + str(int(lot["grow_time"])) + "/" + str(int(lot["max_grow_time"])) + ")"
var crop_name = lot["crop_type"]
label.text = "["+can_planted_crop[crop_name]["品质"]+"-"+lot["crop_type"]+"]"
#根据品质显示颜色
if(can_planted_crop[crop_name]["品质"]=="普通"):
label.modulate = Color.GAINSBORO
pass
elif (can_planted_crop[crop_name]["品质"]=="优良"):
label.modulate = Color.DODGER_BLUE
pass
elif (can_planted_crop[crop_name]["品质"]=="稀有"):
label.modulate = Color.PURPLE
pass
elif (can_planted_crop[crop_name]["品质"]=="史诗"):
label.modulate = Color.YELLOW
pass
elif (can_planted_crop[crop_name]["品质"]=="传奇"):
label.modulate = Color.ORANGE_RED
pass
progressbar.show()
progressbar.max_value = int(lot["max_grow_time"])
progressbar.set_target_value( int(lot["grow_time"]) )
#if is_blink_on:
#label.modulate = Color.YELLOW
#else:
#label.modulate = Color.ORANGE
pass
pass
else:
#土地开垦后没有作物则显示为空地
label.modulate =Color.GREEN
label.text = "["+"空地"+"]"
progressbar.hide()
#label.modulate = Color.WHITE
pass
pass
else :
#土地没有开垦则显示未开垦
label.modulate =Color.WEB_GRAY
label.text = "["+"未开垦"+"]"
progressbar.hide()
#label.modulate = Color.WHITE
pass
# 设置最小尺寸
#button.custom_minimum_size = Vector2(100, 100)
button.connect("pressed", Callable(self, "_on_item_selected").bind(i))
grid_container.add_child(button)
# 更新玩家信息显示
func _update_ui():
show_money.text = "当前金钱:" + str(money) + ""
show_money.modulate = Color.ORANGE
show_experience.text = "当前经验:" + str(experience) + ""
show_experience.modulate = Color.GREEN
show_level.text = "当前等级:" + str(level) + ""
show_level.modulate = Color.DODGER_BLUE
# 处理地块点击事件
func _on_item_selected(index):
var lot = farm_lots[index]
if lot["is_diged"]:
if lot["is_planted"]:
if lot["is_dead"]:
print(lot["crop_type"]+"已被铲除")
root_out_crop(index)
#label.modulate = Color.NAVY_BLUE
#label.text = "["+lot["crop_type"]+"已死亡"+"]"
pass
else:
_harvest_crop(index)
pass
pass
else:
# 记录选中的地块索引,显示作物选择列表
selected_lot_index = index
double_click_close(crop_grid_container)
pass
pass
else :
double_click_close(land_panel)
dig_index = index
pass
func double_click_close(node):
if node.visible == false:
node.show()
pass
else :
node.hide()
pass
pass
# 处理作物选择事件
func _on_crop_selected(crop_index):
print(crop_index)
#var crop_name = crop_list.get_item_text(crop_index).split(" (")[0]
var crop_name = crop_index
if selected_lot_index != -1:
_plant_crop(selected_lot_index, crop_name)
selected_lot_index = -1
#crop_list.hide() # 种植完成后隐藏作物选择列表
crop_grid_container.hide()
# 种植作物
func _plant_crop(index, crop_name):
var crop = can_planted_crop[crop_name]
if money < crop["花费"]:
print("金钱不足,无法种植 " + crop_name)
toast.Toast("金钱不足,无法种植 " + crop_name, Color.RED)
return
money -= crop["花费"]
farm_lots[index]["is_planted"] = true
farm_lots[index]["crop_type"] = crop_name
farm_lots[index]["grow_time"] = 0
farm_lots[index]["max_grow_time"] = crop["生长时间"]
print("在地块[[" + str(index) + "]种植了[" + crop_name + "]")
toast.Toast("在地块[[" + str(index) + "]种植了[" + crop_name + "]", Color.GREEN)
toast2.Toast(
"名称:"+crop_name+"\n"+
"花费:"+str(crop["花费"])+"\n"+
"成熟时间:"+str(crop["生长时间"])+"\n"+
"收益:"+str(crop["收益"])+"\n"+
"品质:"+str(crop["品质"])+"\n"+
"描述:"+str(crop["描述"])+"\n"+
"耐候性:"+str(crop["耐候性"])+"\n"+
"种植等级:"+str(crop["等级"])+"\n"+
"获得经验:"+str(crop["经验"])+"\n"
, Color.ORANGE)
_update_ui()
_update_farm_lots()
#OS
# 收获作物
func _harvest_crop(index):
var lot = farm_lots[index]
if lot["grow_time"] >= lot["max_grow_time"]:
var crop = can_planted_crop[lot["crop_type"]]
money += crop["收益"]+crop["花费"]
experience += crop["经验"]
toast.Toast("从地块[" + str(index) + "]收获了[" + lot["crop_type"] + "]作物", Color.YELLOW)
print("从地块[" + str(index) + "]收获了[" + lot["crop_type"] + "]作物")
lot["is_planted"] = false
lot["crop_type"] = ""
lot["grow_time"] = 0
_check_level_up()
_update_ui()
_update_farm_lots()
else:
print("作物还未成熟")
toast.Toast("作物还未成熟", Color.RED)
func root_out_crop(index):
var lot = farm_lots[index]
lot["is_planted"] = false
lot["grow_time"] = 0
toast.Toast("从地块[" + str(index) + "]铲除了[" + lot["crop_type"] + "]作物", Color.YELLOW)
lot["crop_type"] = ""
_check_level_up()
_update_ui()
_update_farm_lots()
pass
# 检查玩家是否可以升级
func _check_level_up():
var level_up_experience = 100 * level
if experience >= level_up_experience:
level += 1
experience -= level_up_experience
print("恭喜!你升到了等级 ", level)
toast.Toast("恭喜!你升到了" + str(level) + "", Color.SKY_BLUE)
_init_crop_list2()
# 使用 _process 实现作物生长机制
var update_timer: float = 0.0
var update_interval: float = 0.5
func _physics_process(delta):
update_timer += delta
#当作物成熟后(一个一秒钟计时器)
if update_timer >= update_interval:
tip.text = "游戏自动保存剩余【"+str(save_time)+"】秒"
save_time -= 1
if save_time < 0:
_save_game()
save_time = 10
pass
for i in range(len(farm_lots)):
var lot = farm_lots[i]
if lot["is_planted"]:
lot["grow_time"] += grow_speed * update_interval
if lot["grow_time"] >= lot["max_grow_time"]:
lot["grow_time"] = lot["max_grow_time"]
blink_counter += blink_speed * update_interval
is_blink_on = int(blink_counter) % 2 == 0
else:
is_blink_on = false
blink_counter = 0.0
#_update_farm_lots() # 更新地块信息
update_timer = 0.0 # 重置计时器
func _on_dig_button_pressed():
if money < dig_money:
print("金钱不足,无法开垦" )
toast.Toast("金钱不足,无法开垦", Color.RED)
else:
money -= dig_money
farm_lots[dig_index]["is_diged"] = true
land_panel.hide()
_update_ui()
_update_farm_lots()
pass
# 保存游戏数据
func _save_game():
# 创建一个字典来保存游戏状态
var save_data = {
"money": money,
"experience": experience,
"level": level,
"farm_lots": farm_lots
}
write_txt_file(game_path, str(save_data), false)
# 将字典写入文件
# 加载游戏数据
func _load_game():
pass
## 读取字典
#var save_data = JSON.parse_string(read_txt_file(game_path))
##print(read_json_file("C:/Users/shumengya/Desktop/smyfarm/save.txt"))
#
#money = save_data["money"]
#experience = save_data["experience"]
#level = save_data["level"]
#farm_lots = save_data["farm_lots"]
##file.close()
#toast.Toast("游戏已加载!", Color.GREEN)
#_update_ui()
#_update_farm_lots()
#_init_crop_list2()
# 添加按键触发保存和加载的功能
func _input(event):
if event.is_action_pressed("ui_save"): # 需要在输入设置中定义这个动作
_save_game()
elif event.is_action_pressed("ui_load"): # 需要在输入设置中定义这个动作
_load_game()
# 写入 TXT 文件
func write_txt_file(file_path: String, text: String, append: bool = false) -> void:
var file
if append == true:
file = FileAccess.open(file_path, FileAccess.READ_WRITE) # 追加模式
if file:
file.seek_end() # 移动光标到文件末尾
else:
file = FileAccess.open(file_path, FileAccess.WRITE) # 覆盖模式
if file:
file.store_string(text)
file.close()
toast.Toast("游戏已保存!", Color.GREEN)
else:
print("写入文件时打开失败: ", file_path)
toast.Toast("写入文件时打开失败!", Color.RED)
# 读取 TXT 文件
func read_txt_file(file_path: String) -> String:
var file = FileAccess.open(file_path, FileAccess.READ)
if file:
var text = file.get_as_text()
file.close()
return text
else:
print("打开文件失败: ", file_path)
return ""
func random_probability(probability: float) -> bool:
# 确保传入的概率值在 0 到 1 之间
if probability*0.001 < 0.0 or probability*0.001 > 1.0:
print("概率值必须在 0 和 1 之间")
return false
# 生成一个 0 到 1 之间的随机数
var random_value = randf()
# 如果随机数小于等于概率值,则返回 true
return random_value <= (probability*0.001)
#这里处理登录逻辑如果用户没有账号直接注册一个新的json文件
func _on_login_button_pressed():
var user_name = username_input.text
var user_password = password_input.text
if(username_input == " " or password_input == " "):
print("用户名或密码不能为空!")
pass
else :
#这里处理登录逻辑
pass
pass
# 在线程中执行的函数
func _thread_update_farm_lots(data):
while true:
_update_farm_lots() # 更新地块信息
# 控制更新频率
OS.delay_msec(1000)