进一步完善服务器功能,添加远程命令系统,踢人系统
This commit is contained in:
@@ -85,5 +85,45 @@ offset_bottom = 79.25
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "刷新"
|
||||
|
||||
[node name="All_Filter" type="Button" parent="."]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
offset_left = 217.5
|
||||
offset_top = 12.5
|
||||
offset_right = 305.5
|
||||
offset_bottom = 75.5
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "全部"
|
||||
|
||||
[node name="Pet_Filter" type="Button" parent="."]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
offset_left = 310.0
|
||||
offset_top = 13.75
|
||||
offset_right = 398.0
|
||||
offset_bottom = 76.75
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "宠物"
|
||||
|
||||
[node name="Crop_Filter" type="Button" parent="."]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
offset_left = 397.5
|
||||
offset_top = 13.75
|
||||
offset_right = 485.5
|
||||
offset_bottom = 76.75
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "作物"
|
||||
|
||||
[node name="Farm_Filter" type="Button" parent="."]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
offset_left = 485.0
|
||||
offset_top = 13.75
|
||||
offset_right = 573.0
|
||||
offset_bottom = 76.75
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "农场"
|
||||
|
||||
[connection signal="pressed" from="QuitButton" to="." method="_on_quit_button_pressed"]
|
||||
[connection signal="pressed" from="RefreshButton" to="." method="_on_refresh_button_pressed"]
|
||||
[connection signal="pressed" from="All_Filter" to="." method="_on_all_filter_pressed"]
|
||||
[connection signal="pressed" from="Pet_Filter" to="." method="_on_pet_filter_pressed"]
|
||||
[connection signal="pressed" from="Crop_Filter" to="." method="_on_crop_filter_pressed"]
|
||||
[connection signal="pressed" from="Farm_Filter" to="." method="_on_farm_filter_pressed"]
|
||||
|
||||
@@ -15,7 +15,6 @@ corner_detail = 20
|
||||
shadow_size = 20
|
||||
|
||||
[node name="ItemStorePanel" type="Panel"]
|
||||
visible = false
|
||||
offset_left = 58.0
|
||||
offset_top = 79.0
|
||||
offset_right = 1598.0
|
||||
@@ -87,4 +86,48 @@ offset_bottom = 75.5
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "刷新"
|
||||
|
||||
[node name="All_Filter" type="Button" parent="."]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
layout_mode = 2
|
||||
offset_left = 217.5
|
||||
offset_top = 12.5
|
||||
offset_right = 305.5
|
||||
offset_bottom = 75.5
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "全部"
|
||||
|
||||
[node name="Pet_Filter" type="Button" parent="."]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
layout_mode = 2
|
||||
offset_left = 310.0
|
||||
offset_top = 13.75
|
||||
offset_right = 398.0
|
||||
offset_bottom = 76.75
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "宠物"
|
||||
|
||||
[node name="Crop_Filter" type="Button" parent="."]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
layout_mode = 2
|
||||
offset_left = 397.5
|
||||
offset_top = 13.75
|
||||
offset_right = 485.5
|
||||
offset_bottom = 76.75
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "作物"
|
||||
|
||||
[node name="Farm_Filter" type="Button" parent="."]
|
||||
custom_minimum_size = Vector2(60, 60)
|
||||
layout_mode = 2
|
||||
offset_left = 485.0
|
||||
offset_top = 13.75
|
||||
offset_right = 573.0
|
||||
offset_bottom = 76.75
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "农场"
|
||||
|
||||
[connection signal="pressed" from="RefreshButton" to="." method="_on_refresh_button_pressed"]
|
||||
[connection signal="pressed" from="All_Filter" to="." method="_on_all_filter_pressed"]
|
||||
[connection signal="pressed" from="Pet_Filter" to="." method="_on_pet_filter_pressed"]
|
||||
[connection signal="pressed" from="Crop_Filter" to="." method="_on_crop_filter_pressed"]
|
||||
[connection signal="pressed" from="Farm_Filter" to="." method="_on_farm_filter_pressed"]
|
||||
|
||||
179
Scene/BigPanel/PlayGamePanel.tscn
Normal file
179
Scene/BigPanel/PlayGamePanel.tscn
Normal file
@@ -0,0 +1,179 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://jjlgdnoo8e52"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dvaah0n1ia1a3" path="res://Script/BigPanel/PlayGamePanel.gd" id="1_i6cj7"]
|
||||
[ext_resource type="Texture2D" uid="uid://ywdg7xgq7hm8" path="res://assets/装饰物图片/道具背包.webp" id="2_wlugc"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7i23t"]
|
||||
border_width_left = 15
|
||||
border_width_top = 15
|
||||
border_width_right = 15
|
||||
border_width_bottom = 15
|
||||
corner_detail = 20
|
||||
shadow_size = 20
|
||||
|
||||
[node name="PlayGamePanel" type="Panel"]
|
||||
offset_right = 1399.0
|
||||
offset_bottom = 720.0
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_7i23t")
|
||||
script = ExtResource("1_i6cj7")
|
||||
|
||||
[node name="Title" type="Label" parent="."]
|
||||
layout_mode = 0
|
||||
offset_top = 17.0
|
||||
offset_right = 1401.0
|
||||
offset_bottom = 86.0
|
||||
theme_override_colors/font_color = Color(0.560784, 1, 0, 1)
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 20
|
||||
theme_override_font_sizes/font_size = 50
|
||||
text = "玩玩小游戏"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 15.0
|
||||
offset_top = 88.0
|
||||
offset_right = 1384.0
|
||||
offset_bottom = 707.0
|
||||
horizontal_scroll_mode = 0
|
||||
|
||||
[node name="Grid" type="GridContainer" parent="ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
columns = 5
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="ScrollContainer/Grid"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="GameTitle" type="Label" parent="ScrollContainer/Grid/VBox"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 15
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "贪吃蛇"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Grid/VBox"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("2_wlugc")
|
||||
|
||||
[node name="Button" type="Button" parent="ScrollContainer/Grid/VBox"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "点击游玩"
|
||||
|
||||
[node name="VBox2" type="VBoxContainer" parent="ScrollContainer/Grid"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="GameTitle" type="Label" parent="ScrollContainer/Grid/VBox2"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 15
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "贪吃蛇"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Grid/VBox2"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("2_wlugc")
|
||||
|
||||
[node name="Button" type="Button" parent="ScrollContainer/Grid/VBox2"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "点击游玩"
|
||||
|
||||
[node name="VBox3" type="VBoxContainer" parent="ScrollContainer/Grid"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="GameTitle" type="Label" parent="ScrollContainer/Grid/VBox3"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 15
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "贪吃蛇"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Grid/VBox3"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("2_wlugc")
|
||||
|
||||
[node name="Button" type="Button" parent="ScrollContainer/Grid/VBox3"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "点击游玩"
|
||||
|
||||
[node name="VBox4" type="VBoxContainer" parent="ScrollContainer/Grid"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="GameTitle" type="Label" parent="ScrollContainer/Grid/VBox4"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 15
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "贪吃蛇"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Grid/VBox4"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("2_wlugc")
|
||||
|
||||
[node name="Button" type="Button" parent="ScrollContainer/Grid/VBox4"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "点击游玩"
|
||||
|
||||
[node name="VBox5" type="VBoxContainer" parent="ScrollContainer/Grid"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="GameTitle" type="Label" parent="ScrollContainer/Grid/VBox5"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 15
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "贪吃蛇"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Grid/VBox5"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("2_wlugc")
|
||||
|
||||
[node name="Button" type="Button" parent="ScrollContainer/Grid/VBox5"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "点击游玩"
|
||||
223
Scene/BigPanel/SpecialFarmPanel.tscn
Normal file
223
Scene/BigPanel/SpecialFarmPanel.tscn
Normal file
@@ -0,0 +1,223 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://byxhjyyaahs6q"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://ywdg7xgq7hm8" path="res://assets/装饰物图片/道具背包.webp" id="1_mv0g4"]
|
||||
[ext_resource type="Script" uid="uid://btm2je8pg7rgk" path="res://Script/BigPanel/SpecialFarmPanel.gd" id="1_n2mxy"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7i23t"]
|
||||
border_width_left = 15
|
||||
border_width_top = 15
|
||||
border_width_right = 15
|
||||
border_width_bottom = 15
|
||||
corner_detail = 20
|
||||
shadow_size = 20
|
||||
|
||||
[node name="SpecialFarmPanel" type="Panel"]
|
||||
offset_right = 1399.0
|
||||
offset_bottom = 720.0
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_7i23t")
|
||||
script = ExtResource("1_n2mxy")
|
||||
|
||||
[node name="QuitButton" type="Button" parent="."]
|
||||
custom_minimum_size = Vector2(80, 80)
|
||||
layout_mode = 0
|
||||
offset_left = 1303.0
|
||||
offset_top = 17.0
|
||||
offset_right = 1383.0
|
||||
offset_bottom = 97.0
|
||||
theme_override_font_sizes/font_size = 50
|
||||
text = "X"
|
||||
|
||||
[node name="Title" type="Label" parent="."]
|
||||
layout_mode = 0
|
||||
offset_top = 17.0
|
||||
offset_right = 1401.0
|
||||
offset_bottom = 86.0
|
||||
theme_override_colors/font_color = Color(0.560784, 1, 0, 1)
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 20
|
||||
theme_override_font_sizes/font_size = 50
|
||||
text = "神秘农场"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 15.0
|
||||
offset_top = 88.0
|
||||
offset_right = 1384.0
|
||||
offset_bottom = 707.0
|
||||
horizontal_scroll_mode = 0
|
||||
|
||||
[node name="Grid" type="GridContainer" parent="ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
columns = 5
|
||||
|
||||
[node name="FlowerFarm" type="VBoxContainer" parent="ScrollContainer/Grid"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="GameTitle" type="Label" parent="ScrollContainer/Grid/FlowerFarm"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 15
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "花卉农场"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Grid/FlowerFarm"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("1_mv0g4")
|
||||
|
||||
[node name="FlowerFarmButton" type="Button" parent="ScrollContainer/Grid/FlowerFarm"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "点击访问"
|
||||
|
||||
[node name="FruitFarm" type="VBoxContainer" parent="ScrollContainer/Grid"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="GameTitle" type="Label" parent="ScrollContainer/Grid/FruitFarm"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 15
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "瓜果飘香"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Grid/FruitFarm"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("1_mv0g4")
|
||||
|
||||
[node name="FruitFarmButton" type="Button" parent="ScrollContainer/Grid/FruitFarm"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "点击访问"
|
||||
|
||||
[node name="HybridFarm" type="VBoxContainer" parent="ScrollContainer/Grid"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="GameTitle" type="Label" parent="ScrollContainer/Grid/HybridFarm"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 15
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "杂交基地"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Grid/HybridFarm"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("1_mv0g4")
|
||||
|
||||
[node name="HybridFarmButton" type="Button" parent="ScrollContainer/Grid/HybridFarm"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "点击访问"
|
||||
|
||||
[node name="LuckyFarm" type="VBoxContainer" parent="ScrollContainer/Grid"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="GameTitle" type="Label" parent="ScrollContainer/Grid/LuckyFarm"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 15
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "幸运农场"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Grid/LuckyFarm"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("1_mv0g4")
|
||||
|
||||
[node name="LuckyFarmButton" type="Button" parent="ScrollContainer/Grid/LuckyFarm"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "点击访问"
|
||||
|
||||
[node name="RiceFarm" type="VBoxContainer" parent="ScrollContainer/Grid"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="GameTitle" type="Label" parent="ScrollContainer/Grid/RiceFarm"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 15
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "稻香"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Grid/RiceFarm"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("1_mv0g4")
|
||||
|
||||
[node name="RiceFarmButton" type="Button" parent="ScrollContainer/Grid/RiceFarm"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "点击访问"
|
||||
|
||||
[node name="WheatFarm" type="VBoxContainer" parent="ScrollContainer/Grid"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="GameTitle" type="Label" parent="ScrollContainer/Grid/WheatFarm"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/shadow_offset_x = 3
|
||||
theme_override_constants/shadow_offset_y = 3
|
||||
theme_override_constants/outline_size = 15
|
||||
theme_override_constants/shadow_outline_size = 15
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "小麦谷"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="ScrollContainer/Grid/WheatFarm"]
|
||||
layout_mode = 2
|
||||
texture = ExtResource("1_mv0g4")
|
||||
|
||||
[node name="WheatFarmButton" type="Button" parent="ScrollContainer/Grid/WheatFarm"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "点击访问"
|
||||
|
||||
[connection signal="pressed" from="QuitButton" to="." method="_on_quit_button_pressed"]
|
||||
[connection signal="pressed" from="ScrollContainer/Grid/FlowerFarm/FlowerFarmButton" to="." method="_on_flower_farm_button_pressed"]
|
||||
[connection signal="pressed" from="ScrollContainer/Grid/FruitFarm/FruitFarmButton" to="." method="_on_fruit_farm_button_pressed"]
|
||||
[connection signal="pressed" from="ScrollContainer/Grid/HybridFarm/HybridFarmButton" to="." method="_on_hybrid_farm_button_pressed"]
|
||||
[connection signal="pressed" from="ScrollContainer/Grid/LuckyFarm/LuckyFarmButton" to="." method="_on_lucky_farm_button_pressed"]
|
||||
[connection signal="pressed" from="ScrollContainer/Grid/RiceFarm/RiceFarmButton" to="." method="_on_rice_farm_button_pressed"]
|
||||
[connection signal="pressed" from="ScrollContainer/Grid/WheatFarm/WheatFarmButton" to="." method="_on_wheat_farm_button_pressed"]
|
||||
307
Scene/SmallGame/2048Game.gd
Normal file
307
Scene/SmallGame/2048Game.gd
Normal file
@@ -0,0 +1,307 @@
|
||||
extends Panel
|
||||
|
||||
# 游戏常量
|
||||
const GRID_SIZE = 4
|
||||
const CELL_SIZE = 90
|
||||
const CELL_MARGIN = 10
|
||||
|
||||
# 数字颜色配置
|
||||
const NUMBER_COLORS = {
|
||||
0: Color.TRANSPARENT,
|
||||
2: Color(0.93, 0.89, 0.85),
|
||||
4: Color(0.93, 0.88, 0.78),
|
||||
8: Color(0.95, 0.69, 0.47),
|
||||
16: Color(0.96, 0.58, 0.39),
|
||||
32: Color(0.96, 0.49, 0.37),
|
||||
64: Color(0.96, 0.37, 0.23),
|
||||
128: Color(0.93, 0.81, 0.45),
|
||||
256: Color(0.93, 0.80, 0.38),
|
||||
512: Color(0.93, 0.78, 0.31),
|
||||
1024: Color(0.93, 0.77, 0.25),
|
||||
2048: Color(0.93, 0.76, 0.18)
|
||||
}
|
||||
|
||||
const TEXT_COLORS = {
|
||||
2: Color.BLACK,
|
||||
4: Color.BLACK,
|
||||
8: Color.WHITE,
|
||||
16: Color.WHITE,
|
||||
32: Color.WHITE,
|
||||
64: Color.WHITE,
|
||||
128: Color.WHITE,
|
||||
256: Color.WHITE,
|
||||
512: Color.WHITE,
|
||||
1024: Color.WHITE,
|
||||
2048: Color.WHITE
|
||||
}
|
||||
|
||||
# 游戏变量
|
||||
var grid = []
|
||||
var score = 0
|
||||
var best_score = 0
|
||||
var game_over = false
|
||||
var won = false
|
||||
var can_continue = true
|
||||
|
||||
# 节点引用
|
||||
@onready var game_board = $GameBoard
|
||||
@onready var score_label = $ScoreLabel
|
||||
@onready var best_label = $BestLabel
|
||||
@onready var game_over_label = $GameOverLabel
|
||||
@onready var win_label = $WinLabel
|
||||
|
||||
func _ready():
|
||||
# 设置游戏板样式
|
||||
game_board.modulate = Color(0.7, 0.6, 0.5)
|
||||
|
||||
# 初始化游戏
|
||||
init_game()
|
||||
|
||||
func init_game():
|
||||
# 重置游戏状态
|
||||
game_over = false
|
||||
won = false
|
||||
can_continue = true
|
||||
score = 0
|
||||
|
||||
# 初始化网格
|
||||
grid.clear()
|
||||
for y in range(GRID_SIZE):
|
||||
var row = []
|
||||
for x in range(GRID_SIZE):
|
||||
row.append(0)
|
||||
grid.append(row)
|
||||
|
||||
# 添加两个初始数字
|
||||
add_random_number()
|
||||
add_random_number()
|
||||
|
||||
# 更新UI
|
||||
update_ui()
|
||||
hide_labels()
|
||||
|
||||
queue_redraw()
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventKey and event.pressed:
|
||||
if game_over:
|
||||
if event.keycode == KEY_R:
|
||||
init_game()
|
||||
return
|
||||
|
||||
if won and not can_continue:
|
||||
if event.keycode == KEY_C:
|
||||
can_continue = true
|
||||
win_label.visible = false
|
||||
return
|
||||
|
||||
# 移动控制
|
||||
var moved = false
|
||||
match event.keycode:
|
||||
KEY_UP, KEY_W:
|
||||
moved = move_up()
|
||||
KEY_DOWN, KEY_S:
|
||||
moved = move_down()
|
||||
KEY_LEFT, KEY_A:
|
||||
moved = move_left()
|
||||
KEY_RIGHT, KEY_D:
|
||||
moved = move_right()
|
||||
KEY_R:
|
||||
init_game()
|
||||
return
|
||||
|
||||
if moved:
|
||||
add_random_number()
|
||||
update_ui()
|
||||
check_game_state()
|
||||
queue_redraw()
|
||||
|
||||
func move_left() -> bool:
|
||||
var moved = false
|
||||
for y in range(GRID_SIZE):
|
||||
var row = grid[y].duplicate()
|
||||
var new_row = merge_line(row)
|
||||
if new_row != grid[y]:
|
||||
moved = true
|
||||
grid[y] = new_row
|
||||
return moved
|
||||
|
||||
func move_right() -> bool:
|
||||
var moved = false
|
||||
for y in range(GRID_SIZE):
|
||||
var row = grid[y].duplicate()
|
||||
row.reverse()
|
||||
var new_row = merge_line(row)
|
||||
new_row.reverse()
|
||||
if new_row != grid[y]:
|
||||
moved = true
|
||||
grid[y] = new_row
|
||||
return moved
|
||||
|
||||
func move_up() -> bool:
|
||||
var moved = false
|
||||
for x in range(GRID_SIZE):
|
||||
var column = []
|
||||
for y in range(GRID_SIZE):
|
||||
column.append(grid[y][x])
|
||||
|
||||
var new_column = merge_line(column)
|
||||
var changed = false
|
||||
for y in range(GRID_SIZE):
|
||||
if grid[y][x] != new_column[y]:
|
||||
changed = true
|
||||
grid[y][x] = new_column[y]
|
||||
|
||||
if changed:
|
||||
moved = true
|
||||
return moved
|
||||
|
||||
func move_down() -> bool:
|
||||
var moved = false
|
||||
for x in range(GRID_SIZE):
|
||||
var column = []
|
||||
for y in range(GRID_SIZE):
|
||||
column.append(grid[y][x])
|
||||
|
||||
column.reverse()
|
||||
var new_column = merge_line(column)
|
||||
new_column.reverse()
|
||||
|
||||
var changed = false
|
||||
for y in range(GRID_SIZE):
|
||||
if grid[y][x] != new_column[y]:
|
||||
changed = true
|
||||
grid[y][x] = new_column[y]
|
||||
|
||||
if changed:
|
||||
moved = true
|
||||
return moved
|
||||
|
||||
func merge_line(line: Array) -> Array:
|
||||
# 移除零
|
||||
var filtered = []
|
||||
for num in line:
|
||||
if num != 0:
|
||||
filtered.append(num)
|
||||
|
||||
# 合并相同数字
|
||||
var merged = []
|
||||
var i = 0
|
||||
while i < filtered.size():
|
||||
if i < filtered.size() - 1 and filtered[i] == filtered[i + 1]:
|
||||
# 合并
|
||||
var new_value = filtered[i] * 2
|
||||
merged.append(new_value)
|
||||
score += new_value
|
||||
i += 2
|
||||
else:
|
||||
merged.append(filtered[i])
|
||||
i += 1
|
||||
|
||||
# 填充零到指定长度
|
||||
while merged.size() < GRID_SIZE:
|
||||
merged.append(0)
|
||||
|
||||
return merged
|
||||
|
||||
func add_random_number():
|
||||
var empty_cells = []
|
||||
for y in range(GRID_SIZE):
|
||||
for x in range(GRID_SIZE):
|
||||
if grid[y][x] == 0:
|
||||
empty_cells.append(Vector2(x, y))
|
||||
|
||||
if empty_cells.size() > 0:
|
||||
var random_cell = empty_cells[randi() % empty_cells.size()]
|
||||
var value = 2 if randf() < 0.9 else 4
|
||||
grid[random_cell.y][random_cell.x] = value
|
||||
|
||||
func check_game_state():
|
||||
# 检查是否达到2048
|
||||
if not won:
|
||||
for y in range(GRID_SIZE):
|
||||
for x in range(GRID_SIZE):
|
||||
if grid[y][x] == 2048:
|
||||
won = true
|
||||
can_continue = false
|
||||
win_label.visible = true
|
||||
return
|
||||
|
||||
# 检查是否游戏结束
|
||||
if not can_move():
|
||||
game_over = true
|
||||
if score > best_score:
|
||||
best_score = score
|
||||
game_over_label.visible = true
|
||||
|
||||
func can_move() -> bool:
|
||||
# 检查是否有空格
|
||||
for y in range(GRID_SIZE):
|
||||
for x in range(GRID_SIZE):
|
||||
if grid[y][x] == 0:
|
||||
return true
|
||||
|
||||
# 检查是否可以合并
|
||||
for y in range(GRID_SIZE):
|
||||
for x in range(GRID_SIZE):
|
||||
var current = grid[y][x]
|
||||
# 检查右边
|
||||
if x < GRID_SIZE - 1 and grid[y][x + 1] == current:
|
||||
return true
|
||||
# 检查下面
|
||||
if y < GRID_SIZE - 1 and grid[y + 1][x] == current:
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func update_ui():
|
||||
score_label.text = "分数: " + str(score)
|
||||
best_label.text = "最高分: " + str(best_score)
|
||||
|
||||
func hide_labels():
|
||||
game_over_label.visible = false
|
||||
win_label.visible = false
|
||||
|
||||
func _draw():
|
||||
if not game_board:
|
||||
return
|
||||
|
||||
# 获取游戏板位置
|
||||
var board_pos = game_board.position
|
||||
|
||||
# 绘制网格背景
|
||||
for y in range(GRID_SIZE):
|
||||
for x in range(GRID_SIZE):
|
||||
var cell_x = board_pos.x + x * (CELL_SIZE + CELL_MARGIN) + CELL_MARGIN
|
||||
var cell_y = board_pos.y + y * (CELL_SIZE + CELL_MARGIN) + CELL_MARGIN
|
||||
var rect = Rect2(cell_x, cell_y, CELL_SIZE, CELL_SIZE)
|
||||
|
||||
# 绘制单元格背景
|
||||
draw_rect(rect, Color(0.8, 0.7, 0.6), true)
|
||||
|
||||
# 绘制数字
|
||||
var value = grid[y][x]
|
||||
if value > 0:
|
||||
# 绘制数字背景
|
||||
var bg_color = NUMBER_COLORS.get(value, Color.GOLD)
|
||||
draw_rect(rect, bg_color, true)
|
||||
|
||||
# 绘制数字文本
|
||||
var text = str(value)
|
||||
var font_size = 24 if value < 100 else (20 if value < 1000 else 16)
|
||||
var text_color = TEXT_COLORS.get(value, Color.WHITE)
|
||||
|
||||
# 获取默认字体
|
||||
var font = ThemeDB.fallback_font
|
||||
|
||||
# 计算文本尺寸
|
||||
var text_size = font.get_string_size(text, HORIZONTAL_ALIGNMENT_CENTER, -1, font_size)
|
||||
|
||||
# 计算文本位置(居中)
|
||||
var text_pos = Vector2(
|
||||
cell_x + (CELL_SIZE - text_size.x) / 2,
|
||||
cell_y + (CELL_SIZE - text_size.y) / 2 + text_size.y
|
||||
)
|
||||
|
||||
# 绘制文本
|
||||
draw_string(font, text_pos, text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color)
|
||||
1
Scene/SmallGame/2048Game.gd.uid
Normal file
1
Scene/SmallGame/2048Game.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://5dkxyuiuuhxk
|
||||
102
Scene/SmallGame/2048Game.tscn
Normal file
102
Scene/SmallGame/2048Game.tscn
Normal file
@@ -0,0 +1,102 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://dn0f1hjolxori"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://5dkxyuiuuhxk" path="res://Scene/SmallGame/2048Game.gd" id="1_4d5vb"]
|
||||
|
||||
[node name="2048Game" type="Panel"]
|
||||
offset_right = 1400.0
|
||||
offset_bottom = 720.0
|
||||
script = ExtResource("1_4d5vb")
|
||||
|
||||
[node name="GameBoard" type="Panel" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -200.0
|
||||
offset_top = -200.0
|
||||
offset_right = 200.0
|
||||
offset_bottom = 200.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="ScoreLabel" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 50.0
|
||||
offset_top = -100.0
|
||||
offset_right = 250.0
|
||||
offset_bottom = -70.0
|
||||
grow_vertical = 0
|
||||
text = "分数: 0"
|
||||
|
||||
[node name="BestLabel" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 50.0
|
||||
offset_top = -70.0
|
||||
offset_right = 250.0
|
||||
offset_bottom = -40.0
|
||||
grow_vertical = 0
|
||||
text = "最高分: 0"
|
||||
|
||||
[node name="GameOverLabel" type="Label" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -150.0
|
||||
offset_top = -50.0
|
||||
offset_right = 150.0
|
||||
offset_bottom = 50.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
text = "游戏结束
|
||||
按R重新开始"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="WinLabel" type="Label" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -150.0
|
||||
offset_top = -100.0
|
||||
offset_right = 150.0
|
||||
offset_bottom = -50.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
text = "恭喜!达到2048!
|
||||
按C继续游戏"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="ControlsLabel" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 3
|
||||
anchor_left = 1.0
|
||||
anchor_top = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -300.0
|
||||
offset_top = -150.0
|
||||
offset_right = -50.0
|
||||
offset_bottom = -50.0
|
||||
grow_horizontal = 0
|
||||
grow_vertical = 0
|
||||
text = "操作说明:
|
||||
WASD或方向键 - 移动
|
||||
R - 重新开始
|
||||
C - 继续游戏(达到2048后)"
|
||||
317
Scene/SmallGame/PushBox.gd
Normal file
317
Scene/SmallGame/PushBox.gd
Normal file
@@ -0,0 +1,317 @@
|
||||
extends Panel
|
||||
|
||||
# 游戏常量
|
||||
const CELL_SIZE = 40
|
||||
|
||||
# 地图元素
|
||||
enum CellType {
|
||||
EMPTY, # 空地
|
||||
WALL, # 墙壁
|
||||
TARGET, # 目标点
|
||||
BOX, # 箱子
|
||||
PLAYER, # 玩家
|
||||
BOX_ON_TARGET # 箱子在目标点上
|
||||
}
|
||||
|
||||
# 颜色配置
|
||||
const CELL_COLORS = {
|
||||
CellType.EMPTY: Color.WHITE,
|
||||
CellType.WALL: Color.DARK_GRAY,
|
||||
CellType.TARGET: Color.LIGHT_BLUE,
|
||||
CellType.BOX: Color.SADDLE_BROWN,
|
||||
CellType.PLAYER: Color.GREEN,
|
||||
CellType.BOX_ON_TARGET: Color.DARK_GREEN
|
||||
}
|
||||
|
||||
# 关卡数据
|
||||
const LEVELS = [
|
||||
# 关卡1 - 简单入门
|
||||
[
|
||||
"########",
|
||||
"#......#",
|
||||
"#..##..#",
|
||||
"#..#*..#",
|
||||
"#..#$..#",
|
||||
"#..@...#",
|
||||
"#......#",
|
||||
"########"
|
||||
],
|
||||
# 关卡2 - 两个箱子
|
||||
[
|
||||
"########",
|
||||
"#......#",
|
||||
"#.*$*..#",
|
||||
"#......#",
|
||||
"#..$...#",
|
||||
"#..@...#",
|
||||
"#......#",
|
||||
"########"
|
||||
],
|
||||
# 关卡3 - 稍微复杂
|
||||
[
|
||||
"##########",
|
||||
"#........#",
|
||||
"#..####..#",
|
||||
"#..*##*..#",
|
||||
"#..$$....#",
|
||||
"#........#",
|
||||
"#...@....#",
|
||||
"#........#",
|
||||
"##########"
|
||||
],
|
||||
# 关卡4 - 更复杂的布局
|
||||
[
|
||||
"############",
|
||||
"#..........#",
|
||||
"#..######..#",
|
||||
"#..*....#..#",
|
||||
"#..$....#..#",
|
||||
"#.......#..#",
|
||||
"#..#....#..#",
|
||||
"#..*....#..#",
|
||||
"#..$......@#",
|
||||
"#..........#",
|
||||
"############"
|
||||
]
|
||||
]
|
||||
|
||||
# 游戏变量
|
||||
var current_level = 0
|
||||
var level_data = []
|
||||
var player_pos = Vector2()
|
||||
var moves = 0
|
||||
var level_completed = false
|
||||
var map_width = 0
|
||||
var map_height = 0
|
||||
|
||||
# 节点引用
|
||||
@onready var game_area = $GameArea
|
||||
@onready var level_label = $LevelLabel
|
||||
@onready var moves_label = $MovesLabel
|
||||
@onready var win_label = $WinLabel
|
||||
|
||||
func _ready():
|
||||
# 设置游戏区域样式
|
||||
game_area.modulate = Color(0.9, 0.9, 0.9)
|
||||
|
||||
# 初始化游戏
|
||||
init_level()
|
||||
|
||||
func init_level():
|
||||
# 重置游戏状态
|
||||
level_completed = false
|
||||
moves = 0
|
||||
|
||||
# 加载当前关卡
|
||||
load_level(current_level)
|
||||
|
||||
# 更新UI
|
||||
update_ui()
|
||||
win_label.visible = false
|
||||
|
||||
queue_redraw()
|
||||
|
||||
func load_level(level_index: int):
|
||||
if level_index >= LEVELS.size():
|
||||
level_index = LEVELS.size() - 1
|
||||
|
||||
var level_strings = LEVELS[level_index]
|
||||
map_height = level_strings.size()
|
||||
map_width = level_strings[0].length()
|
||||
|
||||
# 初始化关卡数据
|
||||
level_data.clear()
|
||||
for y in range(map_height):
|
||||
var row = []
|
||||
for x in range(map_width):
|
||||
row.append(CellType.EMPTY)
|
||||
level_data.append(row)
|
||||
|
||||
# 解析关卡字符串
|
||||
for y in range(map_height):
|
||||
var line = level_strings[y]
|
||||
for x in range(line.length()):
|
||||
var char = line[x]
|
||||
match char:
|
||||
'#': # 墙壁
|
||||
level_data[y][x] = CellType.WALL
|
||||
'*': # 目标点
|
||||
level_data[y][x] = CellType.TARGET
|
||||
'$': # 箱子
|
||||
level_data[y][x] = CellType.BOX
|
||||
'@': # 玩家
|
||||
level_data[y][x] = CellType.PLAYER
|
||||
player_pos = Vector2(x, y)
|
||||
'+': # 箱子在目标点上
|
||||
level_data[y][x] = CellType.BOX_ON_TARGET
|
||||
'.': # 空地
|
||||
level_data[y][x] = CellType.EMPTY
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventKey and event.pressed:
|
||||
if level_completed:
|
||||
match event.keycode:
|
||||
KEY_N:
|
||||
next_level()
|
||||
KEY_R:
|
||||
init_level()
|
||||
return
|
||||
|
||||
# 移动控制
|
||||
var direction = Vector2.ZERO
|
||||
match event.keycode:
|
||||
KEY_UP, KEY_W:
|
||||
direction = Vector2(0, -1)
|
||||
KEY_DOWN, KEY_S:
|
||||
direction = Vector2(0, 1)
|
||||
KEY_LEFT, KEY_A:
|
||||
direction = Vector2(-1, 0)
|
||||
KEY_RIGHT, KEY_D:
|
||||
direction = Vector2(1, 0)
|
||||
KEY_R:
|
||||
init_level()
|
||||
return
|
||||
KEY_P:
|
||||
prev_level()
|
||||
return
|
||||
KEY_N:
|
||||
next_level()
|
||||
return
|
||||
|
||||
if direction != Vector2.ZERO:
|
||||
move_player(direction)
|
||||
|
||||
func move_player(direction: Vector2):
|
||||
var new_pos = player_pos + direction
|
||||
|
||||
# 检查边界
|
||||
if new_pos.x < 0 or new_pos.x >= map_width or new_pos.y < 0 or new_pos.y >= map_height:
|
||||
return
|
||||
|
||||
var target_cell = level_data[new_pos.y][new_pos.x]
|
||||
|
||||
# 检查是否撞墙
|
||||
if target_cell == CellType.WALL:
|
||||
return
|
||||
|
||||
# 检查是否推箱子
|
||||
if target_cell == CellType.BOX or target_cell == CellType.BOX_ON_TARGET:
|
||||
var box_new_pos = new_pos + direction
|
||||
|
||||
# 检查箱子新位置是否有效
|
||||
if box_new_pos.x < 0 or box_new_pos.x >= map_width or box_new_pos.y < 0 or box_new_pos.y >= map_height:
|
||||
return
|
||||
|
||||
var box_target_cell = level_data[box_new_pos.y][box_new_pos.x]
|
||||
|
||||
# 箱子不能推到墙上或其他箱子上
|
||||
if box_target_cell == CellType.WALL or box_target_cell == CellType.BOX or box_target_cell == CellType.BOX_ON_TARGET:
|
||||
return
|
||||
|
||||
# 移动箱子
|
||||
var was_on_target = (target_cell == CellType.BOX_ON_TARGET)
|
||||
var moving_to_target = (box_target_cell == CellType.TARGET)
|
||||
|
||||
# 更新箱子原位置
|
||||
if was_on_target:
|
||||
level_data[new_pos.y][new_pos.x] = CellType.TARGET
|
||||
else:
|
||||
level_data[new_pos.y][new_pos.x] = CellType.EMPTY
|
||||
|
||||
# 更新箱子新位置
|
||||
if moving_to_target:
|
||||
level_data[box_new_pos.y][box_new_pos.x] = CellType.BOX_ON_TARGET
|
||||
else:
|
||||
level_data[box_new_pos.y][box_new_pos.x] = CellType.BOX
|
||||
|
||||
# 移动玩家
|
||||
# 恢复玩家原位置(检查是否在目标点上)
|
||||
var level_strings = LEVELS[current_level]
|
||||
if player_pos.y < level_strings.size() and player_pos.x < level_strings[player_pos.y].length():
|
||||
var original_char = level_strings[player_pos.y][player_pos.x]
|
||||
if original_char == '*': # 玩家原来在目标点上
|
||||
level_data[player_pos.y][player_pos.x] = CellType.TARGET
|
||||
else:
|
||||
level_data[player_pos.y][player_pos.x] = CellType.EMPTY
|
||||
else:
|
||||
level_data[player_pos.y][player_pos.x] = CellType.EMPTY
|
||||
|
||||
# 更新玩家位置
|
||||
player_pos = new_pos
|
||||
level_data[player_pos.y][player_pos.x] = CellType.PLAYER
|
||||
|
||||
# 增加步数
|
||||
moves += 1
|
||||
|
||||
# 检查是否过关
|
||||
check_win_condition()
|
||||
|
||||
# 更新UI和重绘
|
||||
update_ui()
|
||||
queue_redraw()
|
||||
|
||||
func check_win_condition():
|
||||
# 检查是否所有箱子都在目标点上
|
||||
for y in range(map_height):
|
||||
for x in range(map_width):
|
||||
if level_data[y][x] == CellType.BOX:
|
||||
return # 还有箱子不在目标点上
|
||||
|
||||
# 所有箱子都在目标点上,过关!
|
||||
level_completed = true
|
||||
win_label.visible = true
|
||||
|
||||
func next_level():
|
||||
if current_level < LEVELS.size() - 1:
|
||||
current_level += 1
|
||||
init_level()
|
||||
|
||||
func prev_level():
|
||||
if current_level > 0:
|
||||
current_level -= 1
|
||||
init_level()
|
||||
|
||||
func update_ui():
|
||||
level_label.text = "关卡: " + str(current_level + 1)
|
||||
moves_label.text = "步数: " + str(moves)
|
||||
|
||||
func _draw():
|
||||
if not game_area:
|
||||
return
|
||||
|
||||
# 获取游戏区域位置
|
||||
var area_pos = game_area.position
|
||||
|
||||
# 计算起始绘制位置(居中)
|
||||
var start_x = area_pos.x + (game_area.size.x - map_width * CELL_SIZE) / 2
|
||||
var start_y = area_pos.y + (game_area.size.y - map_height * CELL_SIZE) / 2
|
||||
|
||||
# 绘制地图
|
||||
for y in range(map_height):
|
||||
for x in range(map_width):
|
||||
var cell_x = start_x + x * CELL_SIZE
|
||||
var cell_y = start_y + y * CELL_SIZE
|
||||
var rect = Rect2(cell_x, cell_y, CELL_SIZE, CELL_SIZE)
|
||||
|
||||
var cell_type = level_data[y][x]
|
||||
var color = CELL_COLORS[cell_type]
|
||||
|
||||
# 绘制单元格
|
||||
draw_rect(rect, color, true)
|
||||
|
||||
# 绘制边框
|
||||
draw_rect(rect, Color.BLACK, false, 1)
|
||||
|
||||
# 特殊处理:如果是玩家在目标点上,需要先绘制目标点
|
||||
if cell_type == CellType.PLAYER:
|
||||
# 检查玩家下面是否有目标点(通过检查原始关卡数据)
|
||||
var level_strings = LEVELS[current_level]
|
||||
if y < level_strings.size() and x < level_strings[y].length():
|
||||
var original_char = level_strings[y][x]
|
||||
if original_char == '*': # 玩家在目标点上
|
||||
draw_rect(rect, CELL_COLORS[CellType.TARGET], true)
|
||||
draw_rect(rect, Color.BLACK, false, 1)
|
||||
# 再绘制玩家(半透明)
|
||||
var player_color = CELL_COLORS[CellType.PLAYER]
|
||||
player_color.a = 0.8
|
||||
draw_rect(rect, player_color, true)
|
||||
1
Scene/SmallGame/PushBox.gd.uid
Normal file
1
Scene/SmallGame/PushBox.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b1t5fxyg0jjx5
|
||||
85
Scene/SmallGame/PushBox.tscn
Normal file
85
Scene/SmallGame/PushBox.tscn
Normal file
@@ -0,0 +1,85 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://cq14axh7bovu6"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b1t5fxyg0jjx5" path="res://Scene/SmallGame/PushBox.gd" id="1_qdfdf"]
|
||||
|
||||
[node name="PushBox" type="Panel"]
|
||||
offset_right = 1402.0
|
||||
offset_bottom = 720.0
|
||||
script = ExtResource("1_qdfdf")
|
||||
|
||||
[node name="GameArea" type="Panel" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -300.0
|
||||
offset_top = -250.0
|
||||
offset_right = 300.0
|
||||
offset_bottom = 250.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="LevelLabel" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 50.0
|
||||
offset_top = -100.0
|
||||
offset_right = 200.0
|
||||
offset_bottom = -70.0
|
||||
grow_vertical = 0
|
||||
text = "关卡: 1"
|
||||
|
||||
[node name="MovesLabel" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 50.0
|
||||
offset_top = -70.0
|
||||
offset_right = 200.0
|
||||
offset_bottom = -40.0
|
||||
grow_vertical = 0
|
||||
text = "步数: 0"
|
||||
|
||||
[node name="WinLabel" type="Label" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -150.0
|
||||
offset_top = -50.0
|
||||
offset_right = 150.0
|
||||
offset_bottom = 50.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
text = "恭喜过关!
|
||||
按N进入下一关
|
||||
按R重新开始"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="ControlsLabel" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 3
|
||||
anchor_left = 1.0
|
||||
anchor_top = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -300.0
|
||||
offset_top = -150.0
|
||||
offset_right = -50.0
|
||||
offset_bottom = -50.0
|
||||
grow_horizontal = 0
|
||||
grow_vertical = 0
|
||||
text = "操作说明:
|
||||
WASD或方向键 - 移动
|
||||
R - 重新开始当前关卡
|
||||
N - 下一关(过关后)
|
||||
P - 上一关"
|
||||
207
Scene/SmallGame/SnakeGame.gd
Normal file
207
Scene/SmallGame/SnakeGame.gd
Normal file
@@ -0,0 +1,207 @@
|
||||
extends Panel
|
||||
|
||||
# 游戏常量
|
||||
const GRID_SIZE = 20
|
||||
const GRID_WIDTH = 30
|
||||
const GRID_HEIGHT = 30
|
||||
|
||||
# 方向枚举
|
||||
enum Direction {
|
||||
UP,
|
||||
DOWN,
|
||||
LEFT,
|
||||
RIGHT
|
||||
}
|
||||
|
||||
# 游戏变量
|
||||
var snake_body = []
|
||||
var snake_direction = Direction.RIGHT
|
||||
var next_direction = Direction.RIGHT
|
||||
var food_position = Vector2()
|
||||
var score = 0
|
||||
var game_over = false
|
||||
|
||||
# 节点引用
|
||||
@onready var game_area = $GameArea
|
||||
@onready var score_label = $ScoreLabel
|
||||
@onready var game_over_label = $GameOverLabel
|
||||
@onready var game_timer = $GameTimer
|
||||
|
||||
func _ready():
|
||||
# 连接定时器信号
|
||||
game_timer.timeout.connect(_on_game_timer_timeout)
|
||||
|
||||
# 设置游戏区域样式
|
||||
game_area.modulate = Color(0.2, 0.2, 0.2, 1.0)
|
||||
|
||||
# 初始化游戏
|
||||
init_game()
|
||||
|
||||
func init_game():
|
||||
# 重置游戏状态
|
||||
game_over = false
|
||||
score = 0
|
||||
snake_direction = Direction.RIGHT
|
||||
next_direction = Direction.RIGHT
|
||||
|
||||
# 初始化蛇身
|
||||
snake_body.clear()
|
||||
snake_body.append(Vector2(5, 5))
|
||||
snake_body.append(Vector2(4, 5))
|
||||
snake_body.append(Vector2(3, 5))
|
||||
|
||||
# 生成食物
|
||||
generate_food()
|
||||
|
||||
# 更新UI
|
||||
update_score()
|
||||
game_over_label.visible = false
|
||||
|
||||
# 启动定时器
|
||||
game_timer.start()
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventKey and event.pressed:
|
||||
if game_over:
|
||||
if event.keycode == KEY_SPACE:
|
||||
init_game()
|
||||
return
|
||||
|
||||
# 控制蛇的方向
|
||||
match event.keycode:
|
||||
KEY_UP, KEY_W:
|
||||
if snake_direction != Direction.DOWN:
|
||||
next_direction = Direction.UP
|
||||
KEY_DOWN, KEY_S:
|
||||
if snake_direction != Direction.UP:
|
||||
next_direction = Direction.DOWN
|
||||
KEY_LEFT, KEY_A:
|
||||
if snake_direction != Direction.RIGHT:
|
||||
next_direction = Direction.LEFT
|
||||
KEY_RIGHT, KEY_D:
|
||||
if snake_direction != Direction.LEFT:
|
||||
next_direction = Direction.RIGHT
|
||||
|
||||
func _on_game_timer_timeout():
|
||||
if game_over:
|
||||
return
|
||||
|
||||
# 更新方向
|
||||
snake_direction = next_direction
|
||||
|
||||
# 移动蛇
|
||||
move_snake()
|
||||
|
||||
# 检查碰撞
|
||||
check_collisions()
|
||||
|
||||
# 重绘游戏
|
||||
queue_redraw()
|
||||
|
||||
func move_snake():
|
||||
var head = snake_body[0]
|
||||
var new_head = head
|
||||
|
||||
# 根据方向计算新的头部位置
|
||||
match snake_direction:
|
||||
Direction.UP:
|
||||
new_head = Vector2(head.x, head.y - 1)
|
||||
Direction.DOWN:
|
||||
new_head = Vector2(head.x, head.y + 1)
|
||||
Direction.LEFT:
|
||||
new_head = Vector2(head.x - 1, head.y)
|
||||
Direction.RIGHT:
|
||||
new_head = Vector2(head.x + 1, head.y)
|
||||
|
||||
# 添加新头部
|
||||
snake_body.insert(0, new_head)
|
||||
|
||||
# 检查是否吃到食物
|
||||
if new_head == food_position:
|
||||
# 增加分数
|
||||
score += 10
|
||||
update_score()
|
||||
|
||||
# 生成新食物
|
||||
generate_food()
|
||||
else:
|
||||
# 移除尾部
|
||||
snake_body.pop_back()
|
||||
|
||||
func check_collisions():
|
||||
var head = snake_body[0]
|
||||
|
||||
# 检查边界碰撞
|
||||
if head.x < 0 or head.x >= GRID_WIDTH or head.y < 0 or head.y >= GRID_HEIGHT:
|
||||
game_over = true
|
||||
show_game_over()
|
||||
return
|
||||
|
||||
# 检查自身碰撞
|
||||
for i in range(1, snake_body.size()):
|
||||
if head == snake_body[i]:
|
||||
game_over = true
|
||||
show_game_over()
|
||||
return
|
||||
|
||||
func generate_food():
|
||||
var attempts = 0
|
||||
while attempts < 100: # 防止无限循环
|
||||
food_position = Vector2(
|
||||
randi() % GRID_WIDTH,
|
||||
randi() % GRID_HEIGHT
|
||||
)
|
||||
|
||||
# 确保食物不在蛇身上
|
||||
var food_on_snake = false
|
||||
for segment in snake_body:
|
||||
if segment == food_position:
|
||||
food_on_snake = true
|
||||
break
|
||||
|
||||
if not food_on_snake:
|
||||
break
|
||||
|
||||
attempts += 1
|
||||
|
||||
func update_score():
|
||||
score_label.text = "分数: " + str(score)
|
||||
|
||||
func show_game_over():
|
||||
game_timer.stop()
|
||||
game_over_label.visible = true
|
||||
|
||||
func _draw():
|
||||
if not game_area:
|
||||
return
|
||||
|
||||
# 获取游戏区域的位置和大小
|
||||
var area_pos = game_area.position
|
||||
var area_size = game_area.size
|
||||
|
||||
# 计算网格大小
|
||||
var cell_width = area_size.x / GRID_WIDTH
|
||||
var cell_height = area_size.y / GRID_HEIGHT
|
||||
|
||||
# 绘制蛇身
|
||||
for i in range(snake_body.size()):
|
||||
var segment = snake_body[i]
|
||||
var rect = Rect2(
|
||||
area_pos.x + segment.x * cell_width,
|
||||
area_pos.y + segment.y * cell_height,
|
||||
cell_width - 1,
|
||||
cell_height - 1
|
||||
)
|
||||
|
||||
# 头部用不同颜色
|
||||
var color = Color.GREEN if i == 0 else Color.LIME_GREEN
|
||||
draw_rect(rect, color)
|
||||
|
||||
# 绘制食物
|
||||
var food_rect = Rect2(
|
||||
area_pos.x + food_position.x * cell_width,
|
||||
area_pos.y + food_position.y * cell_height,
|
||||
cell_width - 1,
|
||||
cell_height - 1
|
||||
)
|
||||
draw_rect(food_rect, Color.RED)
|
||||
1
Scene/SmallGame/SnakeGame.gd.uid
Normal file
1
Scene/SmallGame/SnakeGame.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://rut5cdp1l3nh
|
||||
57
Scene/SmallGame/SnakeGame.tscn
Normal file
57
Scene/SmallGame/SnakeGame.tscn
Normal file
@@ -0,0 +1,57 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://grpkpy4duwac"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://rut5cdp1l3nh" path="res://Scene/SmallGame/SnakeGame.gd" id="1_o070e"]
|
||||
|
||||
[node name="SnakeGame" type="Panel"]
|
||||
offset_right = 1403.0
|
||||
offset_bottom = 726.0
|
||||
script = ExtResource("1_o070e")
|
||||
|
||||
[node name="GameArea" type="Panel" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -300.0
|
||||
offset_top = -300.0
|
||||
offset_right = 300.0
|
||||
offset_bottom = 300.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="ScoreLabel" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 20.0
|
||||
offset_top = -50.0
|
||||
offset_right = 200.0
|
||||
offset_bottom = -20.0
|
||||
grow_vertical = 0
|
||||
text = "分数: 0"
|
||||
|
||||
[node name="GameOverLabel" type="Label" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -100.0
|
||||
offset_top = -50.0
|
||||
offset_right = 100.0
|
||||
offset_bottom = 50.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
text = "游戏结束
|
||||
按空格重新开始"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="GameTimer" type="Timer" parent="."]
|
||||
wait_time = 0.2
|
||||
autostart = true
|
||||
333
Scene/SmallGame/Tetris.gd
Normal file
333
Scene/SmallGame/Tetris.gd
Normal file
@@ -0,0 +1,333 @@
|
||||
extends Panel
|
||||
|
||||
# 游戏常量
|
||||
const BOARD_WIDTH = 10
|
||||
const BOARD_HEIGHT = 20
|
||||
const CELL_SIZE = 30
|
||||
|
||||
# 方块类型
|
||||
enum PieceType {
|
||||
I, O, T, S, Z, J, L
|
||||
}
|
||||
|
||||
# 方块形状定义
|
||||
const PIECE_SHAPES = {
|
||||
PieceType.I: [
|
||||
[[1, 1, 1, 1]],
|
||||
[[1], [1], [1], [1]]
|
||||
],
|
||||
PieceType.O: [
|
||||
[[1, 1], [1, 1]]
|
||||
],
|
||||
PieceType.T: [
|
||||
[[0, 1, 0], [1, 1, 1]],
|
||||
[[1, 0], [1, 1], [1, 0]],
|
||||
[[1, 1, 1], [0, 1, 0]],
|
||||
[[0, 1], [1, 1], [0, 1]]
|
||||
],
|
||||
PieceType.S: [
|
||||
[[0, 1, 1], [1, 1, 0]],
|
||||
[[1, 0], [1, 1], [0, 1]]
|
||||
],
|
||||
PieceType.Z: [
|
||||
[[1, 1, 0], [0, 1, 1]],
|
||||
[[0, 1], [1, 1], [1, 0]]
|
||||
],
|
||||
PieceType.J: [
|
||||
[[1, 0, 0], [1, 1, 1]],
|
||||
[[1, 1], [1, 0], [1, 0]],
|
||||
[[1, 1, 1], [0, 0, 1]],
|
||||
[[0, 1], [0, 1], [1, 1]]
|
||||
],
|
||||
PieceType.L: [
|
||||
[[0, 0, 1], [1, 1, 1]],
|
||||
[[1, 0], [1, 0], [1, 1]],
|
||||
[[1, 1, 1], [1, 0, 0]],
|
||||
[[1, 1], [0, 1], [0, 1]]
|
||||
]
|
||||
}
|
||||
|
||||
# 方块颜色
|
||||
const PIECE_COLORS = {
|
||||
PieceType.I: Color.CYAN,
|
||||
PieceType.O: Color.YELLOW,
|
||||
PieceType.T: Color.MAGENTA,
|
||||
PieceType.S: Color.GREEN,
|
||||
PieceType.Z: Color.RED,
|
||||
PieceType.J: Color.BLUE,
|
||||
PieceType.L: Color.ORANGE
|
||||
}
|
||||
|
||||
# 游戏变量
|
||||
var board = []
|
||||
var current_piece = null
|
||||
var current_piece_pos = Vector2()
|
||||
var current_piece_rotation = 0
|
||||
var next_piece_type = PieceType.I
|
||||
var score = 0
|
||||
var level = 1
|
||||
var lines_cleared = 0
|
||||
var game_over = false
|
||||
var drop_time = 1.0
|
||||
|
||||
# 节点引用
|
||||
@onready var game_area = $GameArea
|
||||
@onready var next_piece_area = $NextPieceArea
|
||||
@onready var score_label = $ScoreLabel
|
||||
@onready var level_label = $LevelLabel
|
||||
@onready var lines_label = $LinesLabel
|
||||
@onready var game_over_label = $GameOverLabel
|
||||
@onready var drop_timer = $DropTimer
|
||||
|
||||
func _ready():
|
||||
# 连接定时器信号
|
||||
drop_timer.timeout.connect(_on_drop_timer_timeout)
|
||||
|
||||
# 设置游戏区域样式
|
||||
game_area.modulate = Color(0.1, 0.1, 0.1, 1.0)
|
||||
next_piece_area.modulate = Color(0.2, 0.2, 0.2, 1.0)
|
||||
|
||||
# 初始化游戏
|
||||
init_game()
|
||||
|
||||
func init_game():
|
||||
# 重置游戏状态
|
||||
game_over = false
|
||||
score = 0
|
||||
level = 1
|
||||
lines_cleared = 0
|
||||
drop_time = 1.0
|
||||
|
||||
# 初始化游戏板
|
||||
board.clear()
|
||||
for y in range(BOARD_HEIGHT):
|
||||
var row = []
|
||||
for x in range(BOARD_WIDTH):
|
||||
row.append(0)
|
||||
board.append(row)
|
||||
|
||||
# 生成第一个方块
|
||||
next_piece_type = randi() % PieceType.size()
|
||||
spawn_new_piece()
|
||||
|
||||
# 更新UI
|
||||
update_ui()
|
||||
game_over_label.visible = false
|
||||
|
||||
# 启动定时器
|
||||
drop_timer.wait_time = drop_time
|
||||
drop_timer.start()
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventKey and event.pressed:
|
||||
if game_over:
|
||||
if event.keycode == KEY_SPACE:
|
||||
init_game()
|
||||
return
|
||||
|
||||
if not current_piece:
|
||||
return
|
||||
|
||||
# 控制方块
|
||||
match event.keycode:
|
||||
KEY_A:
|
||||
move_piece(-1, 0)
|
||||
KEY_D:
|
||||
move_piece(1, 0)
|
||||
KEY_S:
|
||||
move_piece(0, 1)
|
||||
KEY_W:
|
||||
rotate_piece()
|
||||
KEY_SPACE:
|
||||
drop_piece()
|
||||
|
||||
func spawn_new_piece():
|
||||
current_piece = {
|
||||
"type": next_piece_type,
|
||||
"rotation": 0
|
||||
}
|
||||
current_piece_pos = Vector2(BOARD_WIDTH / 2 - 1, 0)
|
||||
current_piece_rotation = 0
|
||||
|
||||
# 生成下一个方块
|
||||
next_piece_type = randi() % PieceType.size()
|
||||
|
||||
# 检查游戏是否结束
|
||||
if not can_place_piece(current_piece_pos, current_piece_rotation):
|
||||
game_over = true
|
||||
show_game_over()
|
||||
|
||||
func move_piece(dx: int, dy: int):
|
||||
var new_pos = current_piece_pos + Vector2(dx, dy)
|
||||
if can_place_piece(new_pos, current_piece_rotation):
|
||||
current_piece_pos = new_pos
|
||||
queue_redraw()
|
||||
|
||||
func rotate_piece():
|
||||
var new_rotation = (current_piece_rotation + 1) % get_piece_rotations(current_piece.type)
|
||||
if can_place_piece(current_piece_pos, new_rotation):
|
||||
current_piece_rotation = new_rotation
|
||||
queue_redraw()
|
||||
|
||||
func drop_piece():
|
||||
while can_place_piece(current_piece_pos + Vector2(0, 1), current_piece_rotation):
|
||||
current_piece_pos.y += 1
|
||||
place_piece()
|
||||
|
||||
func can_place_piece(pos: Vector2, rotation: int) -> bool:
|
||||
var shape = get_piece_shape(current_piece.type, rotation)
|
||||
for y in range(shape.size()):
|
||||
for x in range(shape[y].size()):
|
||||
if shape[y][x] == 1:
|
||||
var board_x = pos.x + x
|
||||
var board_y = pos.y + y
|
||||
|
||||
# 检查边界
|
||||
if board_x < 0 or board_x >= BOARD_WIDTH or board_y >= BOARD_HEIGHT:
|
||||
return false
|
||||
|
||||
# 检查碰撞
|
||||
if board_y >= 0 and board[board_y][board_x] != 0:
|
||||
return false
|
||||
return true
|
||||
|
||||
func place_piece():
|
||||
var shape = get_piece_shape(current_piece.type, current_piece_rotation)
|
||||
for y in range(shape.size()):
|
||||
for x in range(shape[y].size()):
|
||||
if shape[y][x] == 1:
|
||||
var board_x = current_piece_pos.x + x
|
||||
var board_y = current_piece_pos.y + y
|
||||
if board_y >= 0:
|
||||
board[board_y][board_x] = current_piece.type + 1
|
||||
|
||||
# 检查并清除完整的行
|
||||
clear_lines()
|
||||
|
||||
# 生成新方块
|
||||
spawn_new_piece()
|
||||
|
||||
queue_redraw()
|
||||
|
||||
func clear_lines():
|
||||
var lines_to_clear = []
|
||||
|
||||
# 找到完整的行
|
||||
for y in range(BOARD_HEIGHT):
|
||||
var is_full = true
|
||||
for x in range(BOARD_WIDTH):
|
||||
if board[y][x] == 0:
|
||||
is_full = false
|
||||
break
|
||||
if is_full:
|
||||
lines_to_clear.append(y)
|
||||
|
||||
# 清除行并下移
|
||||
for line_y in lines_to_clear:
|
||||
board.erase(board[line_y])
|
||||
var new_row = []
|
||||
for x in range(BOARD_WIDTH):
|
||||
new_row.append(0)
|
||||
board.insert(0, new_row)
|
||||
|
||||
# 更新分数和等级
|
||||
if lines_to_clear.size() > 0:
|
||||
lines_cleared += lines_to_clear.size()
|
||||
score += lines_to_clear.size() * 100 * level
|
||||
|
||||
# 每10行提升一个等级
|
||||
level = lines_cleared / 10 + 1
|
||||
drop_time = max(0.1, 1.0 - (level - 1) * 0.1)
|
||||
drop_timer.wait_time = drop_time
|
||||
|
||||
update_ui()
|
||||
|
||||
func get_piece_shape(type: PieceType, rotation: int) -> Array:
|
||||
return PIECE_SHAPES[type][rotation]
|
||||
|
||||
func get_piece_rotations(type: PieceType) -> int:
|
||||
return PIECE_SHAPES[type].size()
|
||||
|
||||
func update_ui():
|
||||
score_label.text = "分数: " + str(score)
|
||||
level_label.text = "等级: " + str(level)
|
||||
lines_label.text = "消除行数: " + str(lines_cleared)
|
||||
|
||||
func show_game_over():
|
||||
drop_timer.stop()
|
||||
game_over_label.visible = true
|
||||
|
||||
func _on_drop_timer_timeout():
|
||||
if game_over or not current_piece:
|
||||
return
|
||||
|
||||
if can_place_piece(current_piece_pos + Vector2(0, 1), current_piece_rotation):
|
||||
current_piece_pos.y += 1
|
||||
queue_redraw()
|
||||
else:
|
||||
place_piece()
|
||||
|
||||
func _draw():
|
||||
if not game_area:
|
||||
return
|
||||
|
||||
# 获取游戏区域的位置
|
||||
var area_pos = game_area.position
|
||||
|
||||
# 绘制游戏板
|
||||
for y in range(BOARD_HEIGHT):
|
||||
for x in range(BOARD_WIDTH):
|
||||
var cell_value = board[y][x]
|
||||
if cell_value > 0:
|
||||
var rect = Rect2(
|
||||
area_pos.x + x * CELL_SIZE,
|
||||
area_pos.y + y * CELL_SIZE,
|
||||
CELL_SIZE - 1,
|
||||
CELL_SIZE - 1
|
||||
)
|
||||
var color = PIECE_COLORS[cell_value - 1]
|
||||
draw_rect(rect, color)
|
||||
|
||||
# 绘制当前方块
|
||||
if current_piece:
|
||||
var shape = get_piece_shape(current_piece.type, current_piece_rotation)
|
||||
for y in range(shape.size()):
|
||||
for x in range(shape[y].size()):
|
||||
if shape[y][x] == 1:
|
||||
var board_x = current_piece_pos.x + x
|
||||
var board_y = current_piece_pos.y + y
|
||||
if board_y >= 0:
|
||||
var rect = Rect2(
|
||||
area_pos.x + board_x * CELL_SIZE,
|
||||
area_pos.y + board_y * CELL_SIZE,
|
||||
CELL_SIZE - 1,
|
||||
CELL_SIZE - 1
|
||||
)
|
||||
var color = PIECE_COLORS[current_piece.type]
|
||||
draw_rect(rect, color)
|
||||
|
||||
# 绘制网格线
|
||||
for x in range(BOARD_WIDTH + 1):
|
||||
var start_pos = Vector2(area_pos.x + x * CELL_SIZE, area_pos.y)
|
||||
var end_pos = Vector2(area_pos.x + x * CELL_SIZE, area_pos.y + BOARD_HEIGHT * CELL_SIZE)
|
||||
draw_line(start_pos, end_pos, Color.GRAY, 1)
|
||||
|
||||
for y in range(BOARD_HEIGHT + 1):
|
||||
var start_pos = Vector2(area_pos.x, area_pos.y + y * CELL_SIZE)
|
||||
var end_pos = Vector2(area_pos.x + BOARD_WIDTH * CELL_SIZE, area_pos.y + y * CELL_SIZE)
|
||||
draw_line(start_pos, end_pos, Color.GRAY, 1)
|
||||
|
||||
# 绘制下一个方块预览
|
||||
var next_area_pos = next_piece_area.position
|
||||
var next_shape = get_piece_shape(next_piece_type, 0)
|
||||
for y in range(next_shape.size()):
|
||||
for x in range(next_shape[y].size()):
|
||||
if next_shape[y][x] == 1:
|
||||
var rect = Rect2(
|
||||
next_area_pos.x + 20 + x * 20,
|
||||
next_area_pos.y + 50 + y * 20,
|
||||
19,
|
||||
19
|
||||
)
|
||||
var color = PIECE_COLORS[next_piece_type]
|
||||
draw_rect(rect, color)
|
||||
1
Scene/SmallGame/Tetris.gd.uid
Normal file
1
Scene/SmallGame/Tetris.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://yhljjw1pbovq
|
||||
120
Scene/SmallGame/Tetris.tscn
Normal file
120
Scene/SmallGame/Tetris.tscn
Normal file
@@ -0,0 +1,120 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://c3nuuwu5te3bu"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://yhljjw1pbovq" path="res://Scene/SmallGame/Tetris.gd" id="1_s1q1g"]
|
||||
|
||||
[node name="Tetris" type="Panel"]
|
||||
offset_right = 1403.0
|
||||
offset_bottom = 721.0
|
||||
script = ExtResource("1_s1q1g")
|
||||
|
||||
[node name="GameArea" type="Panel" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 4
|
||||
anchor_top = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = 50.0
|
||||
offset_top = -300.0
|
||||
offset_right = 350.0
|
||||
offset_bottom = 300.0
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="NextPieceArea" type="Panel" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -200.0
|
||||
offset_top = 50.0
|
||||
offset_right = -50.0
|
||||
offset_bottom = 200.0
|
||||
grow_horizontal = 0
|
||||
|
||||
[node name="NextPieceLabel" type="Label" parent="NextPieceArea"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 5
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
offset_left = -50.0
|
||||
offset_top = 10.0
|
||||
offset_right = 50.0
|
||||
offset_bottom = 40.0
|
||||
grow_horizontal = 2
|
||||
text = "下一个"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="ScoreLabel" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -200.0
|
||||
offset_top = 220.0
|
||||
offset_right = -50.0
|
||||
offset_bottom = 250.0
|
||||
grow_horizontal = 0
|
||||
text = "分数: 0"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="LevelLabel" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -200.0
|
||||
offset_top = 260.0
|
||||
offset_right = -50.0
|
||||
offset_bottom = 290.0
|
||||
grow_horizontal = 0
|
||||
text = "等级: 1"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="LinesLabel" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -200.0
|
||||
offset_top = 300.0
|
||||
offset_right = -50.0
|
||||
offset_bottom = 330.0
|
||||
grow_horizontal = 0
|
||||
text = "消除行数: 0"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="GameOverLabel" type="Label" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -100.0
|
||||
offset_top = -50.0
|
||||
offset_right = 100.0
|
||||
offset_bottom = 50.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
text = "游戏结束
|
||||
按空格重新开始"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="DropTimer" type="Timer" parent="."]
|
||||
autostart = true
|
||||
|
||||
[node name="ControlsLabel" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -200.0
|
||||
offset_top = 400.0
|
||||
offset_right = -50.0
|
||||
offset_bottom = 500.0
|
||||
grow_horizontal = 0
|
||||
text = "操作说明:
|
||||
A/D - 左右移动
|
||||
S - 快速下降
|
||||
W - 旋转
|
||||
空格 - 瞬间下降"
|
||||
Reference in New Issue
Block a user