diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs index f78f577..a5f7853 100644 --- a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs +++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs @@ -42,18 +42,18 @@ //自定义节点 private CustomTypeInfo[] _customTypeInfos = new CustomTypeInfo[] { - new CustomTypeInfo( - "ActivityMark", - "Node2D", - "res://src/framework/map/mark/ActivityMark.cs", - "res://addons/dungeonShooting_plugin/Mark.svg" - ), - new CustomTypeInfo( - "EnemyMark", - "Node2D", - "res://src/framework/map/mark/EnemyMark.cs", - "res://addons/dungeonShooting_plugin/Mark.svg" - ), + // new CustomTypeInfo( + // "ActivityMark", + // "Node2D", + // "res://src/framework/map/mark/ActivityMark.cs", + // "res://addons/dungeonShooting_plugin/Mark.svg" + // ), + // new CustomTypeInfo( + // "EnemyMark", + // "Node2D", + // "res://src/framework/map/mark/EnemyMark.cs", + // "res://addons/dungeonShooting_plugin/Mark.svg" + // ), }; public override void _Process(double delta) diff --git a/DungeonShooting_Godot/prefab/ui/Main.tscn b/DungeonShooting_Godot/prefab/ui/Main.tscn index 3138727..fa4657f 100644 --- a/DungeonShooting_Godot/prefab/ui/Main.tscn +++ b/DungeonShooting_Godot/prefab/ui/Main.tscn @@ -12,33 +12,37 @@ grow_vertical = 2 script = ExtResource("1_s44xr") -[node name="Title" type="Label" parent="."] +[node name="ColorRect" type="ColorRect" parent="."] layout_mode = 1 -anchors_preset = 10 +anchors_preset = 15 anchor_right = 1.0 -offset_top = 172.0 -offset_bottom = 405.0 +anchor_bottom = 1.0 grow_horizontal = 2 +grow_vertical = 2 +color = Color(0.109804, 0.0666667, 0.0901961, 1) + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Title" type="Label" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 6 theme_override_font_sizes/font_size = 160 text = "Program dungeon" horizontal_alignment = 1 vertical_alignment = 1 -[node name="ButtonList" type="VBoxContainer" parent="."] -layout_mode = 1 -anchors_preset = 7 -anchor_left = 0.5 -anchor_top = 1.0 -anchor_right = 0.5 -anchor_bottom = 1.0 -offset_left = -96.0 -offset_top = -641.0 -offset_right = 96.0 -grow_horizontal = 2 -grow_vertical = 0 +[node name="ButtonList" type="VBoxContainer" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 alignment = 1 -[node name="Start" type="Button" parent="ButtonList"] +[node name="Start" type="Button" parent="VBoxContainer/ButtonList"] custom_minimum_size = Vector2(0, 50) layout_mode = 2 focus_neighbor_top = NodePath("../Exit") @@ -47,7 +51,7 @@ text = "开始游戏 " -[node name="Tools" type="Button" parent="ButtonList"] +[node name="Tools" type="Button" parent="VBoxContainer/ButtonList"] custom_minimum_size = Vector2(0, 50) layout_mode = 2 focus_neighbor_top = NodePath("../Start") @@ -56,7 +60,7 @@ theme_override_font_sizes/font_size = 32 text = "开发者工具" -[node name="Setting" type="Button" parent="ButtonList"] +[node name="Setting" type="Button" parent="VBoxContainer/ButtonList"] custom_minimum_size = Vector2(0, 50) layout_mode = 2 focus_neighbor_top = NodePath("../Start") @@ -65,7 +69,7 @@ theme_override_font_sizes/font_size = 32 text = "设置" -[node name="Exit" type="Button" parent="ButtonList"] +[node name="Exit" type="Button" parent="VBoxContainer/ButtonList"] custom_minimum_size = Vector2(0, 50) layout_mode = 2 focus_neighbor_top = NodePath("../Setting") diff --git a/DungeonShooting_Godot/prefab/ui/PauseMenu.tscn b/DungeonShooting_Godot/prefab/ui/PauseMenu.tscn new file mode 100644 index 0000000..421dd01 --- /dev/null +++ b/DungeonShooting_Godot/prefab/ui/PauseMenu.tscn @@ -0,0 +1,59 @@ +[gd_scene load_steps=3 format=3 uid="uid://bkq1wl66w3ais"] + +[ext_resource type="Script" path="res://src/game/ui/pauseMenu/PauseMenuPanel.cs" id="1_ef73i"] +[ext_resource type="Theme" uid="uid://drb1ajgvcih7p" path="res://resource/theme/theme1.tres" id="2_x1py5"] + +[node name="PauseMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource("1_ef73i") +Layer = 2 + +[node name="ColorRect" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0, 0, 0, 0.54902) + +[node name="VBoxContainer" type="VBoxContainer" 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 = -64.0 +offset_top = -79.0 +offset_right = 64.0 +offset_bottom = 79.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Continue" type="Button" parent="VBoxContainer"] +custom_minimum_size = Vector2(0, 50) +layout_mode = 2 +focus_neighbor_top = NodePath("../Exit") +focus_neighbor_bottom = NodePath("../Setting") +theme = ExtResource("2_x1py5") +text = "继续" + +[node name="Restart" type="Button" parent="VBoxContainer"] +custom_minimum_size = Vector2(0, 50) +layout_mode = 2 +focus_neighbor_top = NodePath("../Exit") +focus_neighbor_bottom = NodePath("../Setting") +theme = ExtResource("2_x1py5") +text = "重新开始" + +[node name="Exit" type="Button" parent="VBoxContainer"] +custom_minimum_size = Vector2(0, 50) +layout_mode = 2 +focus_neighbor_top = NodePath("../Exit") +focus_neighbor_bottom = NodePath("../Setting") +theme = ExtResource("2_x1py5") +text = "退出游戏" diff --git a/DungeonShooting_Godot/project.godot b/DungeonShooting_Godot/project.godot index ba66a76..e745e0f 100644 --- a/DungeonShooting_Godot/project.godot +++ b/DungeonShooting_Godot/project.godot @@ -21,8 +21,8 @@ [display] -window/size/viewport_width=1920 -window/size/viewport_height=1080 +window/size/viewport_width=1280 +window/size/viewport_height=720 window/stretch/aspect="keep_width" window/vsync/use_vsync=false diff --git a/DungeonShooting_Godot/resource/map/tileMaps/GroupConfig.json b/DungeonShooting_Godot/resource/map/tileMaps/GroupConfig.json index ce8105f..d9e69c2 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/GroupConfig.json +++ b/DungeonShooting_Godot/resource/map/tileMaps/GroupConfig.json @@ -19,6 +19,10 @@ { "ErrorType": 0, "Path": "resource/map/tileMaps/TestGroup1/inlet/Start1" + }, + { + "ErrorType": 0, + "Path": "resource/map/tileMaps/TestGroup1/inlet/Start2" } ], "OutletList": [ diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Battle3/Preview.png b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Battle3/Preview.png index 95d5f00..d6290c0 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Battle3/Preview.png +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Battle3/Preview.png Binary files differ diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Battle3/TileInfo.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Battle3/TileInfo.json index 6e7dcaa..c0ec3fa 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Battle3/TileInfo.json +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Battle3/TileInfo.json @@ -1 +1 @@ -{"NavigationList":[{"Type":0,"Points":[184,120,376,120,376,152,440,152,440,216,520,216,520,384,456,384,456,464,312,464,312,480,184,480]},{"Type":1,"Points":[264,240,392,240,392,272,424,272,424,344,408,344,408,392,360,392,360,312,312,312,312,328,296,328,296,392,248,392,248,256,264,256]}],"Floor":[32,23,0,0,8,32,22,0,0,8,32,21,0,0,8,32,20,0,0,8,32,19,0,0,8,32,18,0,0,8,32,17,0,0,8,32,16,0,0,8,32,15,0,0,8,32,14,0,0,8,32,13,0,0,8,31,23,0,0,8,31,22,0,0,8,31,21,0,0,8,31,20,0,0,8,31,19,0,0,8,31,18,0,0,8,31,17,0,0,8,31,16,0,0,8,31,15,0,0,8,31,14,0,0,8,31,13,0,0,8,30,23,0,0,8,30,22,0,0,8,30,21,0,0,8,30,20,0,0,8,30,19,0,0,8,30,18,0,0,8,30,17,0,0,8,30,16,0,0,8,30,15,0,0,8,30,14,0,0,8,30,13,0,0,8,29,23,0,0,8,29,22,0,0,8,29,21,0,0,8,29,20,0,0,8,29,19,0,0,8,29,18,0,0,8,29,17,0,0,8,29,16,0,0,8,29,15,0,0,8,29,14,0,0,8,29,13,0,0,8,28,28,0,0,8,28,27,0,0,8,28,26,0,0,8,28,25,0,0,8,28,24,0,0,8,28,23,0,0,8,28,22,0,0,8,28,21,0,0,8,28,20,0,0,8,28,19,0,0,8,28,18,0,0,8,28,17,0,0,8,28,16,0,0,8,28,15,0,0,8,28,14,0,0,8,28,13,0,0,8,27,28,0,0,8,27,27,0,0,8,27,26,0,0,8,27,25,0,0,8,27,24,0,0,8,27,23,0,0,8,27,22,0,0,8,27,21,0,0,8,27,20,0,0,8,27,19,0,0,8,27,18,0,0,8,27,17,0,0,8,27,16,0,0,8,27,15,0,0,8,27,14,0,0,8,27,13,0,0,8,27,9,0,0,8,27,10,0,0,8,27,11,0,0,8,27,12,0,0,8,26,28,0,0,8,26,27,0,0,8,26,26,0,0,8,26,25,0,0,8,26,24,0,0,8,26,23,0,0,8,26,22,0,0,8,26,21,0,0,8,26,20,0,0,8,26,19,0,0,8,26,18,0,0,8,26,17,0,0,8,26,16,0,0,8,26,15,0,0,8,26,14,0,0,8,26,13,0,0,8,26,9,0,0,8,26,10,0,0,8,26,11,0,0,8,26,12,0,0,8,25,28,0,0,8,25,27,0,0,8,25,26,0,0,8,25,25,0,0,8,25,24,0,0,8,25,23,0,0,8,25,22,0,0,8,25,21,0,0,8,25,16,0,0,8,25,15,0,0,8,25,14,0,0,8,25,13,0,0,8,25,9,0,0,8,25,10,0,0,8,25,11,0,0,8,25,12,0,0,8,24,28,0,0,8,24,27,0,0,8,24,26,0,0,8,24,25,0,0,8,24,24,0,0,8,24,16,0,0,8,24,15,0,0,8,24,14,0,0,8,24,13,0,0,8,24,9,0,0,8,24,10,0,0,8,24,11,0,0,8,24,12,0,0,8,23,28,0,0,8,23,27,0,0,8,23,26,0,0,8,23,25,0,0,8,23,24,0,0,8,23,14,0,0,8,23,13,0,0,8,23,7,0,0,8,23,8,0,0,8,23,9,0,0,8,23,10,0,0,8,23,11,0,0,8,23,12,0,0,8,22,28,0,0,8,22,27,0,0,8,22,26,0,0,8,22,25,0,0,8,22,24,0,0,8,22,23,0,0,8,22,22,0,0,8,22,21,0,0,8,22,20,0,0,8,22,19,0,0,8,22,7,0,0,8,22,8,0,0,8,22,9,0,0,8,22,10,0,0,8,22,11,0,0,8,22,12,0,0,8,22,13,0,0,8,22,14,0,0,8,21,28,0,0,8,21,27,0,0,8,21,26,0,0,8,21,25,0,0,8,21,24,0,0,8,21,23,0,0,8,21,22,0,0,8,21,21,0,0,8,21,20,0,0,8,21,19,0,0,8,21,7,0,0,8,21,8,0,0,8,21,9,0,0,8,21,10,0,0,8,21,11,0,0,8,21,12,0,0,8,21,13,0,0,8,21,14,0,0,8,20,28,0,0,8,20,27,0,0,8,20,26,0,0,8,20,25,0,0,8,20,24,0,0,8,20,23,0,0,8,20,22,0,0,8,20,21,0,0,8,20,20,0,0,8,20,19,0,0,8,20,7,0,0,8,20,8,0,0,8,20,9,0,0,8,20,10,0,0,8,20,11,0,0,8,20,12,0,0,8,20,13,0,0,8,20,14,0,0,8,19,29,0,0,8,19,28,0,0,8,19,27,0,0,8,19,26,0,0,8,19,25,0,0,8,19,24,0,0,8,19,23,0,0,8,19,22,0,0,8,19,21,0,0,8,19,20,0,0,8,19,19,0,0,8,19,7,0,0,8,19,8,0,0,8,19,9,0,0,8,19,10,0,0,8,19,11,0,0,8,19,12,0,0,8,19,13,0,0,8,19,14,0,0,8,18,29,0,0,8,18,28,0,0,8,18,27,0,0,8,18,26,0,0,8,18,25,0,0,8,18,24,0,0,8,18,23,0,0,8,18,22,0,0,8,18,21,0,0,8,18,20,0,0,8,18,7,0,0,8,18,8,0,0,8,18,9,0,0,8,18,10,0,0,8,18,11,0,0,8,18,12,0,0,8,18,13,0,0,8,18,14,0,0,8,17,29,0,0,8,17,28,0,0,8,17,27,0,0,8,17,26,0,0,8,17,25,0,0,8,17,24,0,0,8,17,7,0,0,8,17,8,0,0,8,17,9,0,0,8,17,10,0,0,8,17,11,0,0,8,17,12,0,0,8,17,13,0,0,8,17,14,0,0,8,16,29,0,0,8,16,28,0,0,8,16,27,0,0,8,16,26,0,0,8,16,25,0,0,8,16,24,0,0,8,16,7,0,0,8,16,8,0,0,8,16,9,0,0,8,16,10,0,0,8,16,11,0,0,8,16,12,0,0,8,16,13,0,0,8,16,14,0,0,8,16,15,0,0,8,15,29,0,0,8,15,28,0,0,8,15,27,0,0,8,15,26,0,0,8,15,25,0,0,8,15,24,0,0,8,15,23,0,0,8,15,22,0,0,8,15,21,0,0,8,15,20,0,0,8,15,7,0,0,8,15,8,0,0,8,15,9,0,0,8,15,10,0,0,8,15,11,0,0,8,15,12,0,0,8,15,13,0,0,8,15,14,0,0,8,15,15,0,0,8,15,16,0,0,8,15,17,0,0,8,15,18,0,0,8,15,19,0,0,8,14,29,0,0,8,14,28,0,0,8,14,27,0,0,8,14,26,0,0,8,14,25,0,0,8,14,24,0,0,8,14,23,0,0,8,14,22,0,0,8,14,21,0,0,8,14,20,0,0,8,14,7,0,0,8,14,8,0,0,8,14,9,0,0,8,14,10,0,0,8,14,11,0,0,8,14,12,0,0,8,14,13,0,0,8,14,14,0,0,8,14,15,0,0,8,14,16,0,0,8,14,17,0,0,8,14,18,0,0,8,14,19,0,0,8,13,29,0,0,8,13,28,0,0,8,13,27,0,0,8,13,26,0,0,8,13,25,0,0,8,13,24,0,0,8,13,23,0,0,8,13,22,0,0,8,13,21,0,0,8,13,20,0,0,8,13,7,0,0,8,13,8,0,0,8,13,9,0,0,8,13,10,0,0,8,13,11,0,0,8,13,12,0,0,8,13,13,0,0,8,13,14,0,0,8,13,15,0,0,8,13,16,0,0,8,13,17,0,0,8,13,18,0,0,8,13,19,0,0,8,12,29,0,0,8,12,28,0,0,8,12,27,0,0,8,12,26,0,0,8,12,25,0,0,8,12,24,0,0,8,12,23,0,0,8,12,22,0,0,8,12,21,0,0,8,12,20,0,0,8,12,7,0,0,8,12,8,0,0,8,12,9,0,0,8,12,10,0,0,8,12,11,0,0,8,12,12,0,0,8,12,13,0,0,8,12,14,0,0,8,12,15,0,0,8,12,16,0,0,8,12,17,0,0,8,12,18,0,0,8,12,19,0,0,8,11,29,0,0,8,11,28,0,0,8,11,27,0,0,8,11,26,0,0,8,11,25,0,0,8,11,24,0,0,8,11,23,0,0,8,11,22,0,0,8,11,21,0,0,8,11,20,0,0,8,11,7,0,0,8,11,8,0,0,8,11,9,0,0,8,11,10,0,0,8,11,11,0,0,8,11,12,0,0,8,11,13,0,0,8,11,14,0,0,8,11,15,0,0,8,11,16,0,0,8,11,17,0,0,8,11,18,0,0,8,11,19,0,0,8],"Middle":[11,6,0,2,7,12,6,0,2,7,13,6,0,2,7,14,6,0,2,7,15,6,0,2,7,16,6,0,2,7,16,23,0,1,7,17,6,0,2,7,17,23,0,3,7,18,6,0,2,7,18,19,0,3,7,19,6,0,2,7,19,18,0,2,7,20,6,0,2,7,20,18,0,2,7,21,6,0,2,7,21,18,0,2,7,22,6,0,2,7,22,18,0,2,7,23,6,0,2,7,23,23,0,1,7,24,8,0,1,7,24,23,0,3,7,25,8,0,2,7,25,20,0,3,7,26,8,0,2,7,27,8,0,2,7,28,12,0,1,7,29,12,0,2,7,30,12,0,2,7,31,12,0,2,7,32,12,0,2,7],"Top":[10,6,0,3,4,10,7,0,3,3,10,8,0,3,3,10,9,0,3,3,10,10,0,3,3,10,11,0,3,3,10,12,0,3,3,10,13,0,3,3,10,14,0,3,3,10,15,0,3,3,10,16,0,3,3,10,17,0,3,3,10,18,0,3,3,10,19,0,3,3,10,20,0,3,3,10,21,0,3,3,10,22,0,3,3,10,23,0,3,3,10,24,0,3,3,10,25,0,3,3,10,26,0,3,3,10,27,0,3,3,10,28,0,3,3,10,29,0,3,3,10,30,0,11,2,11,30,0,2,2,12,30,0,2,2,13,30,0,2,2,14,30,0,2,2,15,30,0,2,2,16,16,0,1,2,16,17,0,1,3,16,18,0,1,3,16,19,0,1,3,16,20,0,1,3,16,21,0,1,3,16,22,0,1,3,16,30,0,2,2,17,15,0,1,2,17,16,0,13,2,17,19,0,3,4,17,20,0,3,3,17,21,0,3,3,17,22,0,3,3,17,30,0,2,2,18,15,0,2,2,18,18,0,3,4,18,30,0,2,2,19,15,0,2,2,19,30,0,2,2,20,15,0,2,2,20,29,0,1,2,20,30,0,13,2,21,15,0,2,2,21,29,0,2,2,22,15,0,2,2,22,29,0,2,2,23,15,0,3,2,23,16,0,3,3,23,17,0,11,2,23,18,0,1,4,23,19,0,1,3,23,20,0,1,3,23,21,0,1,3,23,22,0,1,3,23,29,0,2,2,24,6,0,1,4,24,7,0,1,3,24,17,0,2,2,24,20,0,3,4,24,21,0,3,3,24,22,0,3,3,24,29,0,2,2,25,17,0,3,2,25,18,0,3,3,25,19,0,3,3,25,29,0,2,2,26,29,0,2,2,27,29,0,2,2,28,8,0,1,4,28,9,0,1,3,28,10,0,1,3,28,11,0,1,3,28,29,0,2,2,29,24,0,1,2,29,25,0,1,3,29,26,0,1,3,29,27,0,1,3,29,28,0,1,3,29,29,0,13,2,30,24,0,2,2,31,24,0,2,2,32,24,0,2,2,33,12,0,1,4,33,13,0,1,3,33,14,0,1,3,33,15,0,1,3,33,16,0,1,3,33,17,0,1,3,33,18,0,1,3,33,19,0,1,3,33,20,0,1,3,33,21,0,1,3,33,22,0,1,3,33,23,0,1,3,33,24,0,13,2]} \ No newline at end of file +{"NavigationList":[{"Type":0,"Points":[184,120,376,120,376,152,440,152,440,216,520,216,520,384,456,384,456,464,312,464,312,480,184,480]},{"Type":1,"Points":[264,240,392,240,392,256,408,256,408,272,424,272,424,344,408,344,408,392,360,392,360,328,296,328,296,312,280,312,280,392,232,392,232,272,248,272,248,256,264,256]}],"Floor":[32,23,0,0,8,32,22,0,0,8,32,21,0,0,8,32,20,0,0,8,32,19,0,0,8,32,18,0,0,8,32,17,0,0,8,32,16,0,0,8,32,15,0,0,8,32,14,0,0,8,32,13,0,0,8,31,23,0,0,8,31,22,0,0,8,31,21,0,0,8,31,20,0,0,8,31,19,0,0,8,31,18,0,0,8,31,17,0,0,8,31,16,0,0,8,31,15,0,0,8,31,14,0,0,8,31,13,0,0,8,30,23,0,0,8,30,22,0,0,8,30,21,0,0,8,30,20,0,0,8,30,19,0,0,8,30,18,0,0,8,30,17,0,0,8,30,16,0,0,8,30,15,0,0,8,30,14,0,0,8,30,13,0,0,8,29,23,0,0,8,29,22,0,0,8,29,21,0,0,8,29,20,0,0,8,29,19,0,0,8,29,18,0,0,8,29,17,0,0,8,29,16,0,0,8,29,15,0,0,8,29,14,0,0,8,29,13,0,0,8,28,28,0,0,8,28,27,0,0,8,28,26,0,0,8,28,25,0,0,8,28,24,0,0,8,28,23,0,0,8,28,22,0,0,8,28,21,0,0,8,28,20,0,0,8,28,19,0,0,8,28,18,0,0,8,28,17,0,0,8,28,16,0,0,8,28,15,0,0,8,28,14,0,0,8,28,13,0,0,8,27,28,0,0,8,27,27,0,0,8,27,26,0,0,8,27,25,0,0,8,27,24,0,0,8,27,23,0,0,8,27,22,0,0,8,27,21,0,0,8,27,20,0,0,8,27,19,0,0,8,27,18,0,0,8,27,17,0,0,8,27,16,0,0,8,27,15,0,0,8,27,14,0,0,8,27,13,0,0,8,27,9,0,0,8,27,10,0,0,8,27,11,0,0,8,27,12,0,0,8,26,28,0,0,8,26,27,0,0,8,26,26,0,0,8,26,25,0,0,8,26,24,0,0,8,26,23,0,0,8,26,22,0,0,8,26,21,0,0,8,26,20,0,0,8,26,19,0,0,8,26,18,0,0,8,26,17,0,0,8,26,16,0,0,8,26,15,0,0,8,26,14,0,0,8,26,13,0,0,8,26,9,0,0,8,26,10,0,0,8,26,11,0,0,8,26,12,0,0,8,25,28,0,0,8,25,27,0,0,8,25,26,0,0,8,25,25,0,0,8,25,24,0,0,8,25,23,0,0,8,25,22,0,0,8,25,21,0,0,8,25,16,0,0,8,25,15,0,0,8,25,14,0,0,8,25,13,0,0,8,25,9,0,0,8,25,10,0,0,8,25,11,0,0,8,25,12,0,0,8,24,28,0,0,8,24,27,0,0,8,24,26,0,0,8,24,25,0,0,8,24,24,0,0,8,24,15,0,0,8,24,14,0,0,8,24,13,0,0,8,24,9,0,0,8,24,10,0,0,8,24,11,0,0,8,24,12,0,0,8,23,28,0,0,8,23,27,0,0,8,23,26,0,0,8,23,25,0,0,8,23,24,0,0,8,23,14,0,0,8,23,13,0,0,8,23,7,0,0,8,23,8,0,0,8,23,9,0,0,8,23,10,0,0,8,23,11,0,0,8,23,12,0,0,8,22,28,0,0,8,22,27,0,0,8,22,26,0,0,8,22,25,0,0,8,22,24,0,0,8,22,23,0,0,8,22,22,0,0,8,22,21,0,0,8,22,20,0,0,8,22,7,0,0,8,22,8,0,0,8,22,9,0,0,8,22,10,0,0,8,22,11,0,0,8,22,12,0,0,8,22,13,0,0,8,22,14,0,0,8,21,28,0,0,8,21,27,0,0,8,21,26,0,0,8,21,25,0,0,8,21,24,0,0,8,21,23,0,0,8,21,22,0,0,8,21,21,0,0,8,21,20,0,0,8,21,7,0,0,8,21,8,0,0,8,21,9,0,0,8,21,10,0,0,8,21,11,0,0,8,21,12,0,0,8,21,13,0,0,8,21,14,0,0,8,20,28,0,0,8,20,27,0,0,8,20,26,0,0,8,20,25,0,0,8,20,24,0,0,8,20,23,0,0,8,20,22,0,0,8,20,21,0,0,8,20,20,0,0,8,20,7,0,0,8,20,8,0,0,8,20,9,0,0,8,20,10,0,0,8,20,11,0,0,8,20,12,0,0,8,20,13,0,0,8,20,14,0,0,8,19,29,0,0,8,19,28,0,0,8,19,27,0,0,8,19,26,0,0,8,19,25,0,0,8,19,24,0,0,8,19,23,0,0,8,19,22,0,0,8,19,21,0,0,8,19,20,0,0,8,19,7,0,0,8,19,8,0,0,8,19,9,0,0,8,19,10,0,0,8,19,11,0,0,8,19,12,0,0,8,19,13,0,0,8,19,14,0,0,8,18,19,0,0,8,18,29,0,0,8,18,28,0,0,8,18,27,0,0,8,18,26,0,0,8,18,25,0,0,8,18,24,0,0,8,18,23,0,0,8,18,22,0,0,8,18,21,0,0,8,18,20,0,0,8,18,7,0,0,8,18,8,0,0,8,18,9,0,0,8,18,10,0,0,8,18,11,0,0,8,18,12,0,0,8,18,13,0,0,8,18,14,0,0,8,17,19,0,0,8,17,23,0,0,8,17,22,0,0,8,17,21,0,0,8,17,20,0,0,8,17,29,0,0,8,17,28,0,0,8,17,27,0,0,8,17,26,0,0,8,17,25,0,0,8,17,24,0,0,8,17,7,0,0,8,17,8,0,0,8,17,9,0,0,8,17,10,0,0,8,17,11,0,0,8,17,12,0,0,8,17,13,0,0,8,17,14,0,0,8,16,29,0,0,8,16,28,0,0,8,16,27,0,0,8,16,26,0,0,8,16,25,0,0,8,16,24,0,0,8,16,7,0,0,8,16,8,0,0,8,16,9,0,0,8,16,10,0,0,8,16,11,0,0,8,16,12,0,0,8,16,13,0,0,8,16,14,0,0,8,16,15,0,0,8,15,29,0,0,8,15,28,0,0,8,15,27,0,0,8,15,26,0,0,8,15,25,0,0,8,15,24,0,0,8,15,7,0,0,8,15,8,0,0,8,15,9,0,0,8,15,10,0,0,8,15,11,0,0,8,15,12,0,0,8,15,13,0,0,8,15,14,0,0,8,15,15,0,0,8,15,16,0,0,8,14,29,0,0,8,14,28,0,0,8,14,27,0,0,8,14,26,0,0,8,14,25,0,0,8,14,24,0,0,8,14,23,0,0,8,14,22,0,0,8,14,21,0,0,8,14,20,0,0,8,14,7,0,0,8,14,8,0,0,8,14,9,0,0,8,14,10,0,0,8,14,11,0,0,8,14,12,0,0,8,14,13,0,0,8,14,14,0,0,8,14,15,0,0,8,14,16,0,0,8,14,17,0,0,8,14,18,0,0,8,14,19,0,0,8,13,29,0,0,8,13,28,0,0,8,13,27,0,0,8,13,26,0,0,8,13,25,0,0,8,13,24,0,0,8,13,23,0,0,8,13,22,0,0,8,13,21,0,0,8,13,20,0,0,8,13,7,0,0,8,13,8,0,0,8,13,9,0,0,8,13,10,0,0,8,13,11,0,0,8,13,12,0,0,8,13,13,0,0,8,13,14,0,0,8,13,15,0,0,8,13,16,0,0,8,13,17,0,0,8,13,18,0,0,8,13,19,0,0,8,12,29,0,0,8,12,28,0,0,8,12,27,0,0,8,12,26,0,0,8,12,25,0,0,8,12,24,0,0,8,12,23,0,0,8,12,22,0,0,8,12,21,0,0,8,12,20,0,0,8,12,7,0,0,8,12,8,0,0,8,12,9,0,0,8,12,10,0,0,8,12,11,0,0,8,12,12,0,0,8,12,13,0,0,8,12,14,0,0,8,12,15,0,0,8,12,16,0,0,8,12,17,0,0,8,12,18,0,0,8,12,19,0,0,8,11,29,0,0,8,11,28,0,0,8,11,27,0,0,8,11,26,0,0,8,11,25,0,0,8,11,24,0,0,8,11,23,0,0,8,11,22,0,0,8,11,21,0,0,8,11,20,0,0,8,11,7,0,0,8,11,8,0,0,8,11,9,0,0,8,11,10,0,0,8,11,11,0,0,8,11,12,0,0,8,11,13,0,0,8,11,14,0,0,8,11,15,0,0,8,11,16,0,0,8,11,17,0,0,8,11,18,0,0,8,11,19,0,0,8],"Middle":[11,6,0,2,7,12,6,0,2,7,13,6,0,2,7,14,6,0,2,7,15,6,0,2,7,15,23,0,1,7,16,6,0,2,7,16,23,0,3,7,17,6,0,2,7,17,18,0,2,7,18,6,0,2,7,18,18,0,2,7,19,6,0,2,7,19,19,0,1,7,20,6,0,2,7,20,19,0,2,7,21,6,0,2,7,21,19,0,2,7,22,6,0,2,7,22,19,0,2,7,23,6,0,2,7,23,23,0,1,7,24,8,0,1,7,24,23,0,3,7,25,8,0,2,7,25,20,0,3,7,26,8,0,2,7,27,8,0,2,7,28,12,0,1,7,29,12,0,2,7,30,12,0,2,7,31,12,0,2,7,32,12,0,2,7],"Top":[10,6,0,3,4,10,7,0,3,3,10,8,0,3,3,10,9,0,3,3,10,10,0,3,3,10,11,0,3,3,10,12,0,3,3,10,13,0,3,3,10,14,0,3,3,10,15,0,3,3,10,16,0,3,3,10,17,0,3,3,10,18,0,3,3,10,19,0,3,3,10,20,0,3,3,10,21,0,3,3,10,22,0,3,3,10,23,0,3,3,10,24,0,3,3,10,25,0,3,3,10,26,0,3,3,10,27,0,3,3,10,28,0,3,3,10,29,0,3,3,10,30,0,11,2,11,30,0,2,2,12,30,0,2,2,13,30,0,2,2,14,30,0,2,2,15,17,0,1,2,15,18,0,1,3,15,19,0,1,3,15,20,0,1,3,15,21,0,1,3,15,22,0,1,3,15,30,0,2,2,16,16,0,1,2,16,17,0,13,2,16,18,0,3,4,16,19,0,3,3,16,20,0,3,3,16,21,0,3,3,16,22,0,3,3,16,30,0,2,2,17,15,0,1,2,17,16,0,13,2,17,30,0,2,2,18,15,0,2,2,18,30,0,2,2,19,15,0,2,2,19,18,0,1,4,19,30,0,2,2,20,15,0,2,2,20,29,0,1,2,20,30,0,13,2,21,15,0,2,2,21,29,0,2,2,22,15,0,2,2,22,29,0,2,2,23,15,0,3,2,23,16,0,11,2,23,19,0,1,4,23,20,0,1,3,23,21,0,1,3,23,22,0,1,3,23,29,0,2,2,24,6,0,1,4,24,7,0,1,3,24,16,0,3,2,24,17,0,11,2,24,20,0,3,4,24,21,0,3,3,24,22,0,3,3,24,29,0,2,2,25,17,0,3,2,25,18,0,3,3,25,19,0,3,3,25,29,0,2,2,26,29,0,2,2,27,29,0,2,2,28,8,0,1,4,28,9,0,1,3,28,10,0,1,3,28,11,0,1,3,28,29,0,2,2,29,24,0,1,2,29,25,0,1,3,29,26,0,1,3,29,27,0,1,3,29,28,0,1,3,29,29,0,13,2,30,24,0,2,2,31,24,0,2,2,32,24,0,2,2,33,12,0,1,4,33,13,0,1,3,33,14,0,1,3,33,15,0,1,3,33,16,0,1,3,33,17,0,1,3,33,18,0,1,3,33,19,0,1,3,33,20,0,1,3,33,21,0,1,3,33,22,0,1,3,33,23,0,1,3,33,24,0,13,2]} \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json index 74763d2..fd75129 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json @@ -1 +1 @@ -[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":19,"Y":2},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":10,"Y":22},"Size":{"X":0,"Y":0},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":0,"Y":16},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0002","Weight":100,"Attr":{"CurrAmmon":"7","ResidueAmmo":"70"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":23,"Y":-24},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0004","Weight":100,"Attr":{"CurrAmmon":"180","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-35,"Y":59},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0005","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"40"},"Altitude":8,"VerticalSpeed":0}]}],[{"Position":{"X":11,"Y":38},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0003","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-15,"Y":31},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0.5,"MarkList":[{"Id":"prop5000","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":36,"Y":36},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":35,"Y":2},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1.5,"MarkList":[{"Id":"prop0002","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-12,"Y":3},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":2,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-36,"Y":-18},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop5000","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":56,"Y":-24},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]}]]}] \ No newline at end of file +[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":19,"Y":2},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":-76,"Y":35},"Size":{"X":0,"Y":0},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-79,"Y":46},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0002","Weight":100,"Attr":{"CurrAmmon":"7","ResidueAmmo":"70"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-75,"Y":2},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0004","Weight":100,"Attr":{"CurrAmmon":"180","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-75,"Y":67},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0005","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"40"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-73,"Y":-18},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0003","Weight":100,"Attr":{"CurrAmmon":"12","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-76,"Y":21},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0006","Weight":100,"Attr":{"CurrAmmon":"20","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-74,"Y":-30},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0007","Weight":100,"Attr":{"CurrAmmon":"60","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]}],[{"Position":{"X":55,"Y":67},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0003","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":56,"Y":24},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0.5,"MarkList":[{"Id":"prop5000","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":56,"Y":0},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":34,"Y":23},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1.5,"MarkList":[{"Id":"prop0002","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":55,"Y":44},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":56,"Y":-24},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]}]]}] \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preview.png b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preview.png index 3f0900c..d64d95a 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preview.png +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preview.png Binary files differ diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/RoomInfo.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/RoomInfo.json index 4285d01..6005b11 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/RoomInfo.json +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/RoomInfo.json @@ -1 +1 @@ -{"Position":{"X":-5,"Y":-4},"Size":{"X":11,"Y":10},"DoorAreaInfos":[],"GroupName":"TestGroup1","RoomType":1,"RoomName":"Start1","Weight":100,"Remark":""} \ No newline at end of file +{"Position":{"X":-8,"Y":-4},"Size":{"X":15,"Y":10},"DoorAreaInfos":[{"Direction":3,"Start":0,"End":208},{"Direction":0,"Start":0,"End":128},{"Direction":2,"Start":128,"End":208},{"Direction":1,"Start":0,"End":128},{"Direction":2,"Start":0,"End":64}],"GroupName":"TestGroup1","RoomType":1,"RoomName":"Start1","Weight":100,"Remark":""} \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/TileInfo.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/TileInfo.json index 22e1c00..68ed08e 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/TileInfo.json +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/TileInfo.json @@ -1 +1 @@ -{"NavigationList":[{"Type":0,"Points":[-56,-40,72,-40,72,80,-56,80]}],"Floor":[-4,-3,0,0,8,-4,-2,0,0,8,-4,-1,0,0,8,-4,0,0,0,8,-4,1,0,0,8,-4,2,0,0,8,-4,3,0,0,8,-4,4,0,0,8,-3,-3,0,0,8,-3,-2,0,0,8,-3,-1,0,0,8,-3,0,0,0,8,-3,1,0,0,8,-3,2,0,0,8,-3,3,0,0,8,-3,4,0,0,8,-2,-3,0,0,8,-2,-2,0,0,8,-2,-1,0,0,8,-2,0,0,0,8,-2,1,0,0,8,-2,2,0,0,8,-2,3,0,0,8,-2,4,0,0,8,-1,-3,0,0,8,-1,-2,0,0,8,-1,-1,0,0,8,-1,0,0,0,8,-1,1,0,0,8,-1,2,0,0,8,-1,3,0,0,8,-1,4,0,0,8,0,-3,0,0,8,0,-2,0,0,8,0,-1,0,0,8,0,0,0,0,8,0,1,0,0,8,0,2,0,0,8,0,3,0,0,8,0,4,0,0,8,4,-3,0,0,8,4,-2,0,0,8,4,-1,0,0,8,4,0,0,0,8,4,1,0,0,8,4,2,0,0,8,4,3,0,0,8,4,4,0,0,8,3,-3,0,0,8,3,-2,0,0,8,3,-1,0,0,8,3,0,0,0,8,3,1,0,0,8,3,2,0,0,8,3,3,0,0,8,3,4,0,0,8,2,-3,0,0,8,2,-2,0,0,8,2,-1,0,0,8,2,0,0,0,8,2,1,0,0,8,2,2,0,0,8,2,3,0,0,8,2,4,0,0,8,1,-3,0,0,8,1,-2,0,0,8,1,-1,0,0,8,1,0,0,0,8,1,1,0,0,8,1,2,0,0,8,1,3,0,0,8,1,4,0,0,8],"Middle":[-4,-4,0,2,7,-3,-4,0,2,7,-2,-4,0,2,7,-1,-4,0,2,7,0,-4,0,2,7,1,-4,0,2,7,2,-4,0,2,7,3,-4,0,2,7,4,-4,0,2,7],"Top":[-5,-4,0,3,4,-5,-3,0,3,3,-5,-2,0,3,3,-5,-1,0,3,3,-5,0,0,3,3,-5,1,0,3,3,-5,2,0,3,3,-5,3,0,3,3,-5,4,0,3,3,-5,5,0,11,2,-4,5,0,2,2,-3,5,0,2,2,-2,5,0,2,2,-1,5,0,2,2,0,5,0,2,2,1,5,0,2,2,2,5,0,2,2,3,5,0,2,2,4,5,0,2,2,5,-4,0,1,4,5,-3,0,1,3,5,-2,0,1,3,5,-1,0,1,3,5,0,0,1,3,5,1,0,1,3,5,2,0,1,3,5,3,0,1,3,5,4,0,1,3,5,5,0,13,2]} \ No newline at end of file +{"NavigationList":[{"Type":0,"Points":[-104,-40,88,-40,88,80,24,80,24,48,-56,48,-56,80,-104,80]}],"Floor":[-7,-3,0,0,8,-7,-2,0,0,8,-7,-1,0,0,8,-7,0,0,0,8,-7,1,0,0,8,-7,2,0,0,8,-7,3,0,0,8,-7,4,0,0,8,-6,-3,0,0,8,-6,-2,0,0,8,-6,-1,0,0,8,-6,0,0,0,8,-6,1,0,0,8,-6,2,0,0,8,-6,3,0,0,8,-6,4,0,0,8,5,-1,0,0,8,5,0,0,0,8,5,1,0,0,8,5,2,0,0,8,5,3,0,0,8,5,4,0,0,8,5,-2,0,0,8,5,-3,0,0,8,-5,-3,0,0,8,-5,-2,0,0,8,-5,-1,0,0,8,-5,0,0,0,8,-5,1,0,0,8,-5,2,0,0,8,-5,3,0,0,8,-5,4,0,0,8,1,4,0,0,8,1,3,0,0,8,1,2,0,0,8,1,1,0,0,8,1,0,0,0,8,1,-1,0,0,8,1,-2,0,0,8,1,-3,0,0,8,2,4,0,0,8,2,3,0,0,8,2,2,0,0,8,2,1,0,0,8,2,0,0,0,8,2,-1,0,0,8,2,-2,0,0,8,2,-3,0,0,8,3,4,0,0,8,3,3,0,0,8,3,2,0,0,8,3,1,0,0,8,3,0,0,0,8,3,-1,0,0,8,3,-2,0,0,8,3,-3,0,0,8,4,4,0,0,8,4,3,0,0,8,4,2,0,0,8,4,1,0,0,8,4,0,0,0,8,4,-1,0,0,8,4,-2,0,0,8,4,-3,0,0,8,0,2,0,0,8,0,1,0,0,8,0,0,0,0,8,0,-1,0,0,8,0,-2,0,0,8,0,-3,0,0,8,-1,2,0,0,8,-1,1,0,0,8,-1,0,0,0,8,-1,-1,0,0,8,-1,-2,0,0,8,-1,-3,0,0,8,-2,2,0,0,8,-2,1,0,0,8,-2,0,0,0,8,-2,-1,0,0,8,-2,-2,0,0,8,-2,-3,0,0,8,-3,2,0,0,8,-3,1,0,0,8,-3,0,0,0,8,-3,-1,0,0,8,-3,-2,0,0,8,-3,-3,0,0,8,-4,4,0,0,8,-4,3,0,0,8,-4,2,0,0,8,-4,1,0,0,8,-4,0,0,0,8,-4,-1,0,0,8,-4,-2,0,0,8,-4,-3,0,0,8],"Middle":[-7,-4,0,2,7,-6,-4,0,2,7,-5,-4,0,2,7,-4,-4,0,2,7,-3,-4,0,2,7,-2,-4,0,2,7,-1,-4,0,2,7,0,-4,0,2,7,1,-4,0,2,7,2,-4,0,2,7,3,-4,0,2,7,4,-4,0,2,7,5,-4,0,2,7],"Top":[-8,-4,0,3,4,-8,-3,0,3,3,-8,-2,0,3,3,-8,-1,0,3,3,-8,0,0,3,3,-8,1,0,3,3,-8,2,0,3,3,-8,3,0,3,3,-8,4,0,3,3,-8,5,0,11,2,-7,5,0,2,2,-6,5,0,2,2,-5,5,0,2,2,-4,5,0,2,2,-3,3,0,1,2,-3,4,0,1,3,-3,5,0,13,2,-2,3,0,2,2,-1,3,0,2,2,0,3,0,3,2,0,4,0,3,3,0,5,0,11,2,1,5,0,2,2,2,5,0,2,2,3,5,0,2,2,4,5,0,2,2,5,5,0,2,2,6,-4,0,1,4,6,-3,0,1,3,6,-2,0,1,3,6,-1,0,1,3,6,0,0,1,3,6,1,0,1,3,6,2,0,1,3,6,3,0,1,3,6,4,0,1,3,6,5,0,13,2]} \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/Preinstall.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/Preinstall.json new file mode 100644 index 0000000..2af15f7 --- /dev/null +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/Preinstall.json @@ -0,0 +1 @@ +[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":0,"Y":0},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":0,"Y":26},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0005","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"40"},"Altitude":8,"VerticalSpeed":0}]}]]}] \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/Preview.png b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/Preview.png new file mode 100644 index 0000000..6d2fd01 --- /dev/null +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/Preview.png Binary files differ diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/Preview.png.import b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/Preview.png.import new file mode 100644 index 0000000..68d306b --- /dev/null +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/Preview.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cr5tlhxfjetuf" +path="res://.godot/imported/Preview.png-8fbf34b154290497f5a1f19b421f568c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/map/tileMaps/TestGroup1/inlet/Start2/Preview.png" +dest_files=["res://.godot/imported/Preview.png-8fbf34b154290497f5a1f19b421f568c.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/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/RoomInfo.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/RoomInfo.json new file mode 100644 index 0000000..27eaead --- /dev/null +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/RoomInfo.json @@ -0,0 +1 @@ +{"Position":{"X":-5,"Y":-5},"Size":{"X":10,"Y":12},"DoorAreaInfos":[{"Direction":3,"Start":0,"End":128},{"Direction":0,"Start":0,"End":160},{"Direction":1,"Start":0,"End":160}],"GroupName":"TestGroup1","RoomType":1,"RoomName":"Start2","Weight":100,"Remark":""} \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/TileInfo.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/TileInfo.json new file mode 100644 index 0000000..60689b8 --- /dev/null +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start2/TileInfo.json @@ -0,0 +1 @@ +{"NavigationList":[{"Type":0,"Points":[-56,-56,56,-56,56,96,40,96,40,48,-40,48,-40,96,-56,96]}],"Floor":[-3,-4,0,0,8,-3,-3,0,0,8,-3,-2,0,0,8,-3,-1,0,0,8,-3,0,0,0,8,-3,1,0,0,8,-3,2,0,0,8,-3,3,0,0,8,-3,4,0,0,8,-3,5,0,0,8,-2,-2,0,0,8,-2,-4,0,0,8,-2,-3,0,0,8,-2,-1,0,0,8,-2,0,0,0,8,-2,1,0,0,8,-2,2,0,0,8,-1,-1,0,0,8,-1,-4,0,0,8,-1,-3,0,0,8,-1,-2,0,0,8,-1,0,0,0,8,-1,1,0,0,8,-1,2,0,0,8,0,0,0,0,8,0,-4,0,0,8,0,-3,0,0,8,0,-2,0,0,8,0,-1,0,0,8,0,1,0,0,8,0,2,0,0,8,1,1,0,0,8,1,-4,0,0,8,1,-3,0,0,8,1,-2,0,0,8,1,-1,0,0,8,1,0,0,0,8,1,2,0,0,8,2,1,0,0,8,2,-4,0,0,8,2,-3,0,0,8,2,-2,0,0,8,2,-1,0,0,8,2,0,0,0,8,2,2,0,0,8,2,3,0,0,8,2,4,0,0,8,2,5,0,0,8,-4,-4,0,0,8,-4,-3,0,0,8,-4,-2,0,0,8,-4,-1,0,0,8,-4,0,0,0,8,-4,1,0,0,8,-4,2,0,0,8,-4,3,0,0,8,-4,4,0,0,8,-4,5,0,0,8,3,-4,0,0,8,3,-3,0,0,8,3,-2,0,0,8,3,-1,0,0,8,3,0,0,0,8,3,1,0,0,8,3,2,0,0,8,3,3,0,0,8,3,4,0,0,8,3,5,0,0,8],"Middle":[-4,-5,0,2,7,-3,-5,0,2,7,-2,-5,0,2,7,-1,-5,0,2,7,0,-5,0,2,7,1,-5,0,2,7,2,-5,0,2,7,3,-5,0,2,7],"Top":[-5,-5,0,3,4,-5,-4,0,3,3,-5,-3,0,3,3,-5,-2,0,3,3,-5,-1,0,3,3,-5,0,0,3,3,-5,1,0,3,3,-5,2,0,3,3,-5,3,0,3,3,-5,4,0,3,3,-5,5,0,3,3,-5,6,0,11,2,-4,6,0,2,2,-3,6,0,2,2,-2,3,0,1,2,-2,4,0,1,3,-2,5,0,1,3,-2,6,0,13,2,-1,3,0,2,2,0,3,0,2,2,1,3,0,3,2,1,4,0,3,3,1,5,0,3,3,1,6,0,11,2,2,6,0,2,2,3,6,0,2,2,4,-5,0,1,4,4,-4,0,1,3,4,-3,0,1,3,4,-2,0,1,3,4,-1,0,1,3,4,0,0,1,3,4,1,0,1,3,4,2,0,1,3,4,3,0,1,3,4,4,0,1,3,4,5,0,1,3,4,6,0,13,2]} \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/outlet/End1/Preview.png b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/outlet/End1/Preview.png index 8e0a47a..6224d08 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/outlet/End1/Preview.png +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/outlet/End1/Preview.png Binary files differ diff --git a/DungeonShooting_Godot/resource/sprite/map/WallTransition1.png b/DungeonShooting_Godot/resource/sprite/map/WallTransition1.png new file mode 100644 index 0000000..420ef2c --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/map/WallTransition1.png Binary files differ diff --git a/DungeonShooting_Godot/resource/sprite/map/WallTransition1.png.import b/DungeonShooting_Godot/resource/sprite/map/WallTransition1.png.import new file mode 100644 index 0000000..7141f43 --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/map/WallTransition1.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ddkx5x25fges7" +path="res://.godot/imported/WallTransition1.png-290006472c94b57424b8ec3bd229ce8b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/sprite/map/WallTransition1.png" +dest_files=["res://.godot/imported/WallTransition1.png-290006472c94b57424b8ec3bd229ce8b.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/DungeonShooting_Godot/resource/sprite/map/WallTransition2.png b/DungeonShooting_Godot/resource/sprite/map/WallTransition2.png new file mode 100644 index 0000000..f01f30b --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/map/WallTransition2.png Binary files differ diff --git a/DungeonShooting_Godot/resource/sprite/map/WallTransition2.png.import b/DungeonShooting_Godot/resource/sprite/map/WallTransition2.png.import new file mode 100644 index 0000000..5f256b8 --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/map/WallTransition2.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b751rowqecctj" +path="res://.godot/imported/WallTransition2.png-43446d8d92d11ce7c994737780ed01a3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/sprite/map/WallTransition2.png" +dest_files=["res://.godot/imported/WallTransition2.png-43446d8d92d11ce7c994737780ed01a3.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/DungeonShooting_Godot/resource/sprite/map/WallTransition3.png b/DungeonShooting_Godot/resource/sprite/map/WallTransition3.png new file mode 100644 index 0000000..430aba3 --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/map/WallTransition3.png Binary files differ diff --git a/DungeonShooting_Godot/resource/sprite/map/WallTransition3.png.import b/DungeonShooting_Godot/resource/sprite/map/WallTransition3.png.import new file mode 100644 index 0000000..1bbeb6d --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/map/WallTransition3.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://civvboe078gcc" +path="res://.godot/imported/WallTransition3.png-db21c2408170d6ada2e3c9da5f2912c8.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/sprite/map/WallTransition3.png" +dest_files=["res://.godot/imported/WallTransition3.png-db21c2408170d6ada2e3c9da5f2912c8.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/DungeonShooting_Godot/scene/Main.tscn b/DungeonShooting_Godot/scene/Main.tscn index b2179bb..877b1ff 100644 --- a/DungeonShooting_Godot/scene/Main.tscn +++ b/DungeonShooting_Godot/scene/Main.tscn @@ -41,7 +41,7 @@ handle_input_locally = false use_hdr_2d = true canvas_item_default_texture_filter = 0 -size = Vector2i(480, 270) +size = Vector2i(320, 180) render_target_update_mode = 4 [node name="SceneRoot" type="Node2D" parent="ViewCanvas/SubViewportContainer/SubViewport"] diff --git a/DungeonShooting_Godot/scene/World.tscn b/DungeonShooting_Godot/scene/World.tscn index 5a92afa..f9bbfa7 100644 --- a/DungeonShooting_Godot/scene/World.tscn +++ b/DungeonShooting_Godot/scene/World.tscn @@ -10,13 +10,15 @@ glow_strength = 1.05 glow_blend_mode = 1 -[node name="World" type="Node2D" node_paths=PackedStringArray("NormalLayer", "YSortLayer", "TileRoot", "StaticSpriteRoot", "AffiliationAreaRoot")] +[node name="World" type="CanvasModulate" node_paths=PackedStringArray("NormalLayer", "YSortLayer", "TileRoot", "StaticSpriteRoot", "AffiliationAreaRoot", "FogMaskRoot")] +color = Color(0, 0, 0, 1) script = ExtResource("1_kt3mm") NormalLayer = NodePath("NormalLayer") YSortLayer = NodePath("YSortLayer") TileRoot = NodePath("TileRoot") StaticSpriteRoot = NodePath("StaticSpriteRoot") AffiliationAreaRoot = NodePath("AffiliationAreaRoot") +FogMaskRoot = NodePath("FogMaskRoot") metadata/_edit_vertical_guides_ = [] [node name="WorldEnvironment" type="WorldEnvironment" parent="."] @@ -59,3 +61,5 @@ y_sort_enabled = true [node name="AffiliationAreaRoot" type="Node2D" parent="."] + +[node name="FogMaskRoot" type="Node2D" parent="."] diff --git a/DungeonShooting_Godot/scene/test/TestRoomFog.tscn b/DungeonShooting_Godot/scene/test/TestRoomFog.tscn new file mode 100644 index 0000000..87a0c1e --- /dev/null +++ b/DungeonShooting_Godot/scene/test/TestRoomFog.tscn @@ -0,0 +1,31 @@ +[gd_scene load_steps=3 format=3 uid="uid://bgbjg8virrams"] + +[ext_resource type="Texture2D" uid="uid://h7hkgbwj1li" path="res://resource/sprite/effects/common/Smoke.png" id="1_bty2r"] +[ext_resource type="Texture2D" uid="uid://uhhfgdhpk7i4" path="res://icon.png" id="1_d62vx"] + +[node name="TestRoomFog" type="Node2D"] + +[node name="PointLight2D" type="PointLight2D" parent="."] +position = Vector2(705, -196) +scale = Vector2(50, 50) +color = Color(1, 1, 1, 0.180392) +blend_mode = 2 +range_item_cull_mask = 3 +texture = ExtResource("1_bty2r") + +[node name="PointLight2D2" type="PointLight2D" parent="."] +position = Vector2(372, 65) +scale = Vector2(50, 50) +blend_mode = 2 +texture = ExtResource("1_bty2r") + +[node name="CanvasModulate" type="CanvasModulate" parent="."] +light_mask = 3 +position = Vector2(-16, 33) +color = Color(0, 0, 0, 1) + +[node name="Sprite2D" type="Sprite2D" parent="CanvasModulate"] +light_mask = 3 +position = Vector2(117, 318) +scale = Vector2(50, 46.168) +texture = ExtResource("1_d62vx") diff --git a/DungeonShooting_Godot/src/framework/activity/ActivityMaterial.cs b/DungeonShooting_Godot/src/framework/activity/ActivityMaterial.cs new file mode 100644 index 0000000..2d561fc --- /dev/null +++ b/DungeonShooting_Godot/src/framework/activity/ActivityMaterial.cs @@ -0,0 +1,8 @@ + +/// +/// 物体材质 +/// +public class ActivityMaterial +{ + +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs index 764238a..f96a52f 100644 --- a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs +++ b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs @@ -115,7 +115,7 @@ public bool IsThrowing => _throwForce != null && !_isFallOver; /// - /// 当前物体的海拔高度, 如果大于0, 则会做自由落体运动, 也就是执行投抛代码 + /// 当前物体的海拔高度, 如果大于0, 则会做自由落体运动, 也就是执行投抛逻辑 /// public float Altitude { @@ -143,11 +143,6 @@ } private float _verticalSpeed; - - /// - /// 物体投抛时旋转速度, 角度制 - /// - public float ThrowRotationDegreesSpeed { get; set; } /// /// 落地之后是否回弹 @@ -163,6 +158,11 @@ /// 物体下坠回弹后的运动速度衰减量 /// public float BounceSpeed { get; set; } = 0.75f; + + /// + /// 物体下坠回弹后的旋转速度衰减量 + /// + public float BounceRotationSpeed { get; set; } = 0.5f; /// /// 投抛状态下物体碰撞器大小, 如果 (x, y) 都小于 0, 则默认使用 AnimatedSprite 的默认动画第一帧的大小 @@ -207,6 +207,11 @@ public bool EnableCustomBehavior { get; set; } = true; /// + /// 物体材质数据 + /// + public ActivityMaterial ActivityMaterial { get; private set; } + + /// /// 所在的 World 对象 /// public World World { get; private set; } @@ -703,7 +708,7 @@ Altitude = altitude; //Position = Position + new Vector2(0, altitude); VerticalSpeed = verticalSpeed; - ThrowRotationDegreesSpeed = rotateSpeed; + //ThrowRotationDegreesSpeed = rotateSpeed; if (_throwForce != null) { MoveController.RemoveForce(_throwForce); @@ -711,6 +716,7 @@ _throwForce = new ExternalForce(ForceNames.Throw); _throwForce.Velocity = velocity; + _throwForce.RotationSpeed = Mathf.DegToRad(rotateSpeed); MoveController.AddForce(_throwForce); InitThrowData(); @@ -909,7 +915,7 @@ { if (EnableVerticalMotion) //如果启用了纵向运动, 则更新运动 { - GlobalRotationDegrees = GlobalRotationDegrees + ThrowRotationDegreesSpeed * newDelta; + //GlobalRotationDegrees = GlobalRotationDegrees + ThrowRotationDegreesSpeed * newDelta; var ysp = VerticalSpeed; @@ -944,7 +950,15 @@ OnFirstFallToGround(); } - MoveController.ScaleAllForce(BounceSpeed); + if (_throwForce != null) + { + //缩放移动速度 + //MoveController.ScaleAllForce(BounceSpeed); + _throwForce.Velocity *= BounceSpeed; + //缩放旋转速度 + //MoveController.ScaleAllRotationSpeed(BounceStrength); + _throwForce.RotationSpeed *= BounceRotationSpeed; + } //如果落地高度不够低, 再抛一次 if (Bounce && (!_hasResilienceVerticalSpeed || _resilienceVerticalSpeed > 5)) { @@ -965,7 +979,6 @@ } } _verticalSpeed = _resilienceVerticalSpeed; - ThrowRotationDegreesSpeed = ThrowRotationDegreesSpeed * BounceStrength; _isFallOver = false; OnFallToGround(); @@ -1120,14 +1133,17 @@ if (IsDebug) { DebugDraw(); - var arr = _components.ToArray(); - for (int i = 0; i < arr.Length; i++) + if (_components.Count > 0) { - if (IsDestroyed) return; - var temp = arr[i].Value; - if (temp != null && temp.ActivityInstance == this && temp.Enable) + var arr = _components.ToArray(); + for (int i = 0; i < arr.Length; i++) { - temp.DebugDraw(); + if (IsDestroyed) return; + var temp = arr[i].Value; + if (temp != null && temp.ActivityInstance == this && temp.Enable) + { + temp.DebugDraw(); + } } } } diff --git a/DungeonShooting_Godot/src/framework/activity/ExternalForce.cs b/DungeonShooting_Godot/src/framework/activity/ExternalForce.cs index 5f45e1b..02ee215 100644 --- a/DungeonShooting_Godot/src/framework/activity/ExternalForce.cs +++ b/DungeonShooting_Godot/src/framework/activity/ExternalForce.cs @@ -22,7 +22,7 @@ public bool EnableResistanceInTheAir { get; set; } = true; /// - /// 当速度(Velocity和RotationSpeed)到达 0 后是否自动销毁, 默认 true + /// 当速度( Velocity 和 RotationSpeed )到达 0 后是否自动销毁, 默认 true /// public bool AutoDestroy { get; set; } = true; diff --git a/DungeonShooting_Godot/src/framework/activity/components/MoveController.cs b/DungeonShooting_Godot/src/framework/activity/components/MoveController.cs index cff7286..36167b1 100644 --- a/DungeonShooting_Godot/src/framework/activity/components/MoveController.cs +++ b/DungeonShooting_Godot/src/framework/activity/components/MoveController.cs @@ -32,9 +32,9 @@ private Vector2 _basisVelocity = Vector2.Zero; /// - /// 缩放所有力对象, 包括基础速率 + /// 缩放所有外力对象的速率, 包括基础速率 /// - public void ScaleAllForce(float scale) + public void ScaleAllVelocity(float scale) { foreach (var externalForce in _forceList) { @@ -43,9 +43,20 @@ BasisVelocity *= scale; } + + /// + /// 缩放所有外力对象的旋转速率 + /// + public void ScaleAllRotationSpeed(float scale) + { + foreach (var externalForce in _forceList) + { + externalForce.RotationSpeed *= scale; + } + } /// - /// 给当前控制器添加指定外力速率, 并且平均分配给所有外力速率 + /// 添加外力速率, 并且平均分配给所有外力速率 /// public void AddVelocity(Vector2 velocity) { @@ -68,9 +79,28 @@ } /// - /// 设置所有力对象, 包括基础速率 + /// 添加外力旋转速率, 并且平均分配给所有外力旋转速率 /// - public void SetAllForce(Vector2 value) + public void AddRotationSpeed(float speed) + { + if (speed != 0) + { + var forceCount = GetForceCount(); + if (forceCount > 0) + { + var tempS = speed / forceCount; + for (var i = 0; i < _forceList.Count; i++) + { + _forceList[i].RotationSpeed += tempS; + } + } + } + } + + /// + /// 设置所有外力对象的速率 + /// + public void SetAllVelocity(Vector2 value) { foreach (var externalForce in _forceList) { @@ -81,6 +111,17 @@ } /// + /// 设置所有外力对象的旋转速率 + /// + public void SetAllRotationSpeed(float speed) + { + foreach (var externalForce in _forceList) + { + externalForce.RotationSpeed = speed; + } + } + + /// /// 获取所有外力对象 /// public ExternalForce[] GetAllForce() @@ -97,7 +138,7 @@ } /// - /// 快速创建一个外力, 该外力为匿名外力, 当速率变为 0 时自动销毁 + /// 快速创建一个速率外力, 该外力为匿名外力, 当速率变为 0 时自动销毁 /// /// 外力速率 /// 阻力大小 @@ -111,6 +152,20 @@ } /// + /// 快速创建一个旋转外力, 该外力为匿名外力, 当速率变为 0 时自动销毁 + /// + /// 外力旋转速率, 弧度制 + /// 阻力大小 + public ExternalForce AddForce(float rotationSpeed, float resistance) + { + var force = AddForce("_anonymity_" + _index++); + force.AutoDestroy = true; + force.RotationSpeed = rotationSpeed; + force.RotationResistance = resistance; + return force; + } + + /// /// 快速创建一个外力, 该外力为匿名外力, 当速率变为 0 时自动销毁 /// /// 外力速率 @@ -216,33 +271,33 @@ return; } - //先调用更新 - var externalForces = _forceList.ToArray(); - for (var i = 0; i < externalForces.Length; i++) - { - var force = externalForces[i]; - if (force.Enable) - { - force.PhysicsProcess(delta); - //自动销毁 - if (CheckAutoDestroy(force)) - { - _forceList.Remove(force); - externalForces[i] = null; - } - } - } - //外力总和 var finallyEf = new Vector2(); //旋转速率总和 var rotationSpeed = 0f; - foreach (var force in externalForces) + + //先调用更新 + if (_forceList.Count > 0) { - if (force != null && force.Enable) + var externalForces = _forceList.ToArray(); + for (var i = 0; i < externalForces.Length; i++) { - finallyEf += force.Velocity; - rotationSpeed += force.RotationSpeed; + var force = externalForces[i]; + if (force.Enable) + { + force.PhysicsProcess(delta); + //自动销毁 + if (CheckAutoDestroy(force)) + { + _forceList.Remove(force); + externalForces[i] = null; + } + else + { + finallyEf += force.Velocity; + rotationSpeed += force.RotationSpeed; + } + } } } diff --git a/DungeonShooting_Godot/src/framework/common/Utils.cs b/DungeonShooting_Godot/src/framework/common/Utils.cs index b6c9f4d..1b62786 100644 --- a/DungeonShooting_Godot/src/framework/common/Utils.cs +++ b/DungeonShooting_Godot/src/framework/common/Utils.cs @@ -17,7 +17,7 @@ } /// - /// 根据四个点计算出矩形 + /// 根据两个点计算出矩形 /// public static Rect2 CalcRect(float start1, float end1, float start2, float end2) { diff --git a/DungeonShooting_Godot/src/framework/coroutine/ProxyCoroutineHandler.cs b/DungeonShooting_Godot/src/framework/coroutine/ProxyCoroutineHandler.cs index 5592d76..ed04749 100644 --- a/DungeonShooting_Godot/src/framework/coroutine/ProxyCoroutineHandler.cs +++ b/DungeonShooting_Godot/src/framework/coroutine/ProxyCoroutineHandler.cs @@ -15,6 +15,10 @@ /// public static void ProxyUpdateCoroutine(ref List coroutineList, float delta) { + if (coroutineList.Count == 0) + { + return; + } var pairs = coroutineList.ToArray(); for (var i = 0; i < pairs.Length; i++) { @@ -77,17 +81,7 @@ if (item.Enumerator.MoveNext()) { var next = item.Enumerator.Current; - if (next is IEnumerable enumerable) //嵌套协程 - { - if (item.EnumeratorStack == null) - { - item.EnumeratorStack = new Stack(); - } - - item.EnumeratorStack.Push(item.Enumerator); - item.Enumerator = enumerable.GetEnumerator(); - } - else if (next is IEnumerator enumerator) //嵌套协程 + if (next is IEnumerator enumerator) //嵌套协程 { if (item.EnumeratorStack == null) { @@ -97,6 +91,16 @@ item.EnumeratorStack.Push(item.Enumerator); item.Enumerator = enumerator; } + else if (next is IEnumerable enumerable) //嵌套协程 + { + if (item.EnumeratorStack == null) + { + item.EnumeratorStack = new Stack(); + } + + item.EnumeratorStack.Push(item.Enumerator); + item.Enumerator = enumerable.GetEnumerator(); + } else if (next is WaitForSeconds seconds) //等待秒数 { item.WaitFor(seconds); diff --git a/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs b/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs index a2cb922..e627e82 100644 --- a/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs +++ b/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs @@ -37,7 +37,7 @@ /// /// 根据矩形区域初始化归属区域 /// - public void Init(RoomInfo roomInfo, Rect2 rect2) + public void Init(RoomInfo roomInfo, Rect2I rect2) { if (_init) { diff --git a/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs b/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs index 5c83e0b..08beefa 100644 --- a/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs +++ b/DungeonShooting_Godot/src/framework/map/DungeonGenerator.cs @@ -1,5 +1,6 @@ using System; +using System.Collections; using System.Collections.Generic; using Godot; @@ -27,11 +28,11 @@ /// boss房间 /// public List BossRoom { get; } = new List(); - + /// /// 随机数对象 /// - public SeedRandom Random { get; } + private SeedRandom _random; //用于标记地图上的坐标是否被占用 private Grid _roomGrid { get; } = new Grid(); @@ -86,9 +87,10 @@ // NoProperDoor, } - public DungeonGenerator(DungeonConfig config) + public DungeonGenerator(DungeonConfig config, SeedRandom seedRandom) { _config = config; + _random = seedRandom; _roomGroup = GameApplication.Instance.RoomConfig[config.GroupName]; //验证该组是否满足生成地牢的条件 @@ -98,9 +100,8 @@ throw new Exception("当前组'" + config.GroupName + "'" + result.ErrorMessage + ", 不能生成地牢!"); } - Random = new SeedRandom(); - GD.Print("创建地牢生成器, 随机种子: " + Random.Seed); - _roomGroup.InitWeight(Random); + GD.Print("创建地牢生成器, 随机种子: " + _random.Seed); + _roomGroup.InitWeight(_random); } /// @@ -124,6 +125,28 @@ EachRoom(next, cb); } } + + /// + /// 用于协程中的遍历所有房间 + /// + public IEnumerator EachRoomCoroutine(Action cb) + { + return EachRoomCoroutine(StartRoomInfo, cb); + } + + private IEnumerator EachRoomCoroutine(RoomInfo roomInfo, Action cb) + { + if (roomInfo == null) + { + yield break; + } + + cb(roomInfo); + foreach (var next in roomInfo.Next) + { + yield return EachRoomCoroutine(next, cb); + } + } /// /// 生成房间 @@ -175,12 +198,12 @@ } else { - tempPrevRoomInfo = Random.RandomChoose(RoomInfos); + tempPrevRoomInfo = _random.RandomChoose(RoomInfos); } } else { - tempPrevRoomInfo = Random.RandomChoose(RoomInfos); + tempPrevRoomInfo = _random.RandomChoose(RoomInfos); } //生成下一个房间 @@ -205,7 +228,7 @@ else if (nextRoomType == DungeonRoomType.Battle) { chainTryCount = 0; - chainMaxTryCount = Random.RandomRangeInt(1, 3); + chainMaxTryCount = _random.RandomRangeInt(1, 3); } prevRoomInfo = nextRoom; CalcNextRoomType(prevRoomInfo); @@ -269,7 +292,7 @@ DungeonRoomSplit roomSplit; if (_config.HasDesignatedRoom && _config.DesignatedType == roomType) //执行指定了房间 { - roomSplit = Random.RandomChoose(_config.DesignatedRoom); + roomSplit = _random.RandomChoose(_config.DesignatedRoom); } else //没有指定房间 { @@ -310,19 +333,19 @@ } for (; tryCount < maxTryCount; tryCount++) { - var direction = Random.RandomRangeInt(0, 3); + var direction = _random.RandomRangeInt(0, 3); //房间间隔 - var space = Random.RandomRangeInt(_roomMinInterval, _roomMaxInterval); + var space = _random.RandomRangeInt(_roomMinInterval, _roomMaxInterval); //中心偏移 int offset; if (direction == 0 || direction == 2) { - offset = Random.RandomRangeInt(-(int)(prevRoomInfo.Size.X * _roomVerticalMinDispersion), + offset = _random.RandomRangeInt(-(int)(prevRoomInfo.Size.X * _roomVerticalMinDispersion), (int)(prevRoomInfo.Size.X * _roomVerticalMaxDispersion)); } else { - offset = Random.RandomRangeInt(-(int)(prevRoomInfo.Size.Y * _roomHorizontalMinDispersion), + offset = _random.RandomRangeInt(-(int)(prevRoomInfo.Size.Y * _roomHorizontalMinDispersion), (int)(prevRoomInfo.Size.Y * _roomHorizontalMaxDispersion)); } @@ -521,7 +544,7 @@ } } - return Random.RandomChoose(list); + return _random.RandomChoose(list); } /// @@ -540,7 +563,7 @@ nextRoomDoor.ConnectDoor = roomDoor; //先寻找直通门 - if (Random.RandomBoolean()) + if (_random.RandomBoolean()) { //直行通道, 优先横轴 if (TryConnectHorizontalDoor(roomInfo, roomDoor, nextRoomInfo, nextRoomDoor) @@ -580,8 +603,8 @@ while (rangeList.Count > 0) { //找到重叠区域 - var range = Random.RandomChooseAndRemove(rangeList); - var x = Random.RandomRangeInt(range.X, range.Y); + var range = _random.RandomChooseAndRemove(rangeList); + var x = _random.RandomRangeInt(range.X, range.Y); if (roomInfo.GetVerticalStart() < nextRoomInfo.GetVerticalStart()) //room在上, nextRoom在下 { @@ -632,8 +655,8 @@ while (rangeList.Count > 0) { //找到重叠区域 - var range = Random.RandomChooseAndRemove(rangeList); - var y = Random.RandomRangeInt(range.X, range.Y); + var range = _random.RandomChooseAndRemove(rangeList); + var y = _random.RandomRangeInt(range.X, range.Y); if (roomInfo.GetHorizontalStart() < nextRoomInfo.GetHorizontalStart()) //room在左, nextRoom在右 { @@ -679,7 +702,7 @@ { if (roomInfo.GetVerticalStart() > nextRoomInfo.GetVerticalStart()) { - if (Random.RandomBoolean()) //↑ //→ + if (_random.RandomBoolean()) //↑ //→ { if (!TryConnect_NE_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) && !TryConnect_WS_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross)) @@ -698,7 +721,7 @@ } else { - if (Random.RandomBoolean()) //↓ //→ + if (_random.RandomBoolean()) //↓ //→ { if (!TryConnect_SE_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) && !TryConnect_WN_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross)) @@ -720,7 +743,7 @@ { if (roomInfo.GetVerticalStart() > nextRoomInfo.GetVerticalStart()) //→ //↓ { - if (Random.RandomBoolean()) + if (_random.RandomBoolean()) { if (!TryConnect_ES_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) && !TryConnect_NW_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross)) @@ -739,7 +762,7 @@ } else { - if (Random.RandomBoolean()) //→ //↑ + if (_random.RandomBoolean()) //→ //↑ { if (!TryConnect_EN_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross) && !TryConnect_SW_Door(roomInfo, nextRoomInfo, roomDoor, nextRoomDoor, ref cross)) diff --git a/DungeonShooting_Godot/src/framework/map/DungeonTileMap.cs b/DungeonShooting_Godot/src/framework/map/DungeonTileMap.cs index ffdb00d..bd3aae9 100644 --- a/DungeonShooting_Godot/src/framework/map/DungeonTileMap.cs +++ b/DungeonShooting_Godot/src/framework/map/DungeonTileMap.cs @@ -1,4 +1,5 @@ +using System.Collections; using System.Collections.Generic; using System.Linq; using Godot; @@ -33,23 +34,23 @@ } /// - /// 根据 startRoom 和 config 数据自动填充 tileMap 参数中的地图数据 + /// 根据 startRoom 和 config 数据自动填充 tileMap 参数中的地图数据, 该函数为协程函数 /// - public void AutoFillRoomTile(AutoTileConfig config, RoomInfo startRoomInfo, SeedRandom random) + public IEnumerator AutoFillRoomTile(AutoTileConfig config, RoomInfo startRoomInfo, SeedRandom random) { _connectNavigationItemList.Clear(); - _AutoFillRoomTile(config, startRoomInfo, random); + yield return _AutoFillRoomTile(config, startRoomInfo, random); } - private void _AutoFillRoomTile(AutoTileConfig config, RoomInfo roomInfo, SeedRandom random) + private IEnumerator _AutoFillRoomTile(AutoTileConfig config, RoomInfo roomInfo, SeedRandom random) { foreach (var info in roomInfo.Next) { - _AutoFillRoomTile(config, info, random); + yield return _AutoFillRoomTile(config, info, random); } //铺房间 - if (roomInfo.RoomSplit == null) + if (roomInfo.RoomSplit == null) //自动填充的矩形房间, 现已经弃用 { FillRect(GameConfig.FloorMapLayer, config.Floor, roomInfo.Position + Vector2.One, roomInfo.Size - new Vector2(2, 2)); @@ -79,6 +80,7 @@ //填充tile操作 var tileInfo = roomInfo.RoomSplit.TileInfo; + //底层 for (var i = 0; i < tileInfo.Floor.Count; i += 5) { var posX = tileInfo.Floor[i]; @@ -89,6 +91,7 @@ var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y); _tileRoot.SetCell(GameConfig.FloorMapLayer, pos, sourceId, new Vector2I(atlasCoordsX, atlasCoordsY)); } + //中层 for (var i = 0; i < tileInfo.Middle.Count; i += 5) { var posX = tileInfo.Middle[i]; @@ -99,6 +102,7 @@ var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y); _tileRoot.SetCell(GameConfig.MiddleMapLayer, pos, sourceId, new Vector2I(atlasCoordsX, atlasCoordsY)); } + //顶层 for (var i = 0; i < tileInfo.Top.Count; i += 5) { var posX = tileInfo.Top[i]; @@ -109,6 +113,7 @@ var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y); _tileRoot.SetCell(GameConfig.TopMapLayer, pos, sourceId, new Vector2I(atlasCoordsX, atlasCoordsY)); } + //随机选择预设 RoomPreinstallInfo preinstallInfo; if (EditorPlayManager.IsPlay && roomInfo.RoomType == GameApplication.Instance.DungeonManager.CurrConfig.DesignatedType) //编辑器模式, 指定预设 @@ -188,7 +193,7 @@ // { // // 在 Godot 4.0 中使用以下这段代码区分层级, 会导致游戏关闭时有概率报错卡死, 目前尚不清楚原因 // //获取自定义层级 - // // var customData = tileInstance.GetCellTileData(0, coords).GetCustomData(CustomTileLayerName); + // // var customData = tileInstance.GetCellSourceId(0, coords).GetCustomData(CustomTileLayerName); // // var layer = customData.AsInt32(); // // layer = Mathf.Clamp(layer, GameConfig.FloorMapLayer, GameConfig.TopMapLayer); // @@ -202,271 +207,346 @@ // tileInstance.CallDeferred(Node.MethodName.QueueFree); } + var doors = roomInfo.GetForwardDoors(); //铺过道 - foreach (var doorInfo in roomInfo.Doors) + foreach (var doorInfo in doors) { - if (doorInfo.ConnectRoom.Id > roomInfo.Id) + //普通的直线连接 + var doorDir1 = doorInfo.Direction; + var doorDir2 = doorInfo.ConnectDoor.Direction; + if (!doorInfo.HasCross) { - //普通的直线连接 - var doorDir1 = doorInfo.Direction; - var doorDir2 = doorInfo.ConnectDoor.Direction; - if (!doorInfo.HasCross) + var rect = Utils.CalcRect( + doorInfo.OriginPosition.X, + doorInfo.OriginPosition.Y, + doorInfo.ConnectDoor.OriginPosition.X, + doorInfo.ConnectDoor.OriginPosition.Y + ); + + switch (doorDir1) { - var rect = Utils.CalcRect( - doorInfo.OriginPosition.X, - doorInfo.OriginPosition.Y, - doorInfo.ConnectDoor.OriginPosition.X, - doorInfo.ConnectDoor.OriginPosition.Y - ); - - switch (doorDir1) - { - case DoorDirection.E: - rect.Size = new Vector2(rect.Size.X, GameConfig.CorridorWidth); - FullHorizontalAisle(config, rect); - FullHorizontalAisleLeft(config, rect, doorInfo); - FullHorizontalAisleRight(config, rect, doorInfo.ConnectDoor); - break; - case DoorDirection.W: - rect.Size = new Vector2(rect.Size.X, GameConfig.CorridorWidth); - FullHorizontalAisle(config, rect); - FullHorizontalAisleLeft(config, rect, doorInfo.ConnectDoor); - FullHorizontalAisleRight(config, rect, doorInfo); - break; - - case DoorDirection.S: - rect.Size = new Vector2(GameConfig.CorridorWidth, rect.Size.Y); - FullVerticalAisle(config, rect); - FullVerticalAisleUp(config, rect, doorInfo); - FullVerticalAisleDown(config, rect, doorInfo.ConnectDoor); - break; - case DoorDirection.N: - rect.Size = new Vector2(GameConfig.CorridorWidth, rect.Size.Y); - FullVerticalAisle(config, rect); - FullVerticalAisleUp(config, rect, doorInfo.ConnectDoor); - FullVerticalAisleDown(config, rect, doorInfo); - break; - } - } - else //带交叉点 - { - //方向, 0横向, 1纵向 - var dir1 = 0; - var dir2 = 0; - - Rect2 rect; - Rect2 rect2; - - //计算范围 - switch (doorDir1) - { - case DoorDirection.E: //→ - rect = new Rect2( - doorInfo.OriginPosition.X, - doorInfo.OriginPosition.Y, - doorInfo.Cross.X - doorInfo.OriginPosition.X, - GameConfig.CorridorWidth - ); - break; - case DoorDirection.W: //← - rect = new Rect2( - doorInfo.Cross.X + GameConfig.CorridorWidth, - doorInfo.Cross.Y, - doorInfo.OriginPosition.X - (doorInfo.Cross.X + GameConfig.CorridorWidth), - GameConfig.CorridorWidth - ); - break; - case DoorDirection.S: //↓ - dir1 = 1; - rect = new Rect2( - doorInfo.OriginPosition.X, - doorInfo.OriginPosition.Y, - GameConfig.CorridorWidth, - doorInfo.Cross.Y - doorInfo.OriginPosition.Y - ); - break; - case DoorDirection.N: //↑ - dir1 = 1; - rect = new Rect2( - doorInfo.Cross.X, - doorInfo.Cross.Y + GameConfig.CorridorWidth, - GameConfig.CorridorWidth, - doorInfo.OriginPosition.Y - (doorInfo.Cross.Y + GameConfig.CorridorWidth) - ); - break; - default: - rect = new Rect2(); - break; - } - - switch (doorDir2) - { - case DoorDirection.E: //→ - rect2 = new Rect2( - doorInfo.ConnectDoor.OriginPosition.X, - doorInfo.ConnectDoor.OriginPosition.Y, - doorInfo.Cross.X - doorInfo.ConnectDoor.OriginPosition.X, - GameConfig.CorridorWidth - ); - break; - case DoorDirection.W: //← - rect2 = new Rect2( - doorInfo.Cross.X + GameConfig.CorridorWidth, - doorInfo.Cross.Y, - doorInfo.ConnectDoor.OriginPosition.X - - (doorInfo.Cross.X + GameConfig.CorridorWidth), - GameConfig.CorridorWidth - ); - break; - case DoorDirection.S: //↓ - dir2 = 1; - rect2 = new Rect2( - doorInfo.ConnectDoor.OriginPosition.X, - doorInfo.ConnectDoor.OriginPosition.Y, - GameConfig.CorridorWidth, - doorInfo.Cross.Y - doorInfo.ConnectDoor.OriginPosition.Y - ); - break; - case DoorDirection.N: //↑ - dir2 = 1; - rect2 = new Rect2( - doorInfo.Cross.X, - doorInfo.Cross.Y + GameConfig.CorridorWidth, - GameConfig.CorridorWidth, - doorInfo.ConnectDoor.OriginPosition.Y - - (doorInfo.Cross.Y + GameConfig.CorridorWidth) - ); - break; - default: - rect2 = new Rect2(); - break; - } - - FillRect(GameConfig.AisleFloorMapLayer, config.Floor, doorInfo.Cross + Vector2.One, - new Vector2(GameConfig.CorridorWidth - 2, GameConfig.CorridorWidth - 2)); - - //墙壁, 0横向, 1纵向 - if (dir1 == 0) - { + case DoorDirection.E: + rect.Size = new Vector2(rect.Size.X, GameConfig.CorridorWidth); FullHorizontalAisle(config, rect); - FullHorizontalAisleLeft(config, rect, doorDir1 == DoorDirection.E ? doorInfo : null); - FullHorizontalAisleRight(config, rect, doorDir1 == DoorDirection.W ? doorInfo : null); - } - else - { + FullHorizontalAisleLeft(config, rect, doorInfo); + FullHorizontalAisleRight(config, rect, doorInfo.ConnectDoor); + break; + case DoorDirection.W: + rect.Size = new Vector2(rect.Size.X, GameConfig.CorridorWidth); + FullHorizontalAisle(config, rect); + FullHorizontalAisleLeft(config, rect, doorInfo.ConnectDoor); + FullHorizontalAisleRight(config, rect, doorInfo); + break; + + case DoorDirection.S: + rect.Size = new Vector2(GameConfig.CorridorWidth, rect.Size.Y); FullVerticalAisle(config, rect); - FullVerticalAisleUp(config, rect, doorDir1 == DoorDirection.S ? doorInfo : null); - FullVerticalAisleDown(config, rect, doorDir1 == DoorDirection.N ? doorInfo : null); - } - - if (dir2 == 0) - { - FullHorizontalAisle(config, rect2); - FullHorizontalAisleLeft(config, rect2, doorDir2 == DoorDirection.E ? doorInfo.ConnectDoor : null); - FullHorizontalAisleRight(config, rect2, doorDir2 == DoorDirection.W ? doorInfo.ConnectDoor : null); - } - else - { - FullVerticalAisle(config, rect2); - FullVerticalAisleUp(config, rect2, doorDir2 == DoorDirection.S ? doorInfo.ConnectDoor : null); - FullVerticalAisleDown(config, rect2, doorDir2 == DoorDirection.N ? doorInfo.ConnectDoor : null); - } - - if ((doorDir1 == DoorDirection.N && doorDir2 == DoorDirection.E) || //↑→ - (doorDir2 == DoorDirection.N && doorDir1 == DoorDirection.E)) - { - FillRect(GameConfig.TopMapLayer, config.OUT_RT, - doorInfo.Cross + new Vector2(0, GameConfig.CorridorWidth - 1), - Vector2.One); - FillRect(GameConfig.TopMapLayer, config.IN_RT, doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, 0), - Vector2.One); - FillRect(GameConfig.MiddleMapLayer, config.T, doorInfo.Cross, new Vector2(GameConfig.CorridorWidth - 1, 1)); - FillRect(GameConfig.TopMapLayer, config.R, doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, 1), - new Vector2(1, GameConfig.CorridorWidth - 1)); - } - else if ((doorDir1 == DoorDirection.E && doorDir2 == DoorDirection.S) || //→↓ - (doorDir2 == DoorDirection.E && doorDir1 == DoorDirection.S)) - { - FillRect(GameConfig.MiddleMapLayer, config.OUT_RB, doorInfo.Cross, Vector2.One); - FillRect(GameConfig.TopMapLayer, config.IN_RB, - doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, - GameConfig.CorridorWidth - 1), - Vector2.One); - FillRect(GameConfig.TopMapLayer, config.R, doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, 0), - new Vector2(1, GameConfig.CorridorWidth - 1)); - FillRect(GameConfig.TopMapLayer, config.B, doorInfo.Cross + new Vector2(0, GameConfig.CorridorWidth - 1), - new Vector2(GameConfig.CorridorWidth - 1, 1)); - } - else if ((doorDir1 == DoorDirection.S && doorDir2 == DoorDirection.W) || //↓← - (doorDir2 == DoorDirection.S && doorDir1 == DoorDirection.W)) - { - FillRect(GameConfig.MiddleMapLayer, config.OUT_LB, - doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, 0), Vector2.One); - FillRect(GameConfig.TopMapLayer, config.IN_LB, doorInfo.Cross + new Vector2(0, GameConfig.CorridorWidth - 1), - Vector2.One); - FillRect(GameConfig.TopMapLayer, config.L, doorInfo.Cross, new Vector2(1, GameConfig.CorridorWidth - 1)); - FillRect(GameConfig.TopMapLayer, config.B, doorInfo.Cross + new Vector2(1, GameConfig.CorridorWidth - 1), - new Vector2(GameConfig.CorridorWidth - 1, 1)); - } - else if ((doorDir1 == DoorDirection.W && doorDir2 == DoorDirection.N) || //←↑ - (doorDir2 == DoorDirection.W && doorDir1 == DoorDirection.N)) - { - FillRect(GameConfig.TopMapLayer, config.OUT_LT, - doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, - GameConfig.CorridorWidth - 1), - Vector2.One); - FillRect(GameConfig.TopMapLayer, config.IN_LT, doorInfo.Cross, Vector2.One); - FillRect(GameConfig.MiddleMapLayer, config.T, doorInfo.Cross + new Vector2(1, 0), - new Vector2(GameConfig.CorridorWidth - 1, 1)); - FillRect(GameConfig.TopMapLayer, config.L, doorInfo.Cross + new Vector2(0, 1), - new Vector2(1, GameConfig.CorridorWidth - 1)); - } - - //在房间墙上开洞 - switch (doorDir1) - { - case DoorDirection.E: //→ - ClearRect(GameConfig.TopMapLayer, doorInfo.OriginPosition + new Vector2(-1, 1), - new Vector2(1, rect.Size.Y - 2)); - break; - case DoorDirection.W: //← - ClearRect(GameConfig.TopMapLayer, doorInfo.OriginPosition + new Vector2(0, 1), - new Vector2(1, rect.Size.Y - 2)); - break; - case DoorDirection.S: //↓ - ClearRect(GameConfig.TopMapLayer, doorInfo.OriginPosition + new Vector2(1, -1), - new Vector2(rect.Size.X - 2, 1)); - break; - case DoorDirection.N: //↑ - ClearRect(GameConfig.MiddleMapLayer, doorInfo.OriginPosition + new Vector2(1, 2), - new Vector2(rect.Size.X - 2, 1)); - break; - } - - switch (doorDir2) - { - case DoorDirection.E: //→ - ClearRect(GameConfig.TopMapLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(-1, 1), - new Vector2(1, rect2.Size.Y - 2)); - break; - case DoorDirection.W: //← - ClearRect(GameConfig.TopMapLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(0, 1), - new Vector2(1, rect2.Size.Y - 2)); - break; - case DoorDirection.S: //↓ - ClearRect(GameConfig.TopMapLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(1, -1), - new Vector2(rect2.Size.X - 2, 1)); - break; - case DoorDirection.N: //↑ - ClearRect(GameConfig.MiddleMapLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(1, 0), - new Vector2(rect2.Size.X - 2, 1)); - break; - } + FullVerticalAisleUp(config, rect, doorInfo); + FullVerticalAisleDown(config, rect, doorInfo.ConnectDoor); + break; + case DoorDirection.N: + rect.Size = new Vector2(GameConfig.CorridorWidth, rect.Size.Y); + FullVerticalAisle(config, rect); + FullVerticalAisleUp(config, rect, doorInfo.ConnectDoor); + FullVerticalAisleDown(config, rect, doorInfo); + break; + } + } + else //带交叉点 + { + //方向, 0横向, 1纵向 + var dir1 = 0; + var dir2 = 0; + + Rect2 rect; + Rect2 rect2; + + //计算范围 + switch (doorDir1) + { + case DoorDirection.E: //→ + rect = new Rect2( + doorInfo.OriginPosition.X, + doorInfo.OriginPosition.Y, + doorInfo.Cross.X - doorInfo.OriginPosition.X, + GameConfig.CorridorWidth + ); + break; + case DoorDirection.W: //← + rect = new Rect2( + doorInfo.Cross.X + GameConfig.CorridorWidth, + doorInfo.Cross.Y, + doorInfo.OriginPosition.X - (doorInfo.Cross.X + GameConfig.CorridorWidth), + GameConfig.CorridorWidth + ); + break; + case DoorDirection.S: //↓ + dir1 = 1; + rect = new Rect2( + doorInfo.OriginPosition.X, + doorInfo.OriginPosition.Y, + GameConfig.CorridorWidth, + doorInfo.Cross.Y - doorInfo.OriginPosition.Y + ); + break; + case DoorDirection.N: //↑ + dir1 = 1; + rect = new Rect2( + doorInfo.Cross.X, + doorInfo.Cross.Y + GameConfig.CorridorWidth, + GameConfig.CorridorWidth, + doorInfo.OriginPosition.Y - (doorInfo.Cross.Y + GameConfig.CorridorWidth) + ); + break; + default: + rect = new Rect2(); + break; + } + + switch (doorDir2) + { + case DoorDirection.E: //→ + rect2 = new Rect2( + doorInfo.ConnectDoor.OriginPosition.X, + doorInfo.ConnectDoor.OriginPosition.Y, + doorInfo.Cross.X - doorInfo.ConnectDoor.OriginPosition.X, + GameConfig.CorridorWidth + ); + break; + case DoorDirection.W: //← + rect2 = new Rect2( + doorInfo.Cross.X + GameConfig.CorridorWidth, + doorInfo.Cross.Y, + doorInfo.ConnectDoor.OriginPosition.X - + (doorInfo.Cross.X + GameConfig.CorridorWidth), + GameConfig.CorridorWidth + ); + break; + case DoorDirection.S: //↓ + dir2 = 1; + rect2 = new Rect2( + doorInfo.ConnectDoor.OriginPosition.X, + doorInfo.ConnectDoor.OriginPosition.Y, + GameConfig.CorridorWidth, + doorInfo.Cross.Y - doorInfo.ConnectDoor.OriginPosition.Y + ); + break; + case DoorDirection.N: //↑ + dir2 = 1; + rect2 = new Rect2( + doorInfo.Cross.X, + doorInfo.Cross.Y + GameConfig.CorridorWidth, + GameConfig.CorridorWidth, + doorInfo.ConnectDoor.OriginPosition.Y - + (doorInfo.Cross.Y + GameConfig.CorridorWidth) + ); + break; + default: + rect2 = new Rect2(); + break; + } + + FillRect(GameConfig.AisleFloorMapLayer, config.Floor, doorInfo.Cross + Vector2.One, + new Vector2(GameConfig.CorridorWidth - 2, GameConfig.CorridorWidth - 2)); + + //墙壁, 0横向, 1纵向 + if (dir1 == 0) + { + FullHorizontalAisle(config, rect); + FullHorizontalAisleLeft(config, rect, doorDir1 == DoorDirection.E ? doorInfo : null); + FullHorizontalAisleRight(config, rect, doorDir1 == DoorDirection.W ? doorInfo : null); + } + else + { + FullVerticalAisle(config, rect); + FullVerticalAisleUp(config, rect, doorDir1 == DoorDirection.S ? doorInfo : null); + FullVerticalAisleDown(config, rect, doorDir1 == DoorDirection.N ? doorInfo : null); + } + + if (dir2 == 0) + { + FullHorizontalAisle(config, rect2); + FullHorizontalAisleLeft(config, rect2, doorDir2 == DoorDirection.E ? doorInfo.ConnectDoor : null); + FullHorizontalAisleRight(config, rect2, doorDir2 == DoorDirection.W ? doorInfo.ConnectDoor : null); + } + else + { + FullVerticalAisle(config, rect2); + FullVerticalAisleUp(config, rect2, doorDir2 == DoorDirection.S ? doorInfo.ConnectDoor : null); + FullVerticalAisleDown(config, rect2, doorDir2 == DoorDirection.N ? doorInfo.ConnectDoor : null); + } + + if ((doorDir1 == DoorDirection.N && doorDir2 == DoorDirection.E) || //↑→ + (doorDir2 == DoorDirection.N && doorDir1 == DoorDirection.E)) + { + FillRect(GameConfig.TopMapLayer, config.OUT_RT, + doorInfo.Cross + new Vector2(0, GameConfig.CorridorWidth - 1), + Vector2.One); + FillRect(GameConfig.TopMapLayer, config.IN_RT, doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, 0), + Vector2.One); + FillRect(GameConfig.MiddleMapLayer, config.T, doorInfo.Cross, new Vector2(GameConfig.CorridorWidth - 1, 1)); + FillRect(GameConfig.TopMapLayer, config.R, doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, 1), + new Vector2(1, GameConfig.CorridorWidth - 1)); + } + else if ((doorDir1 == DoorDirection.E && doorDir2 == DoorDirection.S) || //→↓ + (doorDir2 == DoorDirection.E && doorDir1 == DoorDirection.S)) + { + FillRect(GameConfig.MiddleMapLayer, config.OUT_RB, doorInfo.Cross, Vector2.One); + FillRect(GameConfig.TopMapLayer, config.IN_RB, + doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, + GameConfig.CorridorWidth - 1), + Vector2.One); + FillRect(GameConfig.TopMapLayer, config.R, doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, 0), + new Vector2(1, GameConfig.CorridorWidth - 1)); + FillRect(GameConfig.TopMapLayer, config.B, doorInfo.Cross + new Vector2(0, GameConfig.CorridorWidth - 1), + new Vector2(GameConfig.CorridorWidth - 1, 1)); + } + else if ((doorDir1 == DoorDirection.S && doorDir2 == DoorDirection.W) || //↓← + (doorDir2 == DoorDirection.S && doorDir1 == DoorDirection.W)) + { + FillRect(GameConfig.MiddleMapLayer, config.OUT_LB, + doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, 0), Vector2.One); + FillRect(GameConfig.TopMapLayer, config.IN_LB, doorInfo.Cross + new Vector2(0, GameConfig.CorridorWidth - 1), + Vector2.One); + FillRect(GameConfig.TopMapLayer, config.L, doorInfo.Cross, new Vector2(1, GameConfig.CorridorWidth - 1)); + FillRect(GameConfig.TopMapLayer, config.B, doorInfo.Cross + new Vector2(1, GameConfig.CorridorWidth - 1), + new Vector2(GameConfig.CorridorWidth - 1, 1)); + } + else if ((doorDir1 == DoorDirection.W && doorDir2 == DoorDirection.N) || //←↑ + (doorDir2 == DoorDirection.W && doorDir1 == DoorDirection.N)) + { + FillRect(GameConfig.TopMapLayer, config.OUT_LT, + doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, + GameConfig.CorridorWidth - 1), + Vector2.One); + FillRect(GameConfig.TopMapLayer, config.IN_LT, doorInfo.Cross, Vector2.One); + FillRect(GameConfig.MiddleMapLayer, config.T, doorInfo.Cross + new Vector2(1, 0), + new Vector2(GameConfig.CorridorWidth - 1, 1)); + FillRect(GameConfig.TopMapLayer, config.L, doorInfo.Cross + new Vector2(0, 1), + new Vector2(1, GameConfig.CorridorWidth - 1)); + } + + //在房间墙上开洞 + switch (doorDir1) + { + case DoorDirection.E: //→ + ClearRect(GameConfig.TopMapLayer, doorInfo.OriginPosition + new Vector2(-1, 1), + new Vector2(1, rect.Size.Y - 2)); + break; + case DoorDirection.W: //← + ClearRect(GameConfig.TopMapLayer, doorInfo.OriginPosition + new Vector2(0, 1), + new Vector2(1, rect.Size.Y - 2)); + break; + case DoorDirection.S: //↓ + ClearRect(GameConfig.TopMapLayer, doorInfo.OriginPosition + new Vector2(1, -1), + new Vector2(rect.Size.X - 2, 1)); + break; + case DoorDirection.N: //↑ + ClearRect(GameConfig.MiddleMapLayer, doorInfo.OriginPosition + new Vector2(1, 2), + new Vector2(rect.Size.X - 2, 1)); + break; + } + + switch (doorDir2) + { + case DoorDirection.E: //→ + ClearRect(GameConfig.TopMapLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(-1, 1), + new Vector2(1, rect2.Size.Y - 2)); + break; + case DoorDirection.W: //← + ClearRect(GameConfig.TopMapLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(0, 1), + new Vector2(1, rect2.Size.Y - 2)); + break; + case DoorDirection.S: //↓ + ClearRect(GameConfig.TopMapLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(1, -1), + new Vector2(rect2.Size.X - 2, 1)); + break; + case DoorDirection.N: //↑ + ClearRect(GameConfig.MiddleMapLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(1, 0), + new Vector2(rect2.Size.X - 2, 1)); + break; } } } } + /// + /// 给TileMap添加轮廓, 该函数为协程函数 + /// + /// 描轮廓的Tile + public IEnumerator AddOutlineTile(TileCellInfo tileCellInfo) + { + var c = 0; + var rect = _tileRoot.GetUsedRect(); + var endX = rect.End.X + 1; + var endY = rect.End.Y + 1; + for (int x = rect.Position.X - 1; x <= endX; x++) + { + for (int y = rect.Position.Y - 1; y <= endY; y++) + { + if (c++ > 1000) //份帧处理, 不要挤在一帧 + { + c = 0; + yield return 0; + } + var pos = new Vector2I(x, y); + var flag1 = _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, pos) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, pos) != -1 || + _tileRoot.GetCellSourceId(GameConfig.AisleFloorMapLayer, pos) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, pos) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, pos) != tileCellInfo.AutoTileCoord); + if (!flag1) //空地 + { + var posDown = new Vector2I(pos.X, pos.Y + 1); + var posTop = new Vector2I(pos.X, pos.Y - 1); + var posLeft = new Vector2I(pos.X - 1, pos.Y); + var posRight = new Vector2I(pos.X + 1, pos.Y); + + var posLD = new Vector2I(pos.X - 1, pos.Y + 1); + var posLT = new Vector2I(pos.X - 1, pos.Y - 1); + var posRD = new Vector2I(pos.X + 1, pos.Y + 1); + var posRT = new Vector2I(pos.X + 1, pos.Y - 1); + + var flag2 = _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posDown) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posDown) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posDown) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posDown) != tileCellInfo.AutoTileCoord) || + + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posTop) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posTop) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posTop) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posTop) != tileCellInfo.AutoTileCoord) || + + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posLeft) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posLeft) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posLeft) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posLeft) != tileCellInfo.AutoTileCoord) || + + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posRight) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posRight) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posRight) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posRight) != tileCellInfo.AutoTileCoord) || + // + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posLD) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posLD) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posLD) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posLD) != tileCellInfo.AutoTileCoord) || + + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posLT) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posLT) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posLT) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posLT) != tileCellInfo.AutoTileCoord) || + + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posRD) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posRD) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posRD) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posRD) != tileCellInfo.AutoTileCoord) || + + _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posRT) != -1 || + _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posRT) != -1 || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posRT) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posRT) != tileCellInfo.AutoTileCoord); + + if (flag2) //非空地, 那么说明这个点需要填充 WALL_BLOCK + { + _tileRoot.SetCell(GameConfig.TopMapLayer, pos, tileCellInfo.Id, tileCellInfo.AutoTileCoord); + } + } + } + } + } + //填充tile区域 private void FillRect(int layer, TileCellInfo info, Vector2 pos, Vector2 size) { @@ -671,7 +751,7 @@ try { - var size = new Vector2(_tileRoot.CellQuadrantSize, _tileRoot.CellQuadrantSize); + var size = new Vector2(GameConfig.TileCellSize, GameConfig.TileCellSize); var rect = _tileRoot.GetUsedRect(); @@ -824,7 +904,7 @@ { if (_floorAtlasCoords == null || _floorAtlasCoords.Count == 0) { - return _tileRoot.GetCellTileData(layer, new Vector2I(x, y)) != null; + return _tileRoot.GetCellSourceId(layer, new Vector2I(x, y)) != -1; } var result = _tileRoot.GetCellAtlasCoords(layer, new Vector2I(x, y)); diff --git a/DungeonShooting_Godot/src/framework/map/TileCellInfo.cs b/DungeonShooting_Godot/src/framework/map/TileCellInfo.cs index b892d38..bd120a6 100644 --- a/DungeonShooting_Godot/src/framework/map/TileCellInfo.cs +++ b/DungeonShooting_Godot/src/framework/map/TileCellInfo.cs @@ -13,7 +13,7 @@ } /// - /// 在TileSet中的图块id + /// 在TileSet中的图块id, 也就是sourceId /// public int Id; diff --git a/DungeonShooting_Godot/src/framework/map/fog/RoomFogMask.cs b/DungeonShooting_Godot/src/framework/map/fog/RoomFogMask.cs new file mode 100644 index 0000000..37e02e3 --- /dev/null +++ b/DungeonShooting_Godot/src/framework/map/fog/RoomFogMask.cs @@ -0,0 +1,242 @@ + +using Godot; + +/// +/// 迷雾遮罩 +/// +public partial class RoomFogMask : PointLight2D, IDestroy +{ + public int Width { get; private set; } + public int Height { get; private set; } + + public bool IsDestroyed { get; private set; } + private bool _init = false; + + private static Image _leftTransition; + private static Image _rightTransition; + private static Image _topTransition; + private static Image _downTransition; + + private static Image _leftTopTransition; + private static Image _rightTopTransition; + private static Image _leftDownTransition; + private static Image _rightDownTransition; + + private static Image _inLeftTopTransition; + private static Image _inRightTopTransition; + private static Image _inLeftDownTransition; + private static Image _inRightDownTransition; + + private static bool _initSprite = false; + + private static void InitSprite() + { + if (_initSprite) + { + return; + } + _initSprite = false; + + var temp = ResourceManager.Load(ResourcePath.resource_sprite_map_WallTransition1_png, false); + _leftTransition = temp.GetImage(); + _rightTransition = temp.GetImage(); + _rightTransition.Rotate180(); + _topTransition = temp.GetImage(); + _topTransition.Rotate90(ClockDirection.Clockwise); + _downTransition = temp.GetImage(); + _downTransition.Rotate90(ClockDirection.Counterclockwise); + + var temp2 = ResourceManager.Load(ResourcePath.resource_sprite_map_WallTransition2_png, false); + _leftDownTransition = temp2.GetImage(); + _leftTopTransition = temp2.GetImage(); + _leftTopTransition.Rotate90(ClockDirection.Clockwise); + _rightDownTransition = temp2.GetImage(); + _rightDownTransition.Rotate90(ClockDirection.Counterclockwise); + _rightTopTransition = temp2.GetImage(); + _rightTopTransition.Rotate180(); + + var temp3 = ResourceManager.Load(ResourcePath.resource_sprite_map_WallTransition3_png, false); + _inLeftDownTransition = temp3.GetImage(); + _inLeftTopTransition = temp3.GetImage(); + _inLeftTopTransition.Rotate90(ClockDirection.Clockwise); + _inRightDownTransition = temp3.GetImage(); + _inRightDownTransition.Rotate90(ClockDirection.Counterclockwise); + _inRightTopTransition = temp3.GetImage(); + _inRightTopTransition.Rotate180(); + } + + /// + /// 初始化贩房间迷雾遮罩 + /// + /// 房间对象 + /// 迷雾所占区域 + public void Init(RoomInfo roomInfo, Rect2I rect2) + { + if (_init) + { + return; + } + InitSprite(); + GlobalPosition = rect2.Position + rect2.Size / 2; + + //创建光纹理 + Width = rect2.Size.X; + Height = rect2.Size.Y; + var img = Image.Create(Width, Height, false, Image.Format.Rgba8); + img.Fill(Colors.White); + + //处理边缘过渡 + HandlerTransition(roomInfo, img); + Texture = ImageTexture.CreateFromImage(img); + } + + public void Destroy() + { + if (IsDestroyed) + { + return; + } + + IsDestroyed = true; + QueueFree(); + } + + private void HandlerTransition(RoomInfo roomInfo, Image image) + { + var tileMap = GameApplication.Instance.World.TileRoot; + var autoConfig = GameApplication.Instance.DungeonManager.AutoTileConfig; + var wallCoord = autoConfig.WALL_BLOCK.AutoTileCoord; + var (x, y) = roomInfo.Position; + var (width, height) = roomInfo.Size; + x -= 1; + y -= 1; + width += 2; + height += 2; + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + var pos = new Vector2I(i + x, j + y); + //说明是外层墙壁 + if (tileMap.GetCellAtlasCoords(GameConfig.TopMapLayer, pos) == wallCoord) + { + var left = IsEmptyCell(tileMap, new Vector2I(pos.X - 1, pos.Y)); + var right = IsEmptyCell(tileMap, new Vector2I(pos.X + 1, pos.Y)); + var top = IsEmptyCell(tileMap, new Vector2I(pos.X, pos.Y - 1)); + var down = IsEmptyCell(tileMap, new Vector2I(pos.X, pos.Y + 1)); + + var leftTop = IsEmptyCell(tileMap, new Vector2I(pos.X - 1, pos.Y - 1)); + var leftDown = IsEmptyCell(tileMap, new Vector2I(pos.X - 1, pos.Y + 1)); + var rightTop = IsEmptyCell(tileMap, new Vector2I(pos.X + 1, pos.Y - 1)); + var rightDown = IsEmptyCell(tileMap, new Vector2I(pos.X + 1, pos.Y + 1)); + + if (!left && !right && !top && !down && !leftTop && !leftDown && !rightTop && !rightDown) + { + continue; + } + else if (leftTop && left && top) //外轮廓, 左上 + { + FillTransitionImage(i, j, image, _leftTopTransition); + } + else if (leftDown && left && down) //外轮廓, 左下 + { + FillTransitionImage(i, j, image, _leftDownTransition); + } + else if (rightTop && right && top) //外轮廓, 右上 + { + FillTransitionImage(i, j, image, _rightTopTransition); + } + else if (rightDown && right && down) //外轮廓, 右下 + { + FillTransitionImage(i, j, image, _rightDownTransition); + } + //------------------------- + else if (left) //左 + { + FillTransitionImage(i, j, image, _leftTransition); + } + else if (right) //右 + { + FillTransitionImage(i, j, image, _rightTransition); + } + else if (top) //上 + { + FillTransitionImage(i, j, image, _topTransition); + } + else if (down) //下 + { + FillTransitionImage(i, j, image, _downTransition); + } + //-------------------------- + else if (leftTop) //内轮廓, 左上 + { + FillTransitionImage(i, j, image, _inLeftTopTransition); + } + else if (leftDown) //内轮廓, 左下 + { + FillTransitionImage(i, j, image, _inLeftDownTransition); + } + else if (rightTop) //内轮廓, 右上 + { + FillTransitionImage(i, j, image, _inRightTopTransition); + } + else if (rightDown) //内轮廓, 右下 + { + FillTransitionImage(i, j, image, _inRightDownTransition); + } + //------------------------ + else //全黑 + { + FillBlock(i, j, image); + } + } + } + } + } + + //填充一个16*16像素的区域 + private void FillBlock(int x, int y, Image image) + { + var endX = (x + 1) * GameConfig.TileCellSize; + var endY = (y + 1) * GameConfig.TileCellSize; + for (int i = x * GameConfig.TileCellSize; i < endX; i++) + { + for (int j = y * GameConfig.TileCellSize; j < endY; j++) + { + image.SetPixel(i, j, new Color(1, 1, 1, 0)); + } + } + } + + private void FillTransitionImage(int x, int y, Image image, Image transitionImage) + { + image.BlitRect(transitionImage, + new Rect2I(Vector2I.Zero, 16, 16), + new Vector2I(x * GameConfig.TileCellSize, y * GameConfig.TileCellSize) + ); + } + + private bool IsEmptyCell(TileMap tileMap, Vector2I pos) + { + return tileMap.GetCellSourceId(GameConfig.TopMapLayer, pos) == -1 && + tileMap.GetCellSourceId(GameConfig.MiddleMapLayer, pos) == -1; + } + + //判断是否是墙壁 + private bool IsNotWallCell(TileMap tileMap, Vector2I pos, Vector2I wallCoord) + { + return tileMap.GetCellAtlasCoords(GameConfig.TopMapLayer, pos) != wallCoord && + tileMap.GetCellAtlasCoords(GameConfig.MiddleMapLayer, pos) != wallCoord && + (tileMap.GetCellSourceId(GameConfig.TopMapLayer, pos) != -1 || + tileMap.GetCellSourceId(GameConfig.MiddleMapLayer, pos) != -1); + } + + //判断是否是任意类型的图块 + private bool IsAnyCell(TileMap tileMap, Vector2I pos) + { + return tileMap.GetCellSourceId(GameConfig.FloorMapLayer, pos) != -1 || + tileMap.GetCellSourceId(GameConfig.MiddleMapLayer, pos) != -1 || + tileMap.GetCellSourceId(GameConfig.TopMapLayer, pos) != -1 || + tileMap.GetCellSourceId(GameConfig.AisleFloorMapLayer, pos) != -1; + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs b/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs index 5aef09a..92e4f00 100644 --- a/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs +++ b/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs @@ -251,7 +251,7 @@ if (_currWaveIndex < WaveList.Count) { GD.Print($"执行第{_currWaveIndex}波"); - _coroutineId = GameApplication.Instance.StartCoroutine(RunMark(WaveList[_currWaveIndex])); + _coroutineId = GameApplication.Instance.World.StartCoroutine(RunMark(WaveList[_currWaveIndex])); _currWaveIndex++; } } @@ -268,7 +268,7 @@ } GD.Print($"执行第{_currWaveIndex}波"); - _coroutineId = GameApplication.Instance.StartCoroutine(RunMark(WaveList[_currWaveIndex])); + _coroutineId = GameApplication.Instance.World.StartCoroutine(RunMark(WaveList[_currWaveIndex])); _currWaveIndex++; } diff --git a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs index 1d3b34a..e5753d0 100644 --- a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs +++ b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs @@ -80,6 +80,16 @@ public RoomStaticImageCanvas StaticImageCanvas; /// + /// 房间迷雾 + /// + public RoomFogMask RoomFogMask; + + /// + /// 房间算上连接通道所占用的区域 + /// + public Rect2I OuterRange { get; private set; } + + /// /// 是否处于闭关状态, 也就是房间门没有主动打开 /// public bool IsSeclusion { get; private set; } = false; @@ -94,6 +104,96 @@ //private List _currActivityMarks = new List(); /// + /// 重新计算占用的区域 + /// + public void CalcOuterRange() + { + var worldPos = GetWorldPosition(); + var pos = new Vector2I(worldPos.X, worldPos.Y); + var minX = pos.X; + var minY = pos.Y; + var maxX = minX + GetWidth(); + var maxY = minY + GetHeight(); + + //遍历每一个连接的门, 计算计算canvas覆盖范围 + foreach (var doorInfo in Doors) + { + var connectDoor = doorInfo.ConnectDoor; + switch (connectDoor.Direction) + { + case DoorDirection.E: + case DoorDirection.W: + { + var (px1, py1) = connectDoor.GetWorldOriginPosition(); + var py2 = py1 + 4 * GameConfig.TileCellSize; + if (px1 < minX) + { + minX = px1; + } + else if (px1 > maxX) + { + maxX = px1; + } + + if (py1 < minY) + { + minY = py1; + } + else if (py1 > maxY) + { + maxY = py1; + } + + if (py2 < minY) + { + minY = py2; + } + else if (py2 > maxY) + { + maxY = py2; + } + } + break; + case DoorDirection.S: + case DoorDirection.N: + { + var (px1, py1) = connectDoor.GetWorldOriginPosition(); + var px2 = px1 + 4 * GameConfig.TileCellSize; + if (px1 < minX) + { + minX = px1; + } + else if (px1 > maxX) + { + maxX = px1; + } + + if (py1 < minY) + { + minY = py1; + } + else if (py1 > maxY) + { + maxY = py1; + } + + if (px2 < minX) + { + minX = px2; + } + else if (px2 > maxX) + { + maxX = px2; + } + } + break; + } + } + + OuterRange = new Rect2I(minX, minY, maxX - minX, maxY - minY); + } + + /// /// 获取房间的全局坐标, 单位: 像素 /// public Vector2I GetWorldPosition() @@ -186,6 +286,11 @@ StaticImageCanvas.Destroy(); } + if (RoomFogMask != null) + { + RoomFogMask.Destroy(); + } + if (AffiliationArea != null) { AffiliationArea.Destroy(); @@ -294,4 +399,21 @@ doorInfo.Door.CloseDoor(); } } + + /// + /// 获取该房间所有正向的门,nextRoom.id > this.id + /// + public RoomDoorInfo[] GetForwardDoors() + { + var temp = new List(); + foreach (var doorInfo in Doors) + { + if (doorInfo.ConnectRoom.Id > Id) + { + temp.Add(doorInfo); + } + } + + return temp.ToArray(); + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/ui/grid/IUiGrid.cs b/DungeonShooting_Godot/src/framework/ui/grid/IUiGrid.cs index 0fad5c1..ed184fe 100644 --- a/DungeonShooting_Godot/src/framework/ui/grid/IUiGrid.cs +++ b/DungeonShooting_Godot/src/framework/ui/grid/IUiGrid.cs @@ -1,4 +1,4 @@ - +using Godot; /// /// Ui网格组件基础接口, 无泛型 @@ -9,19 +9,25 @@ /// 当前选中的 Cell 索引 /// int SelectIndex { get; set; } - + /// /// 设置网格组件是否可见 /// bool Visible { get; set; } - + /// /// 当前网格组件数据大小 /// int Count { get; } + + /// + /// Godot 原生网格组件 + /// + GridContainer GridContainer { get; } /// - /// 触发点击 Cell + /// 触发 Cell 的点击事件 /// + /// cell的索引 void Click(int index); } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs b/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs index 23afa6b..bc51bd0 100644 --- a/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs +++ b/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs @@ -12,7 +12,7 @@ public class UiGrid : IUiGrid where TUiCellNode : IUiCellNode { public bool IsDestroyed { get; private set; } - + public int SelectIndex { get => _selectIndex; @@ -31,6 +31,7 @@ return; } } + var prevIndex = _selectIndex; _selectIndex = newIndex; @@ -55,59 +56,71 @@ /// 选中的 Cell 包含的数据 /// public TData SelectData => _selectIndex >= 0 ? _cellList[_selectIndex].Data : default; - + public bool Visible { - get => _gridContainer.Visible; - set => _gridContainer.Visible = value; + get => GridContainer.Visible; + set => GridContainer.Visible = value; } public int Count => _cellList.Count; - + + public GridContainer GridContainer { get; private set; } + //模板对象 private TUiCellNode _template; + //模板大小 private Vector2 _size = Vector2.Zero; + //cell逻辑处理类 private Type _cellType; + //当前活动的cell池 private List> _cellList = new List>(); + //当前已被回收的cell池 private Stack> _cellPool = new Stack>(); - //godot原生网格组件 - private UiGridContainer _gridContainer; + //单个cell偏移 private Vector2I _cellOffset; + //列数 private int _columns; + //是否自动扩展列数 private bool _autoColumns; + //选中的cell索引 private int _selectIndex = -1; public UiGrid(TUiCellNode template, Type cellType) { - _gridContainer = new UiGridContainer(OnReady, OnProcess); - _gridContainer.Ready += OnReady; + GridContainer = new UiGridContainer(OnReady, OnProcess); + GridContainer.Ready += OnReady; _template = template; _cellType = cellType; var uiInstance = _template.GetUiInstance(); - uiInstance.AddSibling(_gridContainer); + uiInstance.AddSibling(GridContainer); uiInstance.GetParent().RemoveChild(uiInstance); if (uiInstance is Control control) { _size = control.Size; + if (control.CustomMinimumSize == Vector2.Zero) + { + control.CustomMinimumSize = _size; + } } } /// /// 设置每个 Cell 之间的偏移量 /// - public void SetCellOffset(Vector2I offset) + public void SetCellOffset(Vector2I offset) { _cellOffset = offset; - _gridContainer.AddThemeConstantOverride("h_separation", offset.X); - _gridContainer.AddThemeConstantOverride("v_separation", offset.Y); + GridContainer.AddThemeConstantOverride("h_separation", offset.X); + GridContainer.AddThemeConstantOverride("v_separation", offset.Y); } /// @@ -124,7 +137,7 @@ public void SetColumns(int columns) { _columns = columns; - _gridContainer.Columns = columns; + GridContainer.Columns = columns; } /// @@ -132,7 +145,7 @@ /// public int GetColumns() { - return _gridContainer.Columns; + return GridContainer.Columns; } /// @@ -145,13 +158,13 @@ _autoColumns = flag; if (_autoColumns) { - _gridContainer.Resized += OnGridResized; + GridContainer.Resized += OnGridResized; OnGridResized(); } else { - _gridContainer.Columns = _columns; - _gridContainer.Resized -= OnGridResized; + GridContainer.Columns = _columns; + GridContainer.Resized -= OnGridResized; } } } @@ -169,7 +182,7 @@ /// public void SetHorizontalExpand(bool flag) { - _gridContainer.SetHorizontalExpand(flag); + SetHorizontalExpand(GridContainer, flag); } /// @@ -177,7 +190,7 @@ /// public bool GetHorizontalExpand() { - return _gridContainer.GetHorizontalExpand(); + return GetHorizontalExpand(GridContainer); } /// @@ -240,7 +253,7 @@ do { var cell = GetCellInstance(); - _gridContainer.AddChild(cell.CellNode.GetUiInstance()); + GridContainer.AddChild(cell.CellNode.GetUiInstance()); } while (array.Length > _cellList.Count); } else if (array.Length < _cellList.Count) @@ -268,7 +281,7 @@ //取消选中 SelectIndex = -1; var cell = GetCellInstance(); - _gridContainer.AddChild(cell.CellNode.GetUiInstance()); + GridContainer.AddChild(cell.CellNode.GetUiInstance()); cell.SetData(data); } @@ -300,6 +313,7 @@ //取消选中 SelectIndex = -1; } + var uiCell = _cellList[index]; _cellList.RemoveAt(index); ReclaimCellInstance(uiCell); @@ -325,14 +339,14 @@ ReclaimCellInstance(uiCell); } } - + public void Click(int index) { if (index < 0 || index >= _cellList.Count) { return; } - + _cellList[index].Click(); } @@ -346,6 +360,7 @@ { return; } + //这里记录 SelectIndex 是让排序后 SelectIndex 指向的 Cell 不变 var selectIndex = SelectIndex; var selectCell = GetCell(selectIndex); @@ -355,21 +370,24 @@ { selectIndex = _cellList.FindIndex(cell => cell == selectCell); } + //先移除所有节点 for (var i = 0; i < _cellList.Count; i++) { - _gridContainer.RemoveChild(_cellList[i].CellNode.GetUiInstance()); + GridContainer.RemoveChild(_cellList[i].CellNode.GetUiInstance()); } if (selectIndex >= 0) { _selectIndex = selectIndex; } + //以新的顺序加入GridContainer for (var i = 0; i < _cellList.Count; i++) { - _gridContainer.AddChild(_cellList[i].CellNode.GetUiInstance()); + GridContainer.AddChild(_cellList[i].CellNode.GetUiInstance()); } + //刷新Index for (var i = 0; i < _cellList.Count; i++) { @@ -377,7 +395,7 @@ cell.SetIndex(i); } } - + /// /// 销毁当前网格组件 /// @@ -402,23 +420,24 @@ _cellList = null; _cellPool = null; - _gridContainer.QueueFree(); + GridContainer.QueueFree(); } - + private void OnReady() { if (_template.GetUiInstance() is Control control) { - _gridContainer.Position = control.Position; + GridContainer.Position = control.Position; } } - + private void OnProcess(float delta) { if (IsDestroyed || !_template.GetUiPanel().IsOpen) { return; } + //调用 cell 更新 var uiCells = _cellPool.ToArray(); for (var i = 0; i < uiCells.Length; i++) @@ -459,23 +478,50 @@ private void ReclaimCellInstance(UiCell cell) { cell.SetEnable(false); - _gridContainer.RemoveChild(cell.CellNode.GetUiInstance()); + GridContainer.RemoveChild(cell.CellNode.GetUiInstance()); _cellPool.Push(cell); } private void OnGridResized() { - if (_autoColumns && _gridContainer != null) + if (_autoColumns && GridContainer != null) { - var width = _gridContainer.Size.X; + var width = GridContainer.Size.X; if (width <= _size.X + _cellOffset.X) { - _gridContainer.Columns = 1; + GridContainer.Columns = 1; } else { - _gridContainer.Columns = Mathf.FloorToInt(width / (_size.X + _cellOffset.X)); + GridContainer.Columns = Mathf.FloorToInt(width / (_size.X + _cellOffset.X)); } } } + + /// + /// 设置Ui布局方式是否横向扩展, 如果为 true, 则 GridContainer 的宽度会撑满父物体 + /// + private static void SetHorizontalExpand(Control control, bool flag) + { + if (flag) + { + control.LayoutMode = 1; + control.AnchorsPreset = (int)Control.LayoutPreset.TopWide; + control.SizeFlagsHorizontal |= Control.SizeFlags.Expand; + } + else if ((control.SizeFlagsHorizontal & Control.SizeFlags.Expand) != 0) + { + control.LayoutMode = 1; + control.AnchorsPreset = (int)Control.LayoutPreset.TopLeft; + control.SizeFlagsHorizontal ^= Control.SizeFlags.Expand; + } + } + + /// + /// 获取Ui布局方式是否横向扩展 + /// + private static bool GetHorizontalExpand(Control control) + { + return (control.SizeFlagsHorizontal & Control.SizeFlags.Expand) != 0; + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/GameApplication.cs b/DungeonShooting_Godot/src/game/GameApplication.cs index 1275dd1..34e9761 100644 --- a/DungeonShooting_Godot/src/game/GameApplication.cs +++ b/DungeonShooting_Godot/src/game/GameApplication.cs @@ -36,7 +36,7 @@ /// 是否开启调试 /// [ExportGroup("Debug")] - [Export] public bool Debug = false; + [Export] public bool Debug; /// /// 鼠标指针 @@ -96,11 +96,13 @@ DungeonConfig = new DungeonConfig(); DungeonConfig.GroupName = RoomConfig.FirstOrDefault().Key; - DungeonConfig.RoomCount = 20; + DungeonConfig.RoomCount = 10; } public override void _EnterTree() { + //背景颜色 + RenderingServer.SetDefaultClearColor(new Color(0, 0, 0, 1)); //随机化种子 //GD.Randomize(); //固定帧率 @@ -108,12 +110,14 @@ //调试绘制开关 ActivityObject.IsDebug = Debug; //Engine.TimeScale = 0.2f; - - ImageCanvas.Init(GetTree().CurrentScene); + //调整窗口分辨率 + OnWindowSizeChanged(); + RefreshSubViewportSize(); //窗体大小改变 GetWindow().SizeChanged += OnWindowSizeChanged; - RefreshSubViewportSize(); + + ImageCanvas.Init(GetTree().CurrentScene); //初始化ui UiManager.Init(); diff --git a/DungeonShooting_Godot/src/game/activity/role/Role.cs b/DungeonShooting_Godot/src/game/activity/role/Role.cs index 6010427..027db19 100644 --- a/DungeonShooting_Godot/src/game/activity/role/Role.cs +++ b/DungeonShooting_Godot/src/game/activity/role/Role.cs @@ -981,11 +981,10 @@ else { damage = RoleState.CallCalcHurtDamageEvent(damage); - if (damage < 0) + if (damage > 0) { - return; + Hp -= damage; } - Hp -= damage; //播放血液效果 // var packedScene = ResourceManager.Load(ResourcePath.prefab_effect_Blood_tscn); // var blood = packedScene.Instance(); diff --git a/DungeonShooting_Godot/src/game/activity/role/player/Player.cs b/DungeonShooting_Godot/src/game/activity/role/player/Player.cs index 4600a54..f9c24de 100644 --- a/DungeonShooting_Godot/src/game/activity/role/player/Player.cs +++ b/DungeonShooting_Godot/src/game/activity/role/player/Player.cs @@ -48,13 +48,13 @@ Shield = 0; // debug用 - // RoleState.Acceleration = 3000; - // RoleState.Friction = 3000; - // RoleState.MoveSpeed = 500; - // CollisionLayer = 0; - // CollisionMask = 0; - // GameCamera.Main.Zoom = new Vector2(0.2f, 0.2f); - // //GameCamera.Main.Zoom = new Vector2(0.5f, 0.5f); + RoleState.Acceleration = 3000; + RoleState.Friction = 3000; + RoleState.MoveSpeed = 500; + CollisionLayer = 0; + CollisionMask = 0; + //GameCamera.Main.Zoom = new Vector2(0.2f, 0.2f); + //GameCamera.Main.Zoom = new Vector2(0.5f, 0.5f); //注册状态机 StateController.Register(new PlayerIdleState()); @@ -254,6 +254,11 @@ GameCamera.Main.SetFollowTarget(null); BasisVelocity = Vector2.Zero; MoveController.ClearForce(); + + //暂停游戏 + GameApplication.Instance.World.Pause = true; + //弹出结算面板 + GameApplication.Instance.Cursor.SetGuiMode(true); UiManager.Open_Settlement(); } @@ -303,4 +308,10 @@ BasisVelocity = new Vector2(BasisVelocity.X, Mathf.MoveToward(BasisVelocity.Y, dir.Y * RoleState.MoveSpeed, RoleState.Acceleration * delta)); } } + + protected override void DebugDraw() + { + base.DebugDraw(); + DrawArc(new Vector2(0, -8), 50, 0, Mathf.Pi * 2f, 20, Colors.Red, 1); + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs index 34ca189..c6b93e7 100644 --- a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs +++ b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs @@ -433,7 +433,8 @@ _noAttackTime += delta; //这把武器被扔在地上, 或者当前武器没有被使用 - if (Master == null || Master.WeaponPack.ActiveItem != this) + //if (Master == null || Master.WeaponPack.ActiveItem != this) + if (Master != null && Master.WeaponPack.ActiveItem != this) //在背上 { //_triggerTimer _triggerTimer = _triggerTimer > 0 ? _triggerTimer - delta : 0; @@ -455,9 +456,7 @@ { _dirtyFlag = false; _aloneReloadState = 0; - Reloading = false; - _reloadTimer = 0; - _reloadUseTime = 0; + StopReload(); _attackFlag = false; _continuousCount = 0; _delayedTime = 0; @@ -520,7 +519,7 @@ if (Attribute.AloneReloadFinishIntervalTime <= 0) { //换弹完成 - StopReloadState(); + StopReload(); ReloadFinishHandler(); } else @@ -545,7 +544,7 @@ if (_reloadTimer <= 0) { //换弹完成 - StopReloadState(); + StopReload(); ReloadFinishHandler(); } _aloneReloadStop = false; @@ -579,7 +578,11 @@ _delayedTime += _attackTimer; _attackTimer = 0; //枪口默认角度 - RotationDegrees = -Attribute.DefaultAngle; + if (Master != null) + { + RotationDegrees = -Attribute.DefaultAngle; + } + //自动上膛 if (_beLoadedState == -1) { @@ -625,7 +628,7 @@ if (!_looseShootFlag && _continuousCount > 0 && _delayedTime <= 0 && _attackTimer <= 0) { //连发开火 - TriggerFire(_attackTrigger); + TriggerFire(); //连发最后一发打完了 if (Attribute.ManualBeLoaded && _continuousCount <= 0) { @@ -647,13 +650,16 @@ //武器身回归 //Position = Position.MoveToward(Vector2.Zero, Attribute.BacklashRegressionSpeed * delta).Rotated(Rotation); _currBacklashLength = Mathf.MoveToward(_currBacklashLength, 0, Attribute.BacklashRegressionSpeed * delta); - Position = new Vector2(_currBacklashLength, 0).Rotated(Rotation); - if (_attackTimer > 0) + if (Master != null) { - RotationDegrees = Mathf.Lerp( - _fireAngle, -Attribute.DefaultAngle, - Mathf.Clamp((_fireInterval - _attackTimer) * Attribute.UpliftAngleRestore / _fireInterval, 0, 1) - ); + Position = new Vector2(_currBacklashLength, 0).Rotated(Rotation); + if (_attackTimer > 0) + { + RotationDegrees = Mathf.Lerp( + _fireAngle, -Attribute.DefaultAngle, + Mathf.Clamp((_fireInterval - _attackTimer) * Attribute.UpliftAngleRestore / _fireInterval, 0, 1) + ); + } } } } @@ -687,7 +693,7 @@ if (_beLoadedState == 0 || _beLoadedState == -1) //需要执行上膛操作 { - if (justDown && !Reloading && Master != null) + if (justDown && !Reloading && trigger != null) { if (CurrAmmo <= 0) { @@ -757,7 +763,7 @@ else if (CurrAmmo <= 0) //子弹不够 { fireFlag = false; - if (justDown && Master != null) + if (justDown && trigger != null) { //第一帧按下, 触发换弹 Reload(); @@ -792,7 +798,7 @@ else { //开火 - TriggerFire(_attackTrigger); + TriggerFire(); //非连射模式 if (!Attribute.ContinuousShoot && Attribute.ManualBeLoaded && _continuousCount <= 0) @@ -868,7 +874,7 @@ _looseShootFlag = false; if (_chargeTime >= Attribute.MinChargeTime) //判断蓄力是否够了 { - TriggerFire(_attackTrigger); + TriggerFire(); //非连射模式 if (!Attribute.ContinuousShoot && Attribute.ManualBeLoaded && _continuousCount <= 0) { @@ -889,7 +895,7 @@ /// /// 触发开火 /// - private void TriggerFire(Role trigger) + private void TriggerFire() { _noAttackTime = 0; @@ -993,6 +999,18 @@ externalForce.RotationSpeed = -Mathf.DegToRad(40); externalForce.RotationResistance = Mathf.DegToRad(80); } + + if (IsInGround()) + { + //在地上弹药打光 + if (IsTotalAmmoEmpty()) + { + //停止动画 + AnimationPlayer.Stop(); + //清除泛白效果 + SetBlendSchedule(0); + } + } } /// @@ -1135,6 +1153,17 @@ } } + /// + /// 强制停止换弹, 或者结束换弹状态 + /// + public void StopReload() + { + _aloneReloadState = 0; + Reloading = false; + _reloadTimer = 0; + _reloadUseTime = 0; + } + //播放换弹开始音效 private void PlayBeginReloadSound() { @@ -1391,15 +1420,6 @@ } } - //停止当前的换弹状态 - private void StopReloadState() - { - _aloneReloadState = 0; - Reloading = false; - _reloadTimer = 0; - _reloadUseTime = 0; - } - /// /// 换弹计时器时间到, 执行换弹操作 /// @@ -1454,7 +1474,7 @@ ResidueAmmo = 0; } - StopReloadState(); + StopReload(); ReloadFinishHandler(); } } diff --git a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs index 5aaa8f5..18d78c3 100644 --- a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs +++ b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs @@ -9,7 +9,6 @@ public const string excel_DungeonShooting_ExcelTool_deps_json = "res://excel/DungeonShooting_ExcelTool.deps.json"; public const string excel_DungeonShooting_ExcelTool_runtimeconfig_json = "res://excel/DungeonShooting_ExcelTool.runtimeconfig.json"; public const string prefab_Cursor_tscn = "res://prefab/Cursor.tscn"; - public const string prefab_FanCollisionShape_tscn = "res://prefab/FanCollisionShape.tscn"; public const string prefab_bullet_Bullet0001_tscn = "res://prefab/bullet/Bullet0001.tscn"; public const string prefab_bullet_Bullet0002_tscn = "res://prefab/bullet/Bullet0002.tscn"; public const string prefab_bullet_Bullet0003_tscn = "res://prefab/bullet/Bullet0003.tscn"; @@ -21,6 +20,7 @@ public const string prefab_effect_weapon_BulletSmoke_tscn = "res://prefab/effect/weapon/BulletSmoke.tscn"; public const string prefab_effect_weapon_FirePart_tscn = "res://prefab/effect/weapon/FirePart.tscn"; public const string prefab_effect_weapon_MeleeAttack1_tscn = "res://prefab/effect/weapon/MeleeAttack1.tscn"; + public const string prefab_effect_weapon_MeleeAttack2_tscn = "res://prefab/effect/weapon/MeleeAttack2.tscn"; public const string prefab_effect_weapon_ShotFire_tscn = "res://prefab/effect/weapon/ShotFire.tscn"; public const string prefab_map_RoomDoor_E_tscn = "res://prefab/map/RoomDoor_E.tscn"; public const string prefab_map_RoomDoor_N_tscn = "res://prefab/map/RoomDoor_N.tscn"; @@ -63,6 +63,7 @@ public const string prefab_ui_MapEditorProject_tscn = "res://prefab/ui/MapEditorProject.tscn"; public const string prefab_ui_MapEditorSelectObject_tscn = "res://prefab/ui/MapEditorSelectObject.tscn"; public const string prefab_ui_MapEditorTools_tscn = "res://prefab/ui/MapEditorTools.tscn"; + public const string prefab_ui_PauseMenu_tscn = "res://prefab/ui/PauseMenu.tscn"; public const string prefab_ui_RoomUI_tscn = "res://prefab/ui/RoomUI.tscn"; public const string prefab_ui_Settlement_tscn = "res://prefab/ui/Settlement.tscn"; public const string prefab_weapon_Weapon0001_tscn = "res://prefab/weapon/Weapon0001.tscn"; @@ -144,6 +145,9 @@ public const string resource_sprite_effects_weapon_KnifeHit1_png = "res://resource/sprite/effects/weapon/KnifeHit1.png"; public const string resource_sprite_effects_weapon_MeleeAttack1_png = "res://resource/sprite/effects/weapon/MeleeAttack1.png"; public const string resource_sprite_effects_weapon_ShotFire_png = "res://resource/sprite/effects/weapon/ShotFire.png"; + public const string resource_sprite_map_WallTransition1_png = "res://resource/sprite/map/WallTransition1.png"; + public const string resource_sprite_map_WallTransition2_png = "res://resource/sprite/map/WallTransition2.png"; + public const string resource_sprite_map_WallTransition3_png = "res://resource/sprite/map/WallTransition3.png"; public const string resource_sprite_map_map1_16x16dungeoniiwallreconfigv04spritesheet_png = "res://resource/sprite/map/map1/16x16 dungeon ii wall reconfig v04 spritesheet.png"; public const string resource_sprite_map_map1_door1_down_png = "res://resource/sprite/map/map1/door1_down.png"; public const string resource_sprite_map_map1_website_txt = "res://resource/sprite/map/map1/website.txt"; @@ -302,6 +306,7 @@ public const string scene_Main_tscn = "res://scene/Main.tscn"; public const string scene_World_tscn = "res://scene/World.tscn"; public const string scene_test_TestCommpont_tscn = "res://scene/test/TestCommpont.tscn"; + public const string scene_test_TestCreateSector_tscn = "res://scene/test/TestCreateSector.tscn"; public const string scene_test_TestExpression_tscn = "res://scene/test/TestExpression.tscn"; public const string scene_test_TestGenerateDungeon_tscn = "res://scene/test/TestGenerateDungeon.tscn"; public const string scene_test_TestNavigation2_tscn = "res://scene/test/TestNavigation2.tscn"; @@ -310,5 +315,6 @@ public const string scene_test_TestOptimizeSprite_tscn = "res://scene/test/TestOptimizeSprite.tscn"; public const string scene_test_TestOutline_tscn = "res://scene/test/TestOutline.tscn"; public const string scene_test_TestReadExcel_tscn = "res://scene/test/TestReadExcel.tscn"; + public const string scene_test_TestRoomFog_tscn = "res://scene/test/TestRoomFog.tscn"; public const string scene_test_TestTileLayer_tscn = "res://scene/test/TestTileLayer.tscn"; } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs b/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs index 738391c..c64b660 100644 --- a/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs +++ b/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs @@ -22,6 +22,7 @@ public const string MapEditorProject = "MapEditorProject"; public const string MapEditorSelectObject = "MapEditorSelectObject"; public const string MapEditorTools = "MapEditorTools"; + public const string PauseMenu = "PauseMenu"; public const string RoomUI = "RoomUI"; public const string Settlement = "Settlement"; } @@ -795,6 +796,54 @@ } /// + /// 创建 PauseMenu, 并返回UI实例, 该函数不会打开 Ui + /// + public static UI.PauseMenu.PauseMenuPanel Create_PauseMenu() + { + return CreateUi(UiName.PauseMenu); + } + + /// + /// 打开 PauseMenu, 并返回UI实例 + /// + public static UI.PauseMenu.PauseMenuPanel Open_PauseMenu() + { + return OpenUi(UiName.PauseMenu); + } + + /// + /// 隐藏 PauseMenu 的所有实例 + /// + public static void Hide_PauseMenu() + { + var uiInstance = Get_PauseMenu_Instance(); + foreach (var uiPanel in uiInstance) + { + uiPanel.HideUi(); + } + } + + /// + /// 销毁 PauseMenu 的所有实例 + /// + public static void Destroy_PauseMenu() + { + var uiInstance = Get_PauseMenu_Instance(); + foreach (var uiPanel in uiInstance) + { + uiPanel.Destroy(); + } + } + + /// + /// 获取所有 PauseMenu 的实例, 如果没有实例, 则返回一个空数组 + /// + public static UI.PauseMenu.PauseMenuPanel[] Get_PauseMenu_Instance() + { + return GetUiInstance(nameof(UI.PauseMenu.PauseMenu)); + } + + /// /// 创建 RoomUI, 并返回UI实例, 该函数不会打开 Ui /// public static UI.RoomUI.RoomUIPanel Create_RoomUI() diff --git a/DungeonShooting_Godot/src/game/room/AutoTileConfig.cs b/DungeonShooting_Godot/src/game/room/AutoTileConfig.cs index 07bcf9d..968d8f3 100644 --- a/DungeonShooting_Godot/src/game/room/AutoTileConfig.cs +++ b/DungeonShooting_Godot/src/game/room/AutoTileConfig.cs @@ -22,6 +22,8 @@ public TileCellInfo OUT_RT = new TileCellInfo(0, new Vector2I(3, 2)); public TileCellInfo OUT_RB = new TileCellInfo(0, new Vector2I(3, 7)); + public TileCellInfo WALL_BLOCK = new TileCellInfo(0, new Vector2I(2, 3)); + private List _middleLayerAtlasCoords = new List() { new Vector2I(1, 6), diff --git a/DungeonShooting_Godot/src/game/room/DungeonManager.cs b/DungeonShooting_Godot/src/game/room/DungeonManager.cs index 7655681..782302c 100644 --- a/DungeonShooting_Godot/src/game/room/DungeonManager.cs +++ b/DungeonShooting_Godot/src/game/room/DungeonManager.cs @@ -43,10 +43,14 @@ /// 当前使用的世界对象 /// public World World { get; private set; } + + /// + /// 自动图块配置 + /// + public AutoTileConfig AutoTileConfig { get; private set; } private UiBase _prevUi; private DungeonTileMap _dungeonTileMap; - private AutoTileConfig _autoTileConfig; private DungeonGenerator _dungeonGenerator; //房间内所有静态导航网格数据 private List _roomStaticNavigationList; @@ -72,7 +76,6 @@ GameApplication.Instance.StartCoroutine(RunLoadDungeonCoroutine(finish)); } - /// /// 重启地牢 /// @@ -152,6 +155,21 @@ { if (IsInDungeon) { + if (World.Pause) //已经暂停 + { + return; + } + + //暂停游戏 + if (Input.IsActionJustPressed("ui_cancel")) + { + World.Pause = true; + //鼠标改为Ui鼠标 + GameApplication.Instance.Cursor.SetGuiMode(true); + //打开暂停Ui + UiManager.Open_PauseMenu(); + } + _checkEnemyTimer += (float)delta; if (_checkEnemyTimer >= 1) { @@ -177,17 +195,18 @@ yield return 0; //创建世界场景 World = GameApplication.Instance.CreateNewWorld(); - yield return new WaitForFixedProcess(10); + yield return 0; //生成地牢房间 - _dungeonGenerator = new DungeonGenerator(CurrConfig); + var random = new SeedRandom(2); + _dungeonGenerator = new DungeonGenerator(CurrConfig, random); _dungeonGenerator.Generate(); yield return 0; //填充地牢 - _autoTileConfig = new AutoTileConfig(); + AutoTileConfig = new AutoTileConfig(); _dungeonTileMap = new DungeonTileMap(World.TileRoot); - _dungeonTileMap.AutoFillRoomTile(_autoTileConfig, _dungeonGenerator.StartRoomInfo, _dungeonGenerator.Random); - yield return 0; + yield return _dungeonTileMap.AutoFillRoomTile(AutoTileConfig, _dungeonGenerator.StartRoomInfo, random); + yield return _dungeonTileMap.AddOutlineTile(AutoTileConfig.WALL_BLOCK); //生成寻路网格, 这一步操作只生成过道的导航 _dungeonTileMap.GenerateNavigationPolygon(GameConfig.AisleFloorMapLayer); @@ -201,14 +220,15 @@ yield return 0; //门导航区域数据 _roomStaticNavigationList.AddRange(_dungeonTileMap.GetConnectDoorPolygonData()); - yield return new WaitForFixedProcess(10); //初始化所有房间 - _dungeonGenerator.EachRoom(InitRoom); - yield return new WaitForFixedProcess(10); + yield return _dungeonGenerator.EachRoomCoroutine(InitRoom); //播放bgm //SoundManager.PlayMusic(ResourcePath.resource_sound_bgm_Intro_ogg, -17f); + //地牢加载即将完成 + yield return _dungeonGenerator.EachRoomCoroutine(info => info.OnReady()); + //初始房间创建玩家标记 var playerBirthMark = StartRoomInfo.RoomPreinstall.GetPlayerBirthMark(); //创建玩家 @@ -221,9 +241,7 @@ player.Name = "Player"; player.PutDown(RoomLayerEnum.YSortLayer); Player.SetCurrentPlayer(player); - - //地牢加载即将完成 - _dungeonGenerator.EachRoom(info => info.OnReady()); + yield return 0; //玩家手上添加武器 //player.PickUpWeapon(ActivityObject.Create(ActivityObject.Ids.Id_weapon0001)); @@ -255,6 +273,7 @@ } } + //执行退出地牢流程 private IEnumerator RunExitDungeonCoroutine(Action finish) { //打开 loading UI @@ -265,17 +284,17 @@ _dungeonGenerator.EachRoom(DisposeRoomInfo); yield return 0; _dungeonTileMap = null; - _autoTileConfig = null; + AutoTileConfig = null; _dungeonGenerator = null; _roomStaticNavigationList.Clear(); _roomStaticNavigationList = null; UiManager.Hide_RoomUI(); - yield return new WaitForFixedProcess(10); + yield return 0; Player.SetCurrentPlayer(null); World = null; GameApplication.Instance.DestroyWorld(); - yield return new WaitForFixedProcess(10); + yield return 0; QueueRedraw(); //鼠标还原 GameApplication.Instance.Cursor.SetGuiMode(true); @@ -293,6 +312,7 @@ // 初始化房间 private void InitRoom(RoomInfo roomInfo) { + roomInfo.CalcOuterRange(); //挂载房间导航区域 MountNavFromRoomInfo(roomInfo); //创建门 @@ -301,6 +321,8 @@ CreateRoomAffiliation(roomInfo); //创建静态精灵画布 CreateRoomStaticSpriteCanvas(roomInfo); + //创建迷雾遮罩 + CreateRoomFogMask(roomInfo); } //挂载房间导航区域 @@ -375,8 +397,8 @@ { var affiliation = new AffiliationArea(); affiliation.Name = "AffiliationArea" + roomInfo.Id; - affiliation.Init(roomInfo, new Rect2( - roomInfo.GetWorldPosition() + new Vector2(GameConfig.TileCellSize, GameConfig.TileCellSize), + affiliation.Init(roomInfo, new Rect2I( + roomInfo.GetWorldPosition() + GameConfig.TileCellSizeVector2I, (roomInfo.Size - new Vector2I(2, 2)) * GameConfig.TileCellSize)); roomInfo.AffiliationArea = affiliation; @@ -387,92 +409,13 @@ private void CreateRoomStaticSpriteCanvas(RoomInfo roomInfo) { var worldPos = roomInfo.GetWorldPosition(); - var pos = new Vector2I((int)worldPos.X, (int)worldPos.Y); - - int minX = pos.X; - int minY = pos.Y; - int maxX = minX + roomInfo.GetWidth(); - int maxY = minY + roomInfo.GetHeight(); + var rect = roomInfo.OuterRange; - //遍历每一个连接的门, 计算计算canvas覆盖范围 - foreach (var doorInfo in roomInfo.Doors) - { - var connectDoor = doorInfo.ConnectDoor; - switch (connectDoor.Direction) - { - case DoorDirection.E: - case DoorDirection.W: - { - var (px1, py1) = connectDoor.GetWorldOriginPosition(); - var py2 = py1 + 4 * GameConfig.TileCellSize; - if (px1 < minX) - { - minX = px1; - } - else if (px1 > maxX) - { - maxX = px1; - } + int minX = rect.Position.X - GameConfig.TileCellSize; + int minY = rect.Position.Y - GameConfig.TileCellSize; + int maxX = rect.End.X + GameConfig.TileCellSize; + int maxY = rect.End.Y + GameConfig.TileCellSize; - if (py1 < minY) - { - minY = py1; - } - else if (py1 > maxY) - { - maxY = py1; - } - - if (py2 < minY) - { - minY = py2; - } - else if (py2 > maxY) - { - maxY = py2; - } - } - break; - case DoorDirection.S: - case DoorDirection.N: - { - var (px1, py1) = connectDoor.GetWorldOriginPosition(); - var px2 = px1 + 4 * GameConfig.TileCellSize; - if (px1 < minX) - { - minX = px1; - } - else if (px1 > maxX) - { - maxX = px1; - } - - if (py1 < minY) - { - minY = py1; - } - else if (py1 > maxY) - { - maxY = py1; - } - - if (px2 < minX) - { - minX = px2; - } - else if (px2 > maxX) - { - maxX = px2; - } - } - break; - } - } - - minX -= GameConfig.TileCellSize; - minY -= GameConfig.TileCellSize; - maxX += GameConfig.TileCellSize; - maxY += GameConfig.TileCellSize; var staticSpriteCanvas = new RoomStaticImageCanvas( World.StaticSpriteRoot, new Vector2I(minX, minY), @@ -482,6 +425,46 @@ roomInfo.StaticImageCanvas = staticSpriteCanvas; } + //创建迷雾遮罩 + private void CreateRoomFogMask(RoomInfo roomInfo) + { + var roomFog = new RoomFogMask(); + //roomFog.BlendMode = Light2D.BlendModeEnum.Mix; + roomFog.Name = "FogMask" + roomFog.IsDestroyed; + roomInfo.RoomFogMask = roomFog; + roomFog.Init(roomInfo, new Rect2I( + roomInfo.GetWorldPosition() - GameConfig.TileCellSizeVector2I, + (roomInfo.Size + new Vector2I(2, 2)) * GameConfig.TileCellSize) + ); + World.FogMaskRoot.AddChild(roomFog); + + //正向门 + var roomDoorInfos = roomInfo.GetForwardDoors(); + foreach (var roomDoorInfo in roomDoorInfos) + { + var p1 = roomDoorInfo.GetWorldOriginPosition(); + var p2 = roomDoorInfo.ConnectDoor.GetWorldOriginPosition(); + var calcRect = Utils.CalcRect(p1.X, p1.Y, p2.X, p2.Y); + if (calcRect.Size.X == 0) + { + calcRect.Size += new Vector2(4 * GameConfig.TileCellSize, 0); + } + else if (calcRect.Size.Y == 0) + { + calcRect.Size += new Vector2(0, 4 * GameConfig.TileCellSize); + } + + var calcRectSize = calcRect.Size.AsVector2I(); + var image = Image.Create(calcRectSize.X, calcRectSize.Y, false, Image.Format.Rgba8); + image.Fill(Colors.White); + var sprite2D = new PointLight2D(); + //sprite2D.BlendMode = Light2D.BlendModeEnum.Mix; + sprite2D.Texture = ImageTexture.CreateFromImage(image); + sprite2D.Position = calcRect.Position + calcRect.Size / 2; + World.FogMaskRoot.AddChild(sprite2D); + } + } + /// /// 玩家第一次进入某个房间回调 /// @@ -591,7 +574,7 @@ //绘制房间区域, debug 用 private void DrawRoomInfo(RoomInfo roomInfo) { - var cellSize = World.TileRoot.CellQuadrantSize; + var cellSize = GameConfig.TileCellSize; var pos1 = (roomInfo.Position + roomInfo.Size / 2) * cellSize; //绘制下一个房间 diff --git a/DungeonShooting_Godot/src/game/room/World.cs b/DungeonShooting_Godot/src/game/room/World.cs index 622803c..650d3da 100644 --- a/DungeonShooting_Godot/src/game/room/World.cs +++ b/DungeonShooting_Godot/src/game/room/World.cs @@ -1,10 +1,11 @@ +using System.Collections; using System.Collections.Generic; using Godot; /// /// 游戏世界 /// -public partial class World : Node2D +public partial class World : CanvasModulate, ICoroutine { /// /// //对象根节点 @@ -23,6 +24,7 @@ [Export] public Node2D StaticSpriteRoot; [Export] public Node2D AffiliationAreaRoot; + [Export] public Node2D FogMaskRoot; /// /// 是否暂停 @@ -73,12 +75,22 @@ public Vector2 Enemy_FindTargetPosition { get; set; } private bool _pause = false; - + private List _coroutineList; + public override void _Ready() { TileRoot.YSortEnabled = false; } + public override void _Process(double delta) + { + //协程更新 + if (_coroutineList != null) + { + ProxyCoroutineHandler.ProxyUpdateCoroutine(ref _coroutineList, (float)delta); + } + } + /// /// 获取指定层级根节点 /// @@ -95,4 +107,23 @@ return null; } + public long StartCoroutine(IEnumerator able) + { + return ProxyCoroutineHandler.ProxyStartCoroutine(ref _coroutineList, able); + } + + public void StopCoroutine(long coroutineId) + { + ProxyCoroutineHandler.ProxyStopCoroutine(ref _coroutineList, coroutineId); + } + + public bool IsCoroutineOver(long coroutineId) + { + return ProxyCoroutineHandler.ProxyIsCoroutineOver(ref _coroutineList, coroutineId); + } + + public void StopAllCoroutine() + { + ProxyCoroutineHandler.ProxyStopAllCoroutine(ref _coroutineList); + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/main/Main.cs b/DungeonShooting_Godot/src/game/ui/main/Main.cs index fe49dfb..779be78 100644 --- a/DungeonShooting_Godot/src/game/ui/main/Main.cs +++ b/DungeonShooting_Godot/src/game/ui/main/Main.cs @@ -6,198 +6,257 @@ public abstract partial class Main : UiBase { /// - /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.Title + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.ColorRect /// - public Main_Title L_Title + public ColorRect L_ColorRect { get { - if (_L_Title == null) _L_Title = new Main_Title(this, GetNodeOrNull("Title")); - return _L_Title; + if (_L_ColorRect == null) _L_ColorRect = new ColorRect((MainPanel)this, GetNode("ColorRect")); + return _L_ColorRect; } } - private Main_Title _L_Title; + private ColorRect _L_ColorRect; /// - /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.ButtonList + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.VBoxContainer /// - public Main_ButtonList L_ButtonList + public VBoxContainer L_VBoxContainer { get { - if (_L_ButtonList == null) _L_ButtonList = new Main_ButtonList(this, GetNodeOrNull("ButtonList")); - return _L_ButtonList; + if (_L_VBoxContainer == null) _L_VBoxContainer = new VBoxContainer((MainPanel)this, GetNode("VBoxContainer")); + return _L_VBoxContainer; } } - private Main_ButtonList _L_ButtonList; + private VBoxContainer _L_VBoxContainer; /// /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.Version /// - public Main_Version L_Version + public Version L_Version { get { - if (_L_Version == null) _L_Version = new Main_Version(this, GetNodeOrNull("Version")); + if (_L_Version == null) _L_Version = new Version((MainPanel)this, GetNode("Version")); return _L_Version; } } - private Main_Version _L_Version; + private Version _L_Version; public Main() : base(nameof(Main)) { } - /// - /// 类型: , 路径: Main.Title - /// - public class Main_Title : UiNode + public sealed override void OnInitNestedUi() { - public Main_Title(Main uiPanel, Godot.Label node) : base(uiPanel, node) { } - public override Main_Title Clone() => new (UiPanel, (Godot.Label)Instance.Duplicate()); + } /// - /// 类型: , 路径: Main.ButtonList.Start + /// 类型: , 路径: Main.ColorRect /// - public class Main_Start : UiNode + public class ColorRect : UiNode { - public Main_Start(Main uiPanel, Godot.Button node) : base(uiPanel, node) { } - public override Main_Start Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + public ColorRect(MainPanel uiPanel, Godot.ColorRect node) : base(uiPanel, node) { } + public override ColorRect Clone() => new (UiPanel, (Godot.ColorRect)Instance.Duplicate()); } /// - /// 类型: , 路径: Main.ButtonList.Tools + /// 类型: , 路径: Main.VBoxContainer.Title /// - public class Main_Tools : UiNode + public class Title : UiNode { - public Main_Tools(Main uiPanel, Godot.Button node) : base(uiPanel, node) { } - public override Main_Tools Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + public Title(MainPanel uiPanel, Godot.Label node) : base(uiPanel, node) { } + public override Title Clone() => new (UiPanel, (Godot.Label)Instance.Duplicate()); } /// - /// 类型: , 路径: Main.ButtonList.Setting + /// 类型: , 路径: Main.VBoxContainer.ButtonList.Start /// - public class Main_Setting : UiNode + public class Start : UiNode { - public Main_Setting(Main uiPanel, Godot.Button node) : base(uiPanel, node) { } - public override Main_Setting Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + public Start(MainPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override Start Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); } /// - /// 类型: , 路径: Main.ButtonList.Exit + /// 类型: , 路径: Main.VBoxContainer.ButtonList.Tools /// - public class Main_Exit : UiNode + public class Tools : UiNode { - public Main_Exit(Main uiPanel, Godot.Button node) : base(uiPanel, node) { } - public override Main_Exit Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + public Tools(MainPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override Tools Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); } /// - /// 类型: , 路径: Main.ButtonList + /// 类型: , 路径: Main.VBoxContainer.ButtonList.Setting /// - public class Main_ButtonList : UiNode + public class Setting : UiNode + { + public Setting(MainPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override Setting Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: Main.VBoxContainer.ButtonList.Exit + /// + public class Exit : UiNode + { + public Exit(MainPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override Exit Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: Main.VBoxContainer.ButtonList + /// + public class ButtonList : UiNode { /// - /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.Start + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.VBoxContainer.Start /// - public Main_Start L_Start + public Start L_Start { get { - if (_L_Start == null) _L_Start = new Main_Start(UiPanel, Instance.GetNodeOrNull("Start")); + if (_L_Start == null) _L_Start = new Start(UiPanel, Instance.GetNode("Start")); return _L_Start; } } - private Main_Start _L_Start; + private Start _L_Start; /// - /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.Tools + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.VBoxContainer.Tools /// - public Main_Tools L_Tools + public Tools L_Tools { get { - if (_L_Tools == null) _L_Tools = new Main_Tools(UiPanel, Instance.GetNodeOrNull("Tools")); + if (_L_Tools == null) _L_Tools = new Tools(UiPanel, Instance.GetNode("Tools")); return _L_Tools; } } - private Main_Tools _L_Tools; + private Tools _L_Tools; /// - /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.Setting + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.VBoxContainer.Setting /// - public Main_Setting L_Setting + public Setting L_Setting { get { - if (_L_Setting == null) _L_Setting = new Main_Setting(UiPanel, Instance.GetNode("Setting")); + if (_L_Setting == null) _L_Setting = new Setting(UiPanel, Instance.GetNode("Setting")); return _L_Setting; } } - private Main_Setting _L_Setting; + private Setting _L_Setting; /// - /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.Exit + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.VBoxContainer.Exit /// - public Main_Exit L_Exit + public Exit L_Exit { get { - if (_L_Exit == null) _L_Exit = new Main_Exit(UiPanel, Instance.GetNodeOrNull("Exit")); + if (_L_Exit == null) _L_Exit = new Exit(UiPanel, Instance.GetNode("Exit")); return _L_Exit; } } - private Main_Exit _L_Exit; + private Exit _L_Exit; - public Main_ButtonList(Main uiPanel, Godot.VBoxContainer node) : base(uiPanel, node) { } - public override Main_ButtonList Clone() => new (UiPanel, (Godot.VBoxContainer)Instance.Duplicate()); + public ButtonList(MainPanel uiPanel, Godot.VBoxContainer node) : base(uiPanel, node) { } + public override ButtonList Clone() => new (UiPanel, (Godot.VBoxContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: Main.VBoxContainer + /// + public class VBoxContainer : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.Title + /// + public Title L_Title + { + get + { + if (_L_Title == null) _L_Title = new Title(UiPanel, Instance.GetNode("Title")); + return _L_Title; + } + } + private Title _L_Title; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Main.ButtonList + /// + public ButtonList L_ButtonList + { + get + { + if (_L_ButtonList == null) _L_ButtonList = new ButtonList(UiPanel, Instance.GetNode("ButtonList")); + return _L_ButtonList; + } + } + private ButtonList _L_ButtonList; + + public VBoxContainer(MainPanel uiPanel, Godot.VBoxContainer node) : base(uiPanel, node) { } + public override VBoxContainer Clone() => new (UiPanel, (Godot.VBoxContainer)Instance.Duplicate()); } /// /// 类型: , 路径: Main.Version /// - public class Main_Version : UiNode + public class Version : UiNode { - public Main_Version(Main uiPanel, Godot.Label node) : base(uiPanel, node) { } - public override Main_Version Clone() => new (UiPanel, (Godot.Label)Instance.Duplicate()); + public Version(MainPanel uiPanel, Godot.Label node) : base(uiPanel, node) { } + public override Version Clone() => new (UiPanel, (Godot.Label)Instance.Duplicate()); } /// - /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.Title + /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.ColorRect /// - public Main_Title S_Title => L_Title; + public ColorRect S_ColorRect => L_ColorRect; /// - /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.ButtonList.Start + /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.VBoxContainer.Title /// - public Main_Start S_Start => L_ButtonList.L_Start; + public Title S_Title => L_VBoxContainer.L_Title; /// - /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.ButtonList.Tools + /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.VBoxContainer.ButtonList.Start /// - public Main_Tools S_Tools => L_ButtonList.L_Tools; + public Start S_Start => L_VBoxContainer.L_ButtonList.L_Start; /// - /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.ButtonList.Setting + /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.VBoxContainer.ButtonList.Tools /// - public Main_Setting S_Setting => L_ButtonList.L_Setting; + public Tools S_Tools => L_VBoxContainer.L_ButtonList.L_Tools; /// - /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.ButtonList.Exit + /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.VBoxContainer.ButtonList.Setting /// - public Main_Exit S_Exit => L_ButtonList.L_Exit; + public Setting S_Setting => L_VBoxContainer.L_ButtonList.L_Setting; /// - /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.ButtonList + /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.VBoxContainer.ButtonList.Exit /// - public Main_ButtonList S_ButtonList => L_ButtonList; + public Exit S_Exit => L_VBoxContainer.L_ButtonList.L_Exit; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.VBoxContainer.ButtonList + /// + public ButtonList S_ButtonList => L_VBoxContainer.L_ButtonList; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.VBoxContainer + /// + public VBoxContainer S_VBoxContainer => L_VBoxContainer; /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: Main.Version /// - public Main_Version S_Version => L_Version; + public Version S_Version => L_Version; } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs index e44a0b6..686b15a 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Text.Json; using Godot; using Godot.Collections; using UI.MapEditorTools; @@ -800,7 +798,7 @@ //设置显示的错误cell, 会标记上红色的闪烁动画 private void SetErrorCell(Vector2I pos) { - MapEditorPanel.S_ErrorCell.Instance.Position = pos * CellQuadrantSize; + MapEditorPanel.S_ErrorCell.Instance.Position = pos * GameConfig.TileCellSize; MapEditorPanel.S_ErrorCellAnimationPlayer.Instance.Play(AnimatorNames.Show); } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs index e4906be..41ed879 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs @@ -462,11 +462,11 @@ S_DynamicTool.Reparent(this); S_DynamicTool.Instance.Visible = false; var markCellIndex = markCell.Index; - var markInfo = waveCell.Data[markCellIndex]; + var markInfo = waveCell.MarkGrid.GetData(markCellIndex).MarkInfo; //派发移除标记事件 EventManager.EmitEvent(EventEnum.OnDeleteMark, markInfo); waveCell.MarkGrid.RemoveByIndex(markCellIndex); - waveCell.Data.RemoveAt(markCellIndex); + waveCell.Data.Remove(markInfo); //派发数据修改事件 EventManager.EmitEvent(EventEnum.OnEditorDirty); } diff --git a/DungeonShooting_Godot/src/game/ui/pauseMenu/PauseMenu.cs b/DungeonShooting_Godot/src/game/ui/pauseMenu/PauseMenu.cs new file mode 100644 index 0000000..256a892 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/pauseMenu/PauseMenu.cs @@ -0,0 +1,154 @@ +namespace UI.PauseMenu; + +/// +/// Ui代码, 该类是根据ui场景自动生成的, 请不要手动编辑该类, 以免造成代码丢失 +/// +public abstract partial class PauseMenu : UiBase +{ + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: PauseMenu.ColorRect + /// + public ColorRect L_ColorRect + { + get + { + if (_L_ColorRect == null) _L_ColorRect = new ColorRect((PauseMenuPanel)this, GetNode("ColorRect")); + return _L_ColorRect; + } + } + private ColorRect _L_ColorRect; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: PauseMenu.VBoxContainer + /// + public VBoxContainer L_VBoxContainer + { + get + { + if (_L_VBoxContainer == null) _L_VBoxContainer = new VBoxContainer((PauseMenuPanel)this, GetNode("VBoxContainer")); + return _L_VBoxContainer; + } + } + private VBoxContainer _L_VBoxContainer; + + + public PauseMenu() : base(nameof(PauseMenu)) + { + } + + public sealed override void OnInitNestedUi() + { + + } + + /// + /// 类型: , 路径: PauseMenu.ColorRect + /// + public class ColorRect : UiNode + { + public ColorRect(PauseMenuPanel uiPanel, Godot.ColorRect node) : base(uiPanel, node) { } + public override ColorRect Clone() => new (UiPanel, (Godot.ColorRect)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: PauseMenu.VBoxContainer.Continue + /// + public class Continue : UiNode + { + public Continue(PauseMenuPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override Continue Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: PauseMenu.VBoxContainer.Restart + /// + public class Restart : UiNode + { + public Restart(PauseMenuPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override Restart Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: PauseMenu.VBoxContainer.Exit + /// + public class Exit : UiNode + { + public Exit(PauseMenuPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override Exit Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: PauseMenu.VBoxContainer + /// + public class VBoxContainer : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: PauseMenu.Continue + /// + public Continue L_Continue + { + get + { + if (_L_Continue == null) _L_Continue = new Continue(UiPanel, Instance.GetNode("Continue")); + return _L_Continue; + } + } + private Continue _L_Continue; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: PauseMenu.Restart + /// + public Restart L_Restart + { + get + { + if (_L_Restart == null) _L_Restart = new Restart(UiPanel, Instance.GetNode("Restart")); + return _L_Restart; + } + } + private Restart _L_Restart; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: PauseMenu.Exit + /// + public Exit L_Exit + { + get + { + if (_L_Exit == null) _L_Exit = new Exit(UiPanel, Instance.GetNode("Exit")); + return _L_Exit; + } + } + private Exit _L_Exit; + + public VBoxContainer(PauseMenuPanel uiPanel, Godot.VBoxContainer node) : base(uiPanel, node) { } + public override VBoxContainer Clone() => new (UiPanel, (Godot.VBoxContainer)Instance.Duplicate()); + } + + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: PauseMenu.ColorRect + /// + public ColorRect S_ColorRect => L_ColorRect; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: PauseMenu.VBoxContainer.Continue + /// + public Continue S_Continue => L_VBoxContainer.L_Continue; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: PauseMenu.VBoxContainer.Restart + /// + public Restart S_Restart => L_VBoxContainer.L_Restart; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: PauseMenu.VBoxContainer.Exit + /// + public Exit S_Exit => L_VBoxContainer.L_Exit; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: PauseMenu.VBoxContainer + /// + public VBoxContainer S_VBoxContainer => L_VBoxContainer; + +} diff --git a/DungeonShooting_Godot/src/game/ui/pauseMenu/PauseMenuPanel.cs b/DungeonShooting_Godot/src/game/ui/pauseMenu/PauseMenuPanel.cs new file mode 100644 index 0000000..19e06a1 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/pauseMenu/PauseMenuPanel.cs @@ -0,0 +1,66 @@ +using Godot; + +namespace UI.PauseMenu; + +public partial class PauseMenuPanel : PauseMenu +{ + + public override void OnCreateUi() + { + S_Continue.Instance.Pressed += OnContinueClick; + S_Restart.Instance.Pressed += OnRestartClick; + S_Exit.Instance.Pressed += OnExitClick; + + if (GameApplication.Instance.DungeonManager.IsEditorMode) //在编辑器模式下打开的Ui + { + S_Exit.Instance.Text = "返回编辑器"; + } + } + + public override void Process(float delta) + { + if (Input.IsActionJustPressed("ui_cancel")) //返回游戏 + { + OnContinueClick(); + } + } + + //继续游戏 + private void OnContinueClick() + { + GameApplication.Instance.World.Pause = false; + GameApplication.Instance.Cursor.SetGuiMode(false); + Destroy(); + } + + //重新开始 + private void OnRestartClick() + { + Destroy(); + if (GameApplication.Instance.DungeonManager.IsEditorMode) //在编辑器模式下打开的Ui + { + EditorPlayManager.Restart(); + } + else //正常重新开始 + { + GameApplication.Instance.DungeonManager.RestartDungeon(GameApplication.Instance.DungeonConfig); + } + } + + //退出地牢 + private void OnExitClick() + { + Destroy(); + if (GameApplication.Instance.DungeonManager.IsEditorMode) //在编辑器模式下打开的Ui + { + EditorPlayManager.Exit(); + } + else //正常关闭Ui + { + GameApplication.Instance.DungeonManager.ExitDungeon(() => + { + UiManager.Open_Main(); + }); + } + } +}