commit d91b6b9f1b7b25b7b1acbfc99b12de9dd6b55099 Author: 树萌芽 <3205788256@qq.com> Date: Tue Dec 3 21:35:56 2024 +0800 初始化提交 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dfe8a02 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# Godot-specific files +.import/ +.godot/ +.mono/ +export.cfg +export_presets.cfg + +# System-specific files +.DS_Store +Thumbs.db + +# IDE-specific files +.vscode/ +.idea/ \ No newline at end of file diff --git a/LoginPanel.gd b/LoginPanel.gd new file mode 100644 index 0000000..8ebde81 --- /dev/null +++ b/LoginPanel.gd @@ -0,0 +1,19 @@ +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 diff --git a/SMY_ProgressBar.gd b/SMY_ProgressBar.gd new file mode 100644 index 0000000..ac34bed --- /dev/null +++ b/SMY_ProgressBar.gd @@ -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) # 从绿色到淡蓝色的渐变 diff --git a/Toast.tscn b/Toast.tscn new file mode 100644 index 0000000..02b5588 --- /dev/null +++ b/Toast.tscn @@ -0,0 +1,16 @@ +[gd_scene load_steps=2 format=3 uid="uid://ffw2vjwnwvew"] + +[ext_resource type="Script" path="res://ToastShow.gd" id="1_0rpwy"] + +[node name="ToastShow" type="PanelContainer"] +offset_left = 469.0 +offset_top = 557.0 +offset_right = 533.0 +offset_bottom = 580.0 +size_flags_horizontal = 6 +size_flags_vertical = 4 +script = ExtResource("1_0rpwy") + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +text = "提示弹窗" diff --git a/ToastShow.gd b/ToastShow.gd new file mode 100644 index 0000000..e6af94e --- /dev/null +++ b/ToastShow.gd @@ -0,0 +1,22 @@ +extends PanelContainer + +@onready var label = $Label +var display_time = 4.0 # 显示的时间(秒) +var fade_duration = 1.0 # 渐隐时间(秒) + +func Toast(text: String, text_color: Color = Color.WHITE): + label.text = text + label.modulate = text_color + show() + modulate.a = 1 # 确保初始透明度为 1 + await get_tree().create_timer(display_time).timeout # 等待显示时间 + await fade_out() # 开始渐隐 + +func fade_out() -> void: + var fade_step = 1.0 / (fade_duration / 60) # 每帧减少的透明度 + while modulate.a > 0: + modulate.a -= fade_step + if modulate.a < 0: + modulate.a = 0 + await get_tree().create_timer(0).timeout # 等待下一帧 + hide() # 完全透明时隐藏面板 diff --git a/assets/GUI/black_blue_bar.tres b/assets/GUI/black_blue_bar.tres new file mode 100644 index 0000000..5be905f --- /dev/null +++ b/assets/GUI/black_blue_bar.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://bh73krj8mnojv"] + +[ext_resource type="Texture2D" uid="uid://ifyhhbct23mk" path="res://assets/c70d56.png" id="1_1diq2"] + +[resource] +atlas = ExtResource("1_1diq2") +region = Rect2(544, 440, 400, 88) diff --git a/assets/GUI/green_bar.tres b/assets/GUI/green_bar.tres new file mode 100644 index 0000000..84c09c5 --- /dev/null +++ b/assets/GUI/green_bar.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://b7yavo67sf4v7"] + +[ext_resource type="Texture2D" uid="uid://ifyhhbct23mk" path="res://assets/c70d56.png" id="1_hjs0s"] + +[resource] +atlas = ExtResource("1_hjs0s") +region = Rect2(72, 304, 400, 88) diff --git a/assets/GUI/orange_bar.tres b/assets/GUI/orange_bar.tres new file mode 100644 index 0000000..7a8aefc --- /dev/null +++ b/assets/GUI/orange_bar.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://bc0rsd5x4pxhn"] + +[ext_resource type="Texture2D" uid="uid://ifyhhbct23mk" path="res://assets/c70d56.png" id="1_yvofj"] + +[resource] +atlas = ExtResource("1_yvofj") +region = Rect2(72, 40, 400, 88) diff --git a/assets/GUI/pink_bar.tres b/assets/GUI/pink_bar.tres new file mode 100644 index 0000000..464ecbd --- /dev/null +++ b/assets/GUI/pink_bar.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://beckne13egl8u"] + +[ext_resource type="Texture2D" uid="uid://ifyhhbct23mk" path="res://assets/c70d56.png" id="1_sy611"] + +[resource] +atlas = ExtResource("1_sy611") +region = Rect2(544, 304, 400, 88) diff --git a/assets/GUI/red_bar.tres b/assets/GUI/red_bar.tres new file mode 100644 index 0000000..dd5af1d --- /dev/null +++ b/assets/GUI/red_bar.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://b73vvxnp31xs4"] + +[ext_resource type="Texture2D" uid="uid://ifyhhbct23mk" path="res://assets/c70d56.png" id="1_0raqg"] + +[resource] +atlas = ExtResource("1_0raqg") +region = Rect2(544, 40, 400, 88) diff --git a/assets/GUI/white_blue_bar.tres b/assets/GUI/white_blue_bar.tres new file mode 100644 index 0000000..03177f6 --- /dev/null +++ b/assets/GUI/white_blue_bar.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://d0h1s3wrx45a7"] + +[ext_resource type="Texture2D" uid="uid://ifyhhbct23mk" path="res://assets/c70d56.png" id="1_dylxy"] + +[resource] +atlas = ExtResource("1_dylxy") +region = Rect2(72, 440, 400, 88) diff --git a/assets/UI/441923.png b/assets/UI/441923.png new file mode 100644 index 0000000..f5e9fa4 Binary files /dev/null and b/assets/UI/441923.png differ diff --git a/assets/UI/441923.png.import b/assets/UI/441923.png.import new file mode 100644 index 0000000..f8c5633 --- /dev/null +++ b/assets/UI/441923.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dq7syuj3tce0q" +path="res://.godot/imported/441923.png-3f79c2537dd7b8eca473851fcc8bf87f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/UI/441923.png" +dest_files=["res://.godot/imported/441923.png-3f79c2537dd7b8eca473851fcc8bf87f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/background1.jpg b/assets/background1.jpg new file mode 100644 index 0000000..e2d0fce Binary files /dev/null and b/assets/background1.jpg differ diff --git a/assets/background1.jpg.import b/assets/background1.jpg.import new file mode 100644 index 0000000..323cc5a --- /dev/null +++ b/assets/background1.jpg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cb83k0nvx8tox" +path="res://.godot/imported/background1.jpg-f48c6b61852da31f553d6c26788ce9fc.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/background1.jpg" +dest_files=["res://.godot/imported/background1.jpg-f48c6b61852da31f553d6c26788ce9fc.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/background2.jpg b/assets/background2.jpg new file mode 100644 index 0000000..ebc0778 Binary files /dev/null and b/assets/background2.jpg differ diff --git a/assets/background2.jpg.import b/assets/background2.jpg.import new file mode 100644 index 0000000..1c1f6d9 --- /dev/null +++ b/assets/background2.jpg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cbjtfrej7iq3x" +path="res://.godot/imported/background2.jpg-20d3edd96b3e306665c2220bbd10aa5d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/background2.jpg" +dest_files=["res://.godot/imported/background2.jpg-20d3edd96b3e306665c2220bbd10aa5d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/c70d56.png b/assets/c70d56.png new file mode 100644 index 0000000..5489392 Binary files /dev/null and b/assets/c70d56.png differ diff --git a/assets/c70d56.png.import b/assets/c70d56.png.import new file mode 100644 index 0000000..7777351 --- /dev/null +++ b/assets/c70d56.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ifyhhbct23mk" +path="res://.godot/imported/c70d56.png-d78d984f7c4168eec78b8461caaf33c5.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/c70d56.png" +dest_files=["res://.godot/imported/c70d56.png-d78d984f7c4168eec78b8461caaf33c5.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000..2a0b8e2 Binary files /dev/null and b/assets/logo.png differ diff --git a/assets/logo.png.import b/assets/logo.png.import new file mode 100644 index 0000000..f8d4595 --- /dev/null +++ b/assets/logo.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://e4oyt5ubyyoa" +path="res://.godot/imported/logo.png-e2220799298e3631eb0e245316e0501a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/logo.png" +dest_files=["res://.godot/imported/logo.png-e2220799298e3631eb0e245316e0501a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/logo2.png b/assets/logo2.png new file mode 100644 index 0000000..b33c17e Binary files /dev/null and b/assets/logo2.png differ diff --git a/assets/logo2.png.import b/assets/logo2.png.import new file mode 100644 index 0000000..b1c7434 --- /dev/null +++ b/assets/logo2.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://blq6shccnpcot" +path="res://.godot/imported/logo2.png-f18f20dd4e7285725c88c4c18bf113df.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/logo2.png" +dest_files=["res://.godot/imported/logo2.png-f18f20dd4e7285725c88c4c18bf113df.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/tu.jpg b/assets/tu.jpg new file mode 100644 index 0000000..8813093 Binary files /dev/null and b/assets/tu.jpg differ diff --git a/assets/tu.jpg.import b/assets/tu.jpg.import new file mode 100644 index 0000000..cb74549 --- /dev/null +++ b/assets/tu.jpg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bo5oinxbn65rw" +path="res://.godot/imported/tu.jpg-3b6c678774d2deb9a41cc1bb693d8351.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/tu.jpg" +dest_files=["res://.godot/imported/tu.jpg-3b6c678774d2deb9a41cc1bb693d8351.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/crop_item.tscn b/crop_item.tscn new file mode 100644 index 0000000..5ac38eb --- /dev/null +++ b/crop_item.tscn @@ -0,0 +1,36 @@ +[gd_scene load_steps=3 format=3 uid="uid://bkivlkirrx6u8"] + +[ext_resource type="Texture2D" uid="uid://bo5oinxbn65rw" path="res://assets/tu.jpg" id="1_stl1w"] +[ext_resource type="Script" path="res://SMY_ProgressBar.gd" id="2_1n4xp"] + +[node name="CropItem" type="Button"] +custom_minimum_size = Vector2(100, 100) +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="background" type="Sprite2D" parent="."] +position = Vector2(50.15, 49.975) +scale = Vector2(0.147923, 0.156084) +texture = ExtResource("1_stl1w") + +[node name="ProgressBar" type="ProgressBar" parent="."] +layout_mode = 2 +offset_top = 86.0 +offset_right = 495.0 +offset_bottom = 159.0 +scale = Vector2(0.2, 0.2) +theme_override_font_sizes/font_size = 50 +script = ExtResource("2_1n4xp") + +[node name="crop_sprite" type="AnimatedSprite2D" parent="."] + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +offset_right = 250.0 +offset_bottom = 55.0 +scale = Vector2(0.4, 0.4) +size_flags_horizontal = 3 +theme_override_font_sizes/font_size = 40 +text = "[普通-超萝卜]" +horizontal_alignment = 1 +vertical_alignment = 1 diff --git a/farm.gd b/farm.gd new file mode 100644 index 0000000..ca3441c --- /dev/null +++ b/farm.gd @@ -0,0 +1,998 @@ +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 +#Thread +@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/VBox/HBox/username_input +#用户登录密码 +@onready var password_input = $LoginPanel/VBox/HBox2/password_input +#注册账号时二次确认密码 +@onready var password_input_2 = $LoginPanel/VBox/HBox5/password_input2 +#登录按钮 +@onready var login_button = $LoginPanel/VBox/HBox4/login_button +#注册按钮 +@onready var register_button = $LoginPanel/VBox/HBox4/register_button +#农场名称 +@onready var farmname_input = $LoginPanel/VBox/HBox3/farmname_input +#登录注册面板 +@onready var login_panel = $LoginPanel +#----------------网络联机部分-------------------------- +@onready var tip = $tip + +@onready var http_request = $HTTPRequest + +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 # 当前被选择的地块索引 +#电脑版保存路径 +var game_path = "C:/Users/shumengya/Desktop/smyfarm/" +var save_time = 10 + +# 使用 _process 计时器实现作物生长机制 +var update_timer: float = 0.0 +var update_interval: float = 1.0 +var start_game = false + +var user_name = "" +var user_password = "" +var farmname = "" +var login_data = {} + +var data = null + +var buttons = [] + +# 准备阶段 +func _ready(): + + + + _update_ui() + _init_crop_list2() + toast.Toast("快去偷其他人的菜吧!", Color.GREEN) + # 初始化农场地块 + _init_farm_lots(40) + _update_farm_lots() + + crop_grid_container.hide() + + # 更新初始显示 + + +# 初始化农场地块 +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_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] + + # 只显示当前等级可以种植的作物 + if crop["等级"] <= level: + var level_btn = _create_crop_button(crop_name, crop["品质"]) + crop_grid_container.add_child(level_btn) + + + + + +# 更新农场地块状态到 GridContainer +func _update_farm_lots(): # 每一秒更新一次状态 + # 清空当前显示的地块 + for child in grid_container.get_children(): + child.queue_free() + + var digged_count = 0 # 统计已开垦地块的数量 + + 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") + + if lot["is_diged"]: + digged_count += 1 # 增加已开垦地块计数 + if lot["is_planted"]: + # 寒冷环境配置,作物随机概率死亡 + climate_death_timer += 1 + if climate_death_timer >= 60: + if random_probability(can_planted_crop[lot["crop_type"]]["耐候性"]): + lot["is_dead"] = true + climate_death_timer = 0 + + # 如果作物已死亡 + if lot["is_dead"]: + print("[" + farm_lots[i]["crop_type"] + "]" + "已死亡!") + label.modulate = Color.NAVY_BLUE + label.text = "[" + farm_lots[i]["crop_type"] + "已死亡" + "]" + else: + # 正常生长逻辑 + var crop_name = lot["crop_type"] + label.text = "[" + can_planted_crop[crop_name]["品质"] + "-" + lot["crop_type"] + "]" + # 根据品质显示颜色 + match can_planted_crop[crop_name]["品质"]: + "普通": + label.modulate = Color.GAINSBORO + "优良": + label.modulate = Color.DODGER_BLUE + "稀有": + label.modulate = Color.PURPLE + "史诗": + label.modulate = Color.YELLOW + "传奇": + label.modulate = Color.ORANGE_RED + + progressbar.show() + progressbar.max_value = int(lot["max_grow_time"]) + progressbar.set_target_value(int(lot["grow_time"])) + else: + # 已开垦但未种植的地块显示为空地 + label.modulate = Color.GREEN + label.text = "[" + "空地" + "]" + progressbar.hide() + else: + # 未开垦的地块 + label.modulate = Color.WEB_GRAY + label.text = "[" + "未开垦" + "]" + progressbar.hide() + + # 连接按钮点击事件 + button.connect("pressed", Callable(self, "_on_item_selected").bind(i)) + grid_container.add_child(button) + + # 根据已开垦地块数量更新 dig_money + dig_money = digged_count * 1000 + dig_button.text = "开垦" + "[" + str(dig_money) + "]" + + +# 更新玩家信息显示 +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) + 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() + +# 收获作物 +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() + + + +func _physics_process(delta): + update_timer += delta + + if update_timer >= update_interval: + update_timer = 0.0 # 重置计时器 + if start_game == true: + _update_save_time() + _update_farm_lots() + pass + + + for i in range(len(farm_lots)): + var lot = farm_lots[i] + if lot["is_planted"]: + lot["grow_time"] += grow_speed * update_interval + _update_blinking(lot) + + + + +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 = { + #"user_name":username_input.text, + #"user_password":password_input.text, + #"farm_name":farmname_input.text, + #"money": money, + #"experience": experience, + #"level": level, + #"farm_lots": farm_lots + #} + #write_txt_file(game_path+username_input.text+".txt", str(save_data), false) + ## 将字典写入文件 + save_game_to_server() + +# 加载游戏数据 +func _load_game(): + + ## 从本地读取字典 + #var save_data = JSON.parse_string(read_txt_file(game_path+username_input.text+".txt")) + #money = save_data["money"] + #experience = save_data["experience"] + #level = save_data["level"] + #farm_lots = save_data["farm_lots"] + + load_game_from_server() + + 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 "false" + + +func random_probability(probability: float) -> bool: + # 确保传入的概率值在 0 到 1 之间 + if probability*0.001 < 0.0 or probability*0.001 > 1.0: + print("概率值必须在 0 和 1 之间") + return false + + # 生成一个 0 到 1 之间的随机数 + var random_value = randf() + + # 如果随机数小于等于概率值,则返回 true + return random_value <= (probability*0.001) + + +#这里处理登录逻辑,如果用户没有账号,直接注册一个新的 +func _on_login_button_pressed(): + + user_name = username_input.text.strip_edges() # 修剪前后的空格 + user_password = password_input.text.strip_edges() + farmname = farmname_input.text.strip_edges() + + login_data = { + "user_name": user_name, + "user_password": user_password + } + + if user_name == "" or user_password == "": + print("用户名或密码不能为空!") + return + + send_request("login", HTTPClient.METHOD_POST, login_data) + +func _on_register_button_pressed(): + user_name = username_input.text.strip_edges() + user_password = password_input.text.strip_edges() + + var user_password_2 = password_input_2.text.strip_edges() + farmname = farmname_input.text.strip_edges() + + var init_player_data = { + "experience": 0, + "farm_lots": [ + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": true, + "is_planted": false, + "max_grow_time": 3 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": true, + "is_planted": false, + "max_grow_time": 3 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": true, + "is_planted": false, + "max_grow_time": 3 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": true, + "is_planted": false, + "max_grow_time": 3 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": true, + "is_planted": false, + "max_grow_time": 3 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": false, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": true, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": true, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": true, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": true, + "is_planted": false, + "max_grow_time": 5 + }, + { + "crop_type": "", + "grow_time": 0, + "is_dead": false, + "is_diged": true, + "is_planted": false, + "max_grow_time": 5 + } + ], + "farm_name": farmname, + "level": 0, + "money": 1000, + "user_name": user_name, + "user_password": user_password +} + + if user_name == "" or user_password == "": + print("用户名或密码不能为空!") + return + if farmname == "": + print("农场名称不能为空!") + return + if user_password != user_password_2: + print("前后密码不相同!") + return + + if is_valid_qq_number(user_name) == false: + return + + send_request("register", HTTPClient.METHOD_POST, init_player_data) + pass + + +func _update_save_time(): + tip.text = "游戏自动保存剩余【"+str(save_time)+"】秒" + save_time -= 1 + if save_time < 0: + _save_game() + save_time = 10 + pass + pass + +func _create_crop_button(crop_name: String, crop_quality: String) -> Button: + # 根据品质选择相应的进度条 + var button = null + match crop_quality: + "普通": + button = green_bar.duplicate() + "优良": + button = white_blue_bar.duplicate() + "稀有": + button = orange_bar.duplicate() + "史诗": + button = pink_bar.duplicate() + "传奇": + button = black_blue_bar.duplicate() + + # 添加按钮事件 + button.connect("pressed", Callable(self, "_on_crop_selected").bind(crop_name)) + button.text = str(crop_name) + return button + + +func _update_blinking(lot: Dictionary): + 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 + + +# 保存玩家数据到node.js后端 +func save_game_to_server(): + var player_data = { + "user_name":user_name, + "user_password":user_password, + "farm_name":farmname, + "money": money, + "experience": experience, + "level": level, + "farm_lots": farm_lots + } + + send_request("save", HTTPClient.METHOD_POST, player_data) + pass + +# 加载玩家数据从node.js后端 +func load_game_from_server(): + send_request("login", HTTPClient.METHOD_POST, login_data) + pass + +func send_request(endpoint: String, method: int, data: Dictionary = {}): + var http_request = HTTPRequest.new() + add_child(http_request) + http_request.request_completed.connect(self._on_request_completed) + + var json_body = JSON.stringify(data) + var headers = ["Content-Type: application/json"] + var error = http_request.request("http://localhost:3000/" + endpoint, headers, method, json_body) + if error != OK: + push_error("请求失败: %s" % str(error)) + else: + #print("请求已发送: ", endpoint, json_body) + pass + +func _on_request_completed(result, response_code, headers, body): + var response_text = body.get_string_from_utf8() + #print("返回 code: %d" % response_code) + #print("返回 body: %s" % response_text) + + var json = JSON.new() + var parse_result = json.parse(response_text) + + if parse_result == OK: + var parsed_data = json.get_data() + data = parsed_data # 将解析后的数据赋值给 data + #print("解析成功: ", data) + + if data["message"] == "登录成功": + print("登录成功") + if data.has("data"): + var user_data = data["data"] + #print("用户数据: ", user_data) + experience = user_data.get("experience", 0) + farm_lots = user_data.get("farm_lots", []) + level = user_data.get("level", 1) + money = user_data.get("money", 0) + farmname_input.text = user_data.get("farm_name", 0) + start_game = true + login_panel.hide() + # 确保在更新数据后调用 UI 更新函数 + _update_ui() + _update_farm_lots() + + + elif data["message"] == "密码错误": + printerr("密码错误") + pass + elif data["message"] == "服务器错误": + if data.has("error"): + printerr("服务器错误"+str(data["error"])) + pass + elif data["message"] == "用户不存在": + printerr("用户不存在") + elif data["message"] == "注册成功": + print("注册成功") + {"user_name": user_name,"user_password": user_password} + send_request("login", HTTPClient.METHOD_POST, {"user_name": user_name,"user_password": user_password}) + elif data["message"] == "用户名已存在": + printerr("用户名已存在") + + + + else: + print("JSON 解析错误: ", json.get_error_message()) + +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: + print("格式错误,请输入正确的QQ号码!") + return false + + return qq_regex.search(qq_number) != null + diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..3fe4f4a --- /dev/null +++ b/icon.svg @@ -0,0 +1 @@ + diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..d568bad --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://2sdfbvf1isif" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/login.gd b/login.gd new file mode 100644 index 0000000..b086158 --- /dev/null +++ b/login.gd @@ -0,0 +1,87 @@ +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 + diff --git a/main.gd b/main.gd new file mode 100644 index 0000000..fb3af9a --- /dev/null +++ b/main.gd @@ -0,0 +1,615 @@ +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) diff --git a/main.tscn b/main.tscn new file mode 100644 index 0000000..a1dc2d7 --- /dev/null +++ b/main.tscn @@ -0,0 +1,339 @@ +[gd_scene load_steps=11 format=3 uid="uid://dgh61dttaas5a"] + +[ext_resource type="Script" path="res://farm.gd" id="1_h7dqo"] +[ext_resource type="Texture2D" uid="uid://cbjtfrej7iq3x" path="res://assets/background2.jpg" id="2_xrhqr"] +[ext_resource type="PackedScene" uid="uid://ffw2vjwnwvew" path="res://Toast.tscn" id="3_0cvam"] +[ext_resource type="PackedScene" uid="uid://bkivlkirrx6u8" path="res://crop_item.tscn" id="4_2mmkk"] +[ext_resource type="Texture2D" uid="uid://bc0rsd5x4pxhn" path="res://assets/GUI/orange_bar.tres" id="5_4fqlq"] +[ext_resource type="Texture2D" uid="uid://b7yavo67sf4v7" path="res://assets/GUI/green_bar.tres" id="5_knm2j"] +[ext_resource type="Texture2D" uid="uid://d0h1s3wrx45a7" path="res://assets/GUI/white_blue_bar.tres" id="6_h5nbu"] +[ext_resource type="Texture2D" uid="uid://beckne13egl8u" path="res://assets/GUI/pink_bar.tres" id="8_na6c6"] +[ext_resource type="Texture2D" uid="uid://bh73krj8mnojv" path="res://assets/GUI/black_blue_bar.tres" id="9_7l4jv"] +[ext_resource type="Texture2D" uid="uid://b73vvxnp31xs4" path="res://assets/GUI/red_bar.tres" id="10_10s87"] + +[node name="main" type="Node"] +script = ExtResource("1_h7dqo") + +[node name="background" type="Sprite2D" parent="."] +position = Vector2(576, 322.5) +scale = Vector2(0.658482, 0.666992) +texture = ExtResource("2_xrhqr") + +[node name="ItemList" type="ItemList" parent="."] +visible = false +offset_left = 80.0 +offset_top = 156.0 +offset_right = 1050.0 +offset_bottom = 606.0 +scale = Vector2(1.02983, 1.02983) +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 20 +allow_reselect = true +allow_rmb_select = true +auto_height = true +max_columns = 100 +same_column_width = true +fixed_column_width = 100 +icon_mode = 0 + +[node name="money" type="Label" parent="."] +offset_left = 1.0 +offset_right = 142.0 +offset_bottom = 42.0 +theme_override_font_sizes/font_size = 20 +text = "钱币:999" + +[node name="experience" type="Label" parent="."] +offset_left = 334.0 +offset_right = 475.0 +offset_bottom = 42.0 +theme_override_font_sizes/font_size = 20 +text = "经验:999" + +[node name="level" type="Label" parent="."] +offset_left = 632.0 +offset_right = 773.0 +offset_bottom = 42.0 +theme_override_font_sizes/font_size = 20 +text = "等级:100" + +[node name="tip" type="Label" parent="."] +offset_left = 878.0 +offset_right = 1150.0 +offset_bottom = 42.0 +theme_override_colors/font_color = Color(1, 0, 1, 1) +theme_override_font_sizes/font_size = 20 +text = "游戏自动保存剩余【10】秒" + +[node name="GridContainer" type="GridContainer" parent="."] +custom_minimum_size = Vector2(100, 100) +offset_top = 143.0 +offset_right = 100.0 +offset_bottom = 243.0 +columns = 10 + +[node name="CropItem" parent="." instance=ExtResource("4_2mmkk")] +offset_left = -1000.0 +offset_right = -960.0 + +[node name="CropList" type="ItemList" parent="."] +visible = false +custom_minimum_size = Vector2(100, 100) +offset_left = 1.0 +offset_top = 41.0 +offset_right = 1152.0 +offset_bottom = 141.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 20 +allow_reselect = true +allow_rmb_select = true +max_columns = 8 +same_column_width = true +fixed_column_width = 222 +icon_mode = 0 + +[node name="ToastShow" parent="." instance=ExtResource("3_0cvam")] +visible = false +offset_top = 580.0 +offset_bottom = 603.0 + +[node name="ToastShow2" parent="." instance=ExtResource("3_0cvam")] +visible = false +offset_left = 1.0 +offset_top = 41.0 +offset_right = 65.0 +offset_bottom = 64.0 + +[node name="Land_Panel" type="PanelContainer" parent="."] +visible = false +offset_right = 108.0 +offset_bottom = 31.0 + +[node name="VBox" type="VBoxContainer" parent="Land_Panel"] +layout_mode = 2 + +[node name="Title" type="Label" parent="Land_Panel/VBox"] +layout_mode = 2 +text = "土地面板" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="HBox" type="HBoxContainer" parent="Land_Panel/VBox"] +layout_mode = 2 + +[node name="Dig_button" type="Button" parent="Land_Panel/VBox/HBox"] +layout_mode = 2 +text = "开垦" + +[node name="Description" type="Label" parent="Land_Panel/VBox/HBox"] +layout_mode = 2 +text = "土地需要开垦才能种植,开垦所需费用随玩家已开垦土地数量增多而增多" + +[node name="HBox2" type="HBoxContainer" parent="Land_Panel/VBox"] +visible = false +layout_mode = 2 + +[node name="Button" type="Button" parent="Land_Panel/VBox/HBox2"] +layout_mode = 2 +text = "升级" + +[node name="Description" type="Label" parent="Land_Panel/VBox/HBox2"] +layout_mode = 2 +text = "升级描述" + +[node name="HBox3" type="HBoxContainer" parent="Land_Panel/VBox"] +visible = false +layout_mode = 2 + +[node name="Button" type="Button" parent="Land_Panel/VBox/HBox3"] +layout_mode = 2 +text = "恢复" + +[node name="Description" type="Label" parent="Land_Panel/VBox/HBox3"] +layout_mode = 2 +text = "恢复描述" + +[node name="ScrollContainer" type="ScrollContainer" parent="."] +offset_left = 1.0 +offset_top = 42.0 +offset_right = 2065.0 +offset_bottom = 244.0 +scale = Vector2(0.5, 0.5) +horizontal_scroll_mode = 0 + +[node name="Crop_GridContainer" type="GridContainer" parent="ScrollContainer"] +layout_mode = 2 +columns = 5 + +[node name="Copy_Nodes" type="Node2D" parent="."] +position = Vector2(-1000, 0) + +[node name="Green" type="Button" parent="Copy_Nodes"] +offset_left = 1.0 +offset_top = 42.0 +offset_right = 409.0 +offset_bottom = 138.0 +theme_override_font_sizes/font_size = 40 +text = "普通" +icon = ExtResource("5_knm2j") +icon_alignment = 1 + +[node name="White_Blue" type="Button" parent="Copy_Nodes"] +offset_left = 1.0 +offset_top = 42.0 +offset_right = 409.0 +offset_bottom = 138.0 +theme_override_font_sizes/font_size = 40 +text = "稀有" +icon = ExtResource("6_h5nbu") +icon_alignment = 1 + +[node name="Orange" type="Button" parent="Copy_Nodes"] +offset_left = 1.0 +offset_top = 42.0 +offset_right = 409.0 +offset_bottom = 138.0 +theme_override_font_sizes/font_size = 40 +text = "优良" +icon = ExtResource("5_4fqlq") +icon_alignment = 1 + +[node name="Pink" type="Button" parent="Copy_Nodes"] +offset_left = 1.0 +offset_top = 42.0 +offset_right = 409.0 +offset_bottom = 138.0 +theme_override_font_sizes/font_size = 40 +text = "史诗" +icon = ExtResource("8_na6c6") +icon_alignment = 1 + +[node name="Black_Blue" type="Button" parent="Copy_Nodes"] +offset_left = 1.0 +offset_top = 42.0 +offset_right = 409.0 +offset_bottom = 138.0 +theme_override_font_sizes/font_size = 40 +text = "传奇" +icon = ExtResource("9_7l4jv") +icon_alignment = 1 + +[node name="Red" type="Button" parent="Copy_Nodes"] +offset_left = 1.0 +offset_top = 92.0 +offset_right = 409.0 +offset_bottom = 188.0 +theme_override_font_sizes/font_size = 40 +text = "神话" +icon = ExtResource("10_10s87") +icon_alignment = 1 + +[node name="LoginPanel" type="Panel" parent="."] +offset_left = 300.0 +offset_top = 139.0 +offset_right = 686.0 +offset_bottom = 427.0 + +[node name="VBox" type="VBoxContainer" parent="LoginPanel"] +layout_mode = 0 +offset_top = 4.0 +offset_right = 386.0 +offset_bottom = 288.0 + +[node name="Title" type="Label" parent="LoginPanel/VBox"] +layout_mode = 2 +text = "登录/注册面板" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="HBox" type="HBoxContainer" parent="LoginPanel/VBox"] +layout_mode = 2 + +[node name="Label" type="Label" parent="LoginPanel/VBox/HBox"] +layout_mode = 2 +text = "账号" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="username_input" type="LineEdit" parent="LoginPanel/VBox/HBox"] +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "请输入QQ号..." +metadata/_edit_use_anchors_ = true + +[node name="HBox2" type="HBoxContainer" parent="LoginPanel/VBox"] +layout_mode = 2 + +[node name="Label2" type="Label" parent="LoginPanel/VBox/HBox2"] +layout_mode = 2 +text = "密码" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="password_input" type="LineEdit" parent="LoginPanel/VBox/HBox2"] +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "请输入密码..." + +[node name="Title3" type="Label" parent="LoginPanel/VBox"] +layout_mode = 2 +text = "以下为注册填写内容" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="HBox5" type="HBoxContainer" parent="LoginPanel/VBox"] +layout_mode = 2 + +[node name="Label2" type="Label" parent="LoginPanel/VBox/HBox5"] +layout_mode = 2 +text = "密码[选填]" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="password_input2" type="LineEdit" parent="LoginPanel/VBox/HBox5"] +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "请再次输入密码(登录不需要)..." + +[node name="HBox3" type="HBoxContainer" parent="LoginPanel/VBox"] +layout_mode = 2 + +[node name="Label" type="Label" parent="LoginPanel/VBox/HBox3"] +layout_mode = 2 +text = "名称[选填]" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="farmname_input" type="LineEdit" parent="LoginPanel/VBox/HBox3"] +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "请输入您的农场名称(登录不需要)..." +metadata/_edit_use_anchors_ = true + +[node name="HBox4" type="HBoxContainer" parent="LoginPanel/VBox"] +layout_mode = 2 + +[node name="login_button" type="Button" parent="LoginPanel/VBox/HBox4"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "登录" + +[node name="register_button" type="Button" parent="LoginPanel/VBox/HBox4"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "注册" + +[node name="Title2" type="Label" parent="LoginPanel/VBox"] +layout_mode = 2 +text = "注意:账号请输入您的QQ号,方便匹配QQ好友, +账号,密码请不要和您的QQ密码相同,防止信息泄露" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="HTTPRequest" type="HTTPRequest" parent="."] + +[connection signal="pressed" from="Land_Panel/VBox/HBox/Dig_button" to="." method="_on_dig_button_pressed"] +[connection signal="pressed" from="LoginPanel/VBox/HBox4/login_button" to="." method="_on_login_button_pressed"] +[connection signal="pressed" from="LoginPanel/VBox/HBox4/register_button" to="." method="_on_register_button_pressed"] diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..e68f717 --- /dev/null +++ b/project.godot @@ -0,0 +1,42 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="萌芽农场" +config/description="一款支持多人联机的农场游戏" +run/main_scene="res://main.tscn" +config/features=PackedStringArray("4.2", "Mobile") +config/icon="res://assets/logo2.png" + +[display] + +window/size/resizable=false +window/stretch/mode="viewport" +window/stretch/aspect="ignore" +window/per_pixel_transparency/allowed=true +window/vsync/vsync_mode=0 + +[input] + +ui_save={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null) +] +} +ui_load={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":76,"key_label":0,"unicode":108,"echo":false,"script":null) +] +} + +[rendering] + +renderer/rendering_method="mobile" diff --git a/shaders/CropProgress.gdshader b/shaders/CropProgress.gdshader new file mode 100644 index 0000000..9036749 --- /dev/null +++ b/shaders/CropProgress.gdshader @@ -0,0 +1,8 @@ +shader_type canvas_item; + +uniform vec4 fill_color; +uniform float progress; + +void fragment() { + +} diff --git a/test.gd b/test.gd new file mode 100644 index 0000000..61510e1 --- /dev/null +++ b/test.gd @@ -0,0 +1 @@ +extends Node