Compare commits

..

15 Commits

Author SHA1 Message Date
2c6f8804ba
Do not create duplicate ui nodes in the same ui group.
禁止在同一个ui组,创建重复的ui节点。
2024-09-18 23:19:38 +08:00
899337e8e3
Fixes pickups flying out of walls, supports pushing furniture by pressing f.
修复可拾捡物飞出墙壁,支持按下f键推动家具。
2024-09-18 21:28:54 +08:00
cb19423cb0
Modifying a node Name.
修改节点名称。
2024-09-18 20:20:02 +08:00
c25d985f87
Improve the efficiency of backpack UI toggle visibility. Prepare for the upcoming workbench UI.
提升背包UI切换可见度时的效率。为即将到来的工作台UI做准备。
2024-09-14 23:38:57 +08:00
ba11bf06da
Make spell separation table.
制作法术分离工作台。
2024-09-13 23:04:39 +08:00
fc8d33b28d
Update the list of contributors.
更新贡献者名单。
2024-09-09 22:26:07 +08:00
4ae8a5d470
Fixed an issue where some room slots could not be blocked.
修复某些房间槽无法被堵住的问题。
2024-09-09 22:22:03 +08:00
1e019339d8
After the map is generated, tiles will be copied from the Barrier layer when unused slots appear. Plug the slot.
生成地图后,当出现尚未使用的插槽,将会从Barrier层拷贝瓦片。堵上插槽。
2024-09-08 21:17:05 +08:00
ce8f9121a5
No more drawing unexplored rooms.
不再绘制未探索过的房间了。
2024-09-08 09:45:14 +08:00
26c0843202
Hands over the responsibility of creating room previews to the minimap.
将创建房间预览图的职责移交给迷你地图。
2024-09-06 23:36:21 +08:00
ab0d05d16d
Makes the map follow the player's movements.
使地图跟随玩家移动。
2024-09-06 22:56:36 +08:00
Cold-Mint
ed4339f390
Merge pull request #8 from Ride-A-Pig/master
Minimap bug fix
2024-09-05 12:42:58 +08:00
Ride_A_Pig
ab10d75b24 Minimap bug fix
修复小地图错位问题
2024-09-05 12:34:41 +08:00
781c50ee30
Add debugging information to the mini map.
为迷你地图加入调试信息。
2024-09-05 11:50:05 +08:00
41a2cebf41
Improved recoil algorithm.
改进后座力算法。
2024-09-04 23:23:22 +08:00
42 changed files with 967 additions and 221 deletions

View File

@ -117,4 +117,5 @@ log_contact_with_tiles_disables_damage,与瓦片接触禁用伤害。,"Disabling
log_hide_all_node,隐藏{0}个节点。,Hide {0} nodes.,{0}ノードを非表示にします。
log_show_all_node,显示{0}个节点。,Show {0} nodes.,{0}ノードが表示されます。
log_enter_the_screen,进入屏幕。,Enter screen,画面に移動。
log_exit_the_screen,退出屏幕。,Exit screen,画面を終了します。
log_exit_the_screen,退出屏幕。,Exit screen,画面を終了します。
log_failed_to_create_room_preview,创建{0}的房间预览图失败。,Failed to create a room preview of the {0}.,{0}の部屋のプレビューを作成できませんでした。
1 id zh en ja
117 log_hide_all_node 隐藏{0}个节点。 Hide {0} nodes. {0}ノードを非表示にします。
118 log_show_all_node 显示{0}个节点。 Show {0} nodes. {0}ノードが表示されます。
119 log_enter_the_screen 进入屏幕。 Enter screen 画面に移動。
120 log_exit_the_screen 退出屏幕。 Exit screen 画面を終了します。
121 log_failed_to_create_room_preview 创建{0}的房间预览图失败。 Failed to create a room preview of the {0}. {0}の部屋のプレビューを作成できませんでした。

View File

@ -0,0 +1,28 @@
[gd_scene load_steps=5 format=3 uid="uid://djsh4unystlf0"]
[ext_resource type="Texture2D" uid="uid://qowlv0viyqbb" path="res://sprites/ui/Null.png" id="1_346je"]
[ext_resource type="Script" path="res://scripts/furniture/GuiFurniture.cs" id="1_t1qdg"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_vx4tg"]
size = Vector2(31, 31)
[sub_resource type="CircleShape2D" id="CircleShape2D_in1f7"]
radius = 52.6118
[node name="RigidBody2D" type="RigidBody2D"]
collision_layer = 256
collision_mask = 160
script = ExtResource("1_t1qdg")
[node name="Null" type="Sprite2D" parent="."]
texture = ExtResource("1_346je")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(-0.5, -0.5)
shape = SubResource("RectangleShape2D_vx4tg")
[node name="OperateArea2D" type="Area2D" parent="."]
visible = false
[node name="CollisionShape2D" type="CollisionShape2D" parent="OperateArea2D"]
shape = SubResource("CircleShape2D_in1f7")

View File

@ -0,0 +1,87 @@
[gd_scene load_steps=9 format=4 uid="uid://br778i2b0skil"]
[ext_resource type="Script" path="res://scripts/map/AiCharacterSpawn.cs" id="1_y2vgj"]
[ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="2_ngfnn"]
[ext_resource type="Texture2D" uid="uid://drw45jlmfo0su" path="res://sprites/light/White_100.png" id="3_r2p3x"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(505, 186)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_o85u0"]
size = Vector2(20, 48)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_30r3c"]
size = Vector2(20, 46)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_7tsse"]
size = Vector2(53, 24)
[sub_resource type="NavigationPolygon" id="NavigationPolygon_rh1gx"]
vertices = PackedVector2Array(499.469, 106.328, 501.523, 150.039, 9.3125, 151.953, 470.156, 107.352, 10.7031, 107, 43.1562, 107, 170.328, 40.6797, 169.344, 11, 216.617, 11, 218.617, 41.9297, 469.148, 43.9219, 42.1484, 44.6875)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3), PackedInt32Array(3, 2, 4, 5), PackedInt32Array(6, 7, 8, 9), PackedInt32Array(10, 3, 5, 9), PackedInt32Array(6, 9, 5, 11)])
outlines = Array[PackedVector2Array]([PackedVector2Array(479, 34, 228, 32, 226, 1, 159, 1, 160, 31, 32, 35, 33, 97, 1, 97, -1, 162, 512, 160, 509, 96, 480, 97)])
source_geometry_group_name = &"navigation_polygon_source_group"
[node name="InitialRoom" type="Node2D"]
[node name="RoomArea" type="Area2D" parent="."]
collision_mask = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomArea"]
position = Vector2(255.5, 97)
shape = SubResource("RectangleShape2D_kiih8")
[node name="RoomSlotList" type="Node2D" parent="."]
[node name="Area2D" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D"]
position = Vector2(17, 129)
shape = SubResource("RectangleShape2D_o85u0")
[node name="Area2D2" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D2"]
position = Vector2(498, 128)
shape = SubResource("RectangleShape2D_30r3c")
[node name="Area2D3" type="Area2D" parent="RoomSlotList"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D3"]
position = Vector2(193, 15)
shape = SubResource("RectangleShape2D_7tsse")
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(260, 87)
script = ExtResource("1_y2vgj")
ResPath = "res://prefab/entitys/DelivererOfDarkMagic.tscn"
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
navigation_polygon = SubResource("NavigationPolygon_rh1gx")
[node name="TileMap" type="Node2D" parent="."]
[node name="BackgroundWall" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAOAAEAAQAGAAUAAAAOAAIAAQAGAAUAAAAOAAMAAQAGAAUAAAAOAAQAAQAGAAUAAAANAAQAAQAGAAUAAAANAAMAAQAGAAUAAAANAAIAAQAGAAUAAAANAAEAAQAGAAUAAAAMAAEAAQAGAAUAAAALAAEAAQAGAAUAAAAKAAEAAQAGAAUAAAAJAAEAAQAGAAUAAAAIAAEAAQAGAAUAAAAHAAEAAQAGAAUAAAAGAAEAAQAGAAUAAAAFAAEAAQAGAAUAAAAEAAEAAQAGAAUAAAADAAEAAQAGAAUAAAACAAEAAQAGAAUAAAABAAEAAQAGAAUAAAABAAIAAQAGAAUAAAACAAIAAQAGAAUAAAADAAIAAQAGAAUAAAAEAAIAAQAGAAUAAAAFAAIAAQAGAAUAAAAGAAIAAQAGAAUAAAAHAAIAAQAGAAUAAAAIAAIAAQAGAAUAAAAJAAIAAQAGAAUAAAAKAAIAAQAGAAUAAAALAAIAAQAGAAUAAAAMAAIAAQAGAAUAAAAMAAMAAQAGAAUAAAALAAMAAQAGAAUAAAAKAAMAAQAGAAUAAAAJAAMAAQAGAAUAAAAIAAMAAQAEAAUAAAAHAAMAAQAGAAUAAAAGAAMAAQAGAAUAAAAFAAMAAQAEAAUAAAAEAAMAAQAGAAUAAAADAAMAAQAGAAUAAAACAAMAAQAGAAUAAAABAAMAAQAGAAUAAAABAAQAAQAGAAUAAAACAAQAAQAGAAUAAAADAAQAAQAGAAUAAAAEAAQAAQAGAAUAAAAFAAQAAQAGAAUAAAAGAAQAAQAGAAUAAAAHAAQAAQAGAAUAAAAIAAQAAQAGAAUAAAAJAAQAAQAGAAUAAAAKAAQAAQAGAAUAAAALAAQAAQAGAAUAAAAMAAQAAQAGAAUAAAAAAAMAAQAGAAUAAAAAAAQAAQAGAAUAAAAPAAQAAQAGAAUAAAAPAAMAAQAGAAUAAAAFAAAAAQAGAAUAAAAGAAAAAQAGAAUAAAA=")
tile_set = ExtResource("2_ngfnn")
navigation_enabled = false
[node name="BackgroundDecoration" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_set = ExtResource("2_ngfnn")
[node name="Ground" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAAAAAAAQAAAAMAAAAAAAEAAQACAAEAAAAAAAIAAQACAAEAAAABAAAAAQABAAIAAAACAAAAAQABAAIAAAADAAAAAQABAAIAAAAEAAAAAQABAAIAAAAHAAAAAQABAAIAAAAIAAAAAQABAAIAAAAJAAAAAQABAAIAAAAKAAAAAQABAAIAAAALAAAAAQABAAIAAAAMAAAAAQABAAIAAAANAAAAAQABAAIAAAAOAAAAAQABAAMAAAAPAAAAAQACAAMAAAAPAAEAAQACAAQAAAAPAAIAAQACAAQAAAABAAUAAQABAAAAAAACAAUAAQABAAAAAAADAAUAAQABAAAAAAAEAAUAAQABAAAAAAAFAAUAAQABAAAAAAAGAAUAAQABAAAAAAAHAAUAAQABAAAAAAAIAAUAAQABAAAAAAAJAAUAAQABAAAAAAAKAAUAAQABAAAAAAALAAUAAQABAAAAAAAMAAUAAQABAAAAAAANAAUAAQABAAAAAAAOAAUAAQABAAAAAAAAAAUAAQAAAAUAAAAPAAUAAQACAAUAAAAFAAAAAQAEAAQAAAAGAAAAAQAEAAQAAAA=")
tile_set = ExtResource("2_ngfnn")
[node name="Barrier" type="TileMapLayer" parent="TileMap"]
tile_map_data = PackedByteArray("AAAPAAMAAQAAAAEAAAAPAAQAAQAAAAEAAAAAAAMAAQACAAEAAAAAAAQAAQACAAEAAAAFAAAAAQABAAIAAAAGAAAAAQABAAIAAAA=")
tile_set = ExtResource("2_ngfnn")
[node name="PointLight2D" type="PointLight2D" parent="."]
visible = false
position = Vector2(256, 96.5)
scale = Vector2(15.875, 5.96875)
texture = ExtResource("3_r2p3x")

View File

@ -76,6 +76,10 @@ use_parent_material = true
tile_map_data = PackedByteArray("AAAAAAAAAQAAAAMAAAAAAAEAAQACAAEAAAAAAAIAAQACAAEAAAABAAAAAQABAAIAAAACAAAAAQABAAIAAAADAAAAAQABAAIAAAAEAAAAAQABAAIAAAAHAAAAAQABAAIAAAAIAAAAAQABAAIAAAAJAAAAAQABAAIAAAAKAAAAAQABAAIAAAALAAAAAQABAAIAAAAMAAAAAQABAAIAAAANAAAAAQABAAIAAAAOAAAAAQABAAMAAAAPAAAAAQACAAMAAAAPAAEAAQACAAQAAAAPAAIAAQACAAQAAAABAAUAAQABAAAAAAACAAUAAQABAAAAAAADAAUAAQABAAAAAAAEAAUAAQABAAAAAAAFAAUAAQABAAAAAAAGAAUAAQABAAAAAAAHAAUAAQABAAAAAAAIAAUAAQABAAAAAAAJAAUAAQABAAAAAAAKAAUAAQABAAAAAAALAAUAAQABAAAAAAAMAAUAAQABAAAAAAANAAUAAQABAAAAAAAOAAUAAQABAAAAAAAAAAUAAQAAAAUAAAAPAAUAAQACAAUAAAAFAAAAAQAEAAQAAAAGAAAAAQAEAAQAAAA=")
tile_set = ExtResource("1_a15hy")
[node name="Barrier" type="TileMapLayer" parent="TileMap"]
tile_map_data = PackedByteArray("AAAPAAMAAQAAAAEAAAAPAAQAAQAAAAEAAAAAAAMAAQACAAEAAAAAAAQAAQACAAEAAAAFAAAAAQABAAIAAAAGAAAAAQABAAIAAAA=")
tile_set = ExtResource("1_a15hy")
[node name="PointLight2D" type="PointLight2D" parent="."]
visible = false
position = Vector2(256, 96.5)

View File

@ -77,6 +77,11 @@ use_parent_material = true
tile_map_data = PackedByteArray("AAAAAAAAAQAAAAMAAAAAAAEAAQACAAEAAAAAAAIAAQACAAEAAAABAAAAAQABAAIAAAACAAAAAQABAAIAAAADAAAAAQABAAIAAAAEAAAAAQABAAIAAAAFAAAAAQABAAIAAAAGAAAAAQABAAIAAAAHAAAAAQABAAIAAAAIAAAAAQABAAIAAAAJAAAAAQABAAIAAAAKAAAAAQABAAIAAAALAAAAAQABAAIAAAAMAAAAAQABAAIAAAANAAAAAQABAAIAAAAOAAAAAQABAAMAAAAPAAAAAQACAAMAAAAPAAEAAQACAAQAAAAPAAIAAQACAAQAAAABAAUAAQABAAAAAAACAAUAAQABAAAAAAADAAUAAQABAAAAAAAEAAUAAQABAAAAAAAFAAUAAQABAAAAAAAIAAUAAQABAAAAAAAJAAUAAQABAAAAAAAKAAUAAQABAAAAAAALAAUAAQABAAAAAAAMAAUAAQABAAAAAAANAAUAAQABAAAAAAAOAAUAAQABAAAAAAAAAAUAAQAAAAUAAAAPAAUAAQACAAUAAAAGAAUAAQAEAAQAAAAHAAUAAQAEAAQAAAA=")
tile_set = ExtResource("1_rn2om")
[node name="Barrier" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAAAAMAAQACAAEAAAAAAAQAAQACAAEAAAAPAAMAAQAAAAEAAAAPAAQAAQAAAAEAAAAGAAUAAQABAAAAAAAHAAUAAQABAAAAAAA=")
tile_set = ExtResource("1_rn2om")
[node name="PointLight2D" type="PointLight2D" parent="."]
visible = false
position = Vector2(256.5, 94)

View File

@ -1,9 +1,10 @@
[gd_scene load_steps=8 format=4 uid="uid://du5ldsp613fei"]
[gd_scene load_steps=9 format=4 uid="uid://du5ldsp613fei"]
[ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="1_rn2om"]
[ext_resource type="Script" path="res://scripts/map/PlayerSpawn.cs" id="2_6p8mv"]
[ext_resource type="Script" path="res://scripts/map/ItemSpawn.cs" id="3_v1tlc"]
[ext_resource type="Texture2D" uid="uid://drw45jlmfo0su" path="res://sprites/light/White_100.png" id="5_4pssd"]
[ext_resource type="PackedScene" uid="uid://djsh4unystlf0" path="res://prefab/furnitures/MagicSeparator.tscn" id="5_7c8bh"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(507, 251)
@ -65,8 +66,17 @@ use_parent_material = true
tile_map_data = PackedByteArray("AAAAAAAAAQAAAAMAAAAAAAEAAQACAAEAAAAAAAIAAQACAAEAAAAAAAMAAQACAAEAAAAAAAQAAQACAAEAAAAAAAcAAQAAAAUAAAAPAAAAAQACAAMAAAAPAAEAAQACAAQAAAAPAAIAAQACAAQAAAAPAAMAAQACAAQAAAAPAAQAAQACAAQAAAAPAAcAAQACAAUAAAAAAAUAAQACAAEAAAAAAAYAAQACAAEAAAABAAAAAQABAAIAAAACAAAAAQABAAIAAAADAAAAAQABAAIAAAAEAAAAAQABAAIAAAAFAAAAAQABAAIAAAAGAAAAAQABAAIAAAAHAAAAAQABAAIAAAAIAAAAAQABAAIAAAAJAAAAAQABAAIAAAAKAAAAAQABAAIAAAALAAAAAQABAAIAAAAMAAAAAQABAAIAAAANAAAAAQABAAIAAAAOAAAAAQABAAMAAAABAAcAAQABAAAAAAACAAcAAQABAAAAAAADAAcAAQABAAAAAAAEAAcAAQABAAAAAAAFAAcAAQABAAAAAAAGAAcAAQABAAAAAAAHAAcAAQABAAAAAAAIAAcAAQABAAAAAAAJAAcAAQABAAAAAAAKAAcAAQABAAAAAAALAAcAAQABAAAAAAAMAAcAAQABAAAAAAANAAcAAQABAAAAAAAOAAcAAQABAAAAAAA=")
tile_set = ExtResource("1_rn2om")
[node name="Barrier" type="TileMapLayer" parent="TileMap"]
use_parent_material = true
tile_map_data = PackedByteArray("AAAPAAUAAQAAAAEAAAAPAAYAAQAAAAEAAAA=")
tile_set = ExtResource("1_rn2om")
[node name="PointLight2D" type="PointLight2D" parent="."]
visible = false
position = Vector2(259.5, 128.5)
scale = Vector2(16.0312, 7.96875)
texture = ExtResource("5_4pssd")
[node name="RigidBody2D" parent="." instance=ExtResource("5_7c8bh")]
position = Vector2(149, 109)
collision_mask = 0

View File

@ -21,7 +21,7 @@ polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3, 4), PackedInt32
outlines = Array[PackedVector2Array]([PackedVector2Array(35, 39, 36, 415, 0, 417, 3, 481, 733, 477, 729, 415, 706, 415, 701, 93, 734, 89, 731, 34)])
source_geometry_group_name = &"navigation_polygon_source_group"
[node name="InitialRoom" type="Node2D"]
[node name="InitialRoom2" type="Node2D"]
[node name="RoomArea" type="Area2D" parent="."]
collision_mask = 0
@ -45,10 +45,9 @@ position = Vector2(720, 61)
shape = SubResource("RectangleShape2D_30r3c")
[node name="Area2D3" type="Area2D" parent="RoomSlotList"]
position = Vector2(138, 11)
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D3"]
position = Vector2(584, 437)
position = Vector2(722, 447)
shape = SubResource("RectangleShape2D_6qg1t")
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
@ -72,6 +71,12 @@ use_parent_material = true
tile_map_data = PackedByteArray("AAAAAAAAAQAAAAMAAAAAAAEAAQACAAEAAAAAAAIAAQACAAEAAAAAAAMAAQACAAEAAAAAAAQAAQACAAEAAAAAAAUAAQACAAEAAAAAAAYAAQACAAEAAAABAAAAAQABAAIAAAACAAAAAQABAAIAAAADAAAAAQABAAIAAAAEAAAAAQABAAIAAAAFAAAAAQABAAIAAAAGAAAAAQABAAIAAAAHAAAAAQABAAIAAAAIAAAAAQABAAIAAAAJAAAAAQABAAIAAAAKAAAAAQABAAIAAAALAAAAAQABAAIAAAAMAAAAAQABAAIAAAANAAAAAQABAAIAAAAOAAAAAQABAAIAAAAPAAAAAQABAAIAAAAQAAAAAQABAAIAAAARAAAAAQABAAIAAAASAAAAAQABAAIAAAATAAAAAQABAAIAAAAUAAAAAQABAAIAAAAVAAAAAQABAAIAAAAWAAAAAQACAAMAAAAWAAMAAQAAAAEAAAAWAAQAAQAAAAEAAAAWAAUAAQAAAAEAAAAWAAYAAQAAAAEAAAAWAAcAAQAAAAEAAAAWAAgAAQAAAAEAAAAWAAkAAQAAAAEAAAAWAAoAAQAAAAEAAAAWAAsAAQAAAAEAAAAWAAwAAQAAAAEAAAAAAAcAAQACAAEAAAAAAAgAAQACAAEAAAAAAAkAAQACAAEAAAAAAAoAAQACAAEAAAAAAAsAAQACAAEAAAAAAAwAAQACAAEAAAAVAA8AAQABAAAAAAAUAA8AAQABAAAAAAATAA8AAQABAAAAAAASAA8AAQABAAAAAAARAA8AAQABAAAAAAAQAA8AAQABAAAAAAAPAA8AAQABAAAAAAAOAA8AAQABAAAAAAANAA8AAQABAAAAAAAMAA8AAQABAAAAAAALAA8AAQABAAAAAAAKAA8AAQABAAAAAAAJAA8AAQABAAAAAAAIAA8AAQABAAAAAAAHAA8AAQABAAAAAAAGAA8AAQABAAAAAAAFAA8AAQABAAAAAAAEAA8AAQABAAAAAAADAA8AAQABAAAAAAACAA8AAQABAAAAAAABAA8AAQABAAAAAAAAAA8AAQAAAAUAAAAWAA8AAQACAAUAAAASAAsAAQAEAAQAAAATAAsAAQAEAAQAAAAUAAsAAQAEAAQAAAAVAAsAAQAFAAQAAAABAAsAAQADAAQAAAACAAsAAQAEAAQAAAADAAsAAQAEAAQAAAAEAAsAAQAEAAQAAAAFAAsAAQAEAAQAAAAGAAsAAQAEAAQAAAAHAAsAAQAEAAQAAAAIAAsAAQAEAAQAAAAOAAsAAQAEAAQAAAAPAAsAAQAEAAQAAAAQAAsAAQAEAAQAAAARAAsAAQAEAAQAAAABAAoAAQAEAAMAAAAVAAoAAQAEAAMAAAACAAoAAQAEAAIAAAAUAAoAAQAEAAIAAAANAAQAAQAEAAQAAAANAAwAAQAEAAQAAAAMAA0AAQAEAAQAAAALAA4AAQAEAAQAAAAJAAsAAQAEAAQAAAAGAAoAAQAEAAQAAAAHAAkAAQAEAAQAAAAIAAgAAQAEAAQAAAAJAAcAAQAEAAQAAAAKAAcAAQAEAAQAAAALAAcAAQAEAAQAAAAMAAcAAQAEAAQAAAANAAcAAQAEAAQAAAAOAAcAAQAEAAQAAAAPAAcAAQAEAAQAAAAQAAcAAQAEAAQAAAARAAcAAQAEAAQAAAASAAcAAQAEAAQAAAATAAcAAQAEAAQAAAAUAAcAAQAEAAQAAAAVAAcAAQAEAAQAAAABAAcAAQAEAAQAAAACAAcAAQAEAAQAAAADAAcAAQAEAAQAAAAEAAcAAQAEAAQAAAAFAAcAAQAEAAQAAAALAAYAAQAEAAQAAAAMAAUAAQAEAAQAAAAPAAMAAQAEAAQAAAAQAAMAAQAEAAQAAAARAAMAAQAEAAQAAAASAAMAAQAEAAQAAAATAAMAAQAEAAQAAAAUAAMAAQAEAAQAAAAVAAMAAQAEAAQAAAABAAMAAQAEAAQAAAACAAMAAQAEAAQAAAADAAMAAQAEAAQAAAAEAAMAAQAEAAQAAAAFAAMAAQAEAAQAAAAGAAMAAQAEAAQAAAAHAAMAAQAEAAQAAAAIAAMAAQAEAAQAAAAJAAMAAQAEAAQAAAA=")
tile_set = ExtResource("1_rn2om")
[node name="Barrier" type="TileMapLayer" parent="TileMap"]
visible = false
use_parent_material = true
tile_map_data = PackedByteArray("AAAWAA0AAQAAAAEAAAAWAA4AAQAAAAEAAAAWAAEAAQAAAAEAAAAWAAIAAQAAAAEAAAAAAA0AAQACAAEAAAAAAA4AAQACAAEAAAA=")
tile_set = ExtResource("1_rn2om")
[node name="PointLight2D" type="PointLight2D" parent="."]
visible = false
position = Vector2(367.5, 258)

View File

@ -147,6 +147,11 @@ hotbar_previous={
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":4,"axis_value":1.0,"script":null)
]
}
push={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":70,"physical_keycode":0,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
]
}
[internationalization]
@ -162,6 +167,7 @@ locale/translations=PackedStringArray("res://locals/DeathInfo.en.translation", "
2d_physics/layer_6="Platform"
2d_physics/layer_7="Mob"
2d_physics/layer_8="Wall"
2d_physics/layer_9="Furniture"
[physics]

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=8 format=3 uid="uid://bnftvkj2cido7"]
[gd_scene load_steps=9 format=3 uid="uid://bnftvkj2cido7"]
[ext_resource type="Script" path="res://scripts/loader/sceneLoader/GameSceneLoader.cs" id="1_mqdgt"]
[ext_resource type="Texture2D" uid="uid://cs6e0af876ss5" path="res://sprites/ui/HeartEmpty.png" id="2_n1yht"]
@ -7,6 +7,7 @@
[ext_resource type="Script" path="res://scripts/FpsLabel.cs" id="5_dis4v"]
[ext_resource type="PackedScene" uid="uid://c74180dtf7j7a" path="res://scenes/mapContainer.tscn" id="6_ljdj4"]
[ext_resource type="PackedScene" uid="uid://bb188382q7btp" path="res://scenes/gameOverMenu.tscn" id="6_yjmrv"]
[ext_resource type="Script" path="res://scripts/utils/UiGroup.cs" id="7_p0u6a"]
[node name="Game" type="Node2D"]
script = ExtResource("1_mqdgt")
@ -94,7 +95,7 @@ grow_horizontal = 2
[node name="MapContainer" parent="CanvasLayer/Control" instance=ExtResource("6_ljdj4")]
layout_mode = 1
[node name="BackpackUIContainer" type="Control" parent="CanvasLayer"]
[node name="DynamicUiGroup" type="Control" parent="CanvasLayer"]
visible = false
layout_mode = 3
anchors_preset = 15
@ -103,6 +104,7 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
script = ExtResource("7_p0u6a")
[node name="GameOverMenu" parent="CanvasLayer" instance=ExtResource("6_yjmrv")]
visible = false

View File

@ -1,6 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://c74180dtf7j7a"]
[gd_scene load_steps=4 format=3 uid="uid://c74180dtf7j7a"]
[ext_resource type="Texture2D" uid="uid://c35bsle7thcnh" path="res://sprites/ui/MiniMapBg.png" id="1_h88bi"]
[ext_resource type="Script" path="res://scripts/map/miniMap/MiniMap.cs" id="2_ltp8b"]
[ext_resource type="Texture2D" uid="uid://cfpcm0hkmpu38" path="res://sprites/ui/mark.png" id="3_x80y0"]
[node name="MapContainer" type="Control"]
layout_mode = 3
@ -28,10 +30,10 @@ anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -174.0
offset_top = -177.0
offset_right = -24.0
offset_bottom = -27.0
offset_left = -169.0
offset_top = -168.0
offset_right = -19.0
offset_bottom = -18.0
grow_horizontal = 0
grow_vertical = 0
texture = ExtResource("1_h88bi")
@ -39,5 +41,10 @@ patch_margin_left = 7
patch_margin_top = 7
patch_margin_right = 7
patch_margin_bottom = 7
script = ExtResource("2_ltp8b")
[node name="RoomPreviewContainer" type="Node2D" parent="MiniMap"]
[node name="Mark" type="Sprite2D" parent="MiniMap"]
position = Vector2(75, 75)
texture = ExtResource("3_x80y0")

View File

@ -20,7 +20,7 @@ public static class Config
/// </summary>
public const string Test = "test";
}
/// <summary>
/// <para>Difficulty</para>
/// <para>游戏难度</para>
@ -32,11 +32,13 @@ public static class Config
/// <para>简单模式</para>
/// </summary>
public const int Easy = 0;
/// <summary>
/// <para>Normal mode</para>
/// <para>正常模式</para>
/// </summary>
public const int Normal = 1;
/// <summary>
/// <para>Hard mode</para>
/// <para>困难模式</para>
@ -82,6 +84,12 @@ public static class Config
/// </summary>
public const float ThrownItemsHitEnemiesReduceSpeedByPercentage = 0.5f;
/// <summary>
/// <para>Scale of the room preview view</para>
/// <para>房间预览图的缩放</para>
/// </summary>
public const float RoomPreviewScale = 3f;
/// <summary>
/// <para>How much blood does a heart represent</para>
/// <para>一颗心代表多少血量</para>
@ -94,12 +102,6 @@ public static class Config
/// </summary>
public const string ModManifestFileName = "ModManifest.yaml";
/// <summary>
/// <para>The maximum number of stacked items in a single inventory</para>
/// <para>单个物品栏最大堆叠的物品数量</para>
/// </summary>
public const int MaxStackQuantity = 99;
/// <summary>
/// <para>Text change buffering Time How long does it take to execute the actual event after an event with a text change listener is triggered? (Anti-shake processing time), unit: milliseconds</para>
/// <para>当添加了文本改变监听器的事件被触发后,多长时间后执行实际事件?(防抖处理时长),单位:毫秒</para>
@ -136,7 +138,7 @@ public static class Config
/// <para>快捷栏上有多少个物品槽</para>
/// </summary>
public const int HotBarSize = 9;
/// <summary>
/// <para>Whether version isolation is enabled</para>
@ -375,6 +377,12 @@ public static class Config
/// </summary>
public const int DefaultMaxHp = 100;
/// <summary>
/// <para>The default durability of furniture</para>
/// <para>家具的默认耐久度</para>
/// </summary>
public const int DefaultMaxDurability = 50;
/// <summary>
/// <para>When a creature takes damage, how long to hide the bloodline again</para>
/// <para>生物受到伤害时,要在多长时间后再次隐藏血条</para>
@ -420,28 +428,25 @@ public static class Config
public static class OffsetAngleMode
{
/// <summary>
/// <para>Random(Default)</para>
/// <para>随机的(默认)</para>
/// </summary>
public const int Random = 0;
/// <summary>
/// <para>AlwaysSame</para>
/// <para>永远不变的偏移角度</para>
/// </summary>
public const int AlwaysSame = 1;
/// <summary>
/// <para>Cross</para>
/// <para>交叉变换</para>
/// </summary>
public const int Cross = 2;
}
/// <summary>
/// <para>Physical collision layer number</para>
/// <para>物理碰撞层 序号</para>
@ -449,13 +454,30 @@ public static class Config
public static class LayerNumber
{
public const int RoomArea = 1;
/// <summary>
/// <para>Floor</para>
/// <para>地板</para>
/// </summary>
public const int Floor = 2;
public const int Player = 3;
public const int PickAbleItem = 4;
public const int Projectile = 5;
/// <summary>
/// <para>Platform</para>
/// <para>平台</para>
/// </summary>
public const int Platform = 6;
public const int Mob = 7;
/// <summary>
/// <para>Wall</para>
/// <para>墙壁</para>
/// </summary>
public const int Wall = 8;
/// <summary>
/// <para>Furniture</para>
/// <para>家具</para>
/// </summary>
public const int Furniture = 9;
}
/// <summary>
@ -474,6 +496,12 @@ public static class Config
/// </remarks>
public const string Ground = "Ground";
/// <summary>
/// <para>Barrier</para>
/// <para>屏障</para>
/// </summary>
public const string Barrier = "Barrier";
/// <summary>
/// <para>Background decorative layer</para>
/// <para>背景装饰层</para>

View File

@ -4,10 +4,10 @@ using ColdMint.scripts.map.events;
namespace ColdMint.scripts;
/// <summary>
/// <para>EventManager</para>
/// <para>事件管理器</para>
/// <para>EventBus</para>
/// <para>事件总线</para>
/// </summary>
public static class EventManager
public static class EventBus
{
/// <summary>
/// <para>Event when the AI character is generated</para>
@ -38,10 +38,4 @@ public static class EventManager
/// <para>地图生成完成事件</para>
/// </summary>
public static Action<MapGenerationCompleteEvent>? MapGenerationCompleteEvent;
/// <summary>
/// <para>Player Instance Change Event</para>
/// <para>玩家实例改变事件</para>
/// </summary>
public static Action<PlayerInstanceChangeEvent>? PlayerInstanceChangeEvent;
}

View File

@ -1,7 +1,6 @@
using ColdMint.scripts.character;
using ColdMint.scripts.inventory;
using ColdMint.scripts.loader.uiLoader;
using ColdMint.scripts.map.events;
using ColdMint.scripts.map.miniMap;
using ColdMint.scripts.utils;
using Godot;
@ -14,11 +13,11 @@ namespace ColdMint.scripts;
public static class GameSceneDepend
{
/// <summary>
/// <para>The midpoint of the minimap</para>
/// <para>迷你地图的中点</para>
/// <para>MiniMap</para>
/// <para>迷你地图</para>
/// </summary>
public static Vector2 MiniMapMidpointCoordinate;
public static MiniMap? MiniMap { get; set; }
private static Player? _player;
/// <summary>
@ -31,13 +30,10 @@ public static class GameSceneDepend
set
{
_player = value;
//Broadcast the event to the outside when the player instance changes.
//当玩家实例改变时,向外广播事件。
var playerInstanceChangeEvent = new PlayerInstanceChangeEvent
if (MiniMap != null)
{
PlayerInstance = _player
};
EventManager.PlayerInstanceChangeEvent?.Invoke(playerInstanceChangeEvent);
MiniMap.OwnerNode = _player;
}
}
}
@ -46,12 +42,6 @@ public static class GameSceneDepend
/// <para>鼠标进入到某个角色的范围内时,会将其视作目标</para>
/// </summary>
public static Node2D? TemporaryTargetNode { get; set; }
/// <summary>
/// <para>MiniMapContainerNode</para>
/// <para>迷你地图容器节点</para>
/// </summary>
public static Node2D? MiniMapContainerNode { get; set; }
/// <summary>
/// <para>ProjectileContainer</para>
@ -101,44 +91,14 @@ public static class GameSceneDepend
/// <para>操作提示</para>
/// </summary>
public static RichTextLabel? OperationTipLabel { get; set; }
/// <summary>
/// <para>BackpackUiContainer</para>
/// <para>背包Ui容器</para>
/// <para>DynamicUiGroup</para>
/// <para>动态生成的Ui组</para>
/// </summary>
/// <remarks>
///<para>The knapsack Ui container houses the container of the knapsack ui node. When a user uses a backpack, the node to which his backpack is attached is displayed from within the backpack ui container.</para>
///<para>背包Ui容器内存放的是背包ui节点的容器。当用户使用背包时会从背包ui容器内将其背包对于的节点展示出来。</para>
///<para>Dynamically generated Ui objects will be placed under this node</para>
///<para>动态生成的Ui对象将放置在此节点下</para>
/// </remarks>
public static Control? BackpackUiContainer { get; set; }
/// <summary>
/// <para>Hide the knapsack node in the knapsack Ui if the knapsack UI is displayed</para>
/// <para>如果背包Ui处于显示状态那么隐藏背包UI内的背包节点</para>
/// </summary>
public static void HideBackpackUiContainerIfVisible()
{
if (BackpackUiContainer == null)
{
return;
}
if (!BackpackUiContainer.Visible)
{
return;
}
NodeUtils.ForEachNode<PacksackUi>(BackpackUiContainer, node =>
{
//If the child node is not visible, the traversal continues.
//如果子节点不可见,则继续遍历。
if (!node.Visible)
return false;
//Until you find a visible node, hide it, and return true, ending the loop.
//直到找到可见的节点隐藏该节点然后返回true结束遍历。
node.Hide();
return true;
});
}
public static UiGroup? DynamicUiGroup { get; set; }
}

View File

@ -163,9 +163,9 @@ public partial class CharacterTemplate : CharacterBody2D
//The initial health of the character after creation
//角色创建后的初始血量
[Export] public int InitialHp;
[Export] private int _initialHp;
[Export] public int MaxHp;
[Export] protected int MaxHp;
/// <summary>
/// <para>The camp ID of the role</para>
@ -189,6 +189,16 @@ public partial class CharacterTemplate : CharacterBody2D
public Node[] PickingRangeBodies => PickingRangeBodiesList?.ToArray() ?? [];
/// <summary>
/// <para>Full Hp Revive</para>
/// <para>满血复活</para>
/// </summary>
public void FullHpRevive()
{
Revive(MaxHp);
}
/// <summary>
/// <para>Resurrected character</para>
/// <para>复活角色</para>
@ -266,19 +276,17 @@ public partial class CharacterTemplate : CharacterBody2D
if (MaxHp <= 0)
{
//If Max blood volume is 0 or less, set Max blood volume to 10
//若最大血量为0或小于0则将最大血量设置为10
MaxHp = Config.DefaultMaxHp;
}
if (InitialHp <= 0 || InitialHp > MaxHp)
if (_initialHp <= 0 || _initialHp > MaxHp)
{
//If the initial health is less than or equal to 0 or greater than the maximum health, then set it to the maximum health
//如果初始血量小于等于0或者大于最大血量那么将其设置为最大血量
InitialHp = MaxHp;
_initialHp = MaxHp;
}
CurrentHp = InitialHp;
CurrentHp = _initialHp;
//The health bar of a creature may be null.
//生物的健康条可能为null。
_healthBar = GetNodeOrNull<HealthBar>("HealthBar");
@ -322,8 +330,6 @@ public partial class CharacterTemplate : CharacterBody2D
}
public override void _MouseEnter()
{
if (GameSceneDepend.Player != null)
@ -620,8 +626,9 @@ public partial class CharacterTemplate : CharacterBody2D
{
if (_additionalForce != Vector2.Zero)
{
throw new InvalidOperationException("AddForce called more than once");
return;
}
_additionalForce = force;
}

View File

@ -89,7 +89,7 @@ public partial class Player : CharacterTemplate
private void SelectedItemSlotChangeEvent(SelectedItemSlotChangeEvent selectedItemSlotChangeEvent)
{
var item = selectedItemSlotChangeEvent.NewItemSlotNode?.GetItem();
GameSceneDepend.HideBackpackUiContainerIfVisible();
GameSceneDepend.DynamicUiGroup?.HideAllControl();
if (item is Node2D node2D)
{
CurrentItem = node2D;
@ -230,6 +230,8 @@ public partial class Player : CharacterTemplate
UseItem(GetGlobalMousePosition());
}
//Pick up an item
//捡起物品
if (Input.IsActionJustPressed("pick_up"))
@ -303,7 +305,7 @@ public partial class Player : CharacterTemplate
}
ThrowItem(ItemContainer.GetSelectIndex(), 1, GetThrowVelocity());
GameSceneDepend.HideBackpackUiContainerIfVisible();
GameSceneDepend.DynamicUiGroup?.HideAllControl();
CurrentItem = null;
}
}
@ -405,7 +407,7 @@ public partial class Player : CharacterTemplate
{
Hide();
ProcessMode = ProcessModeEnum.Disabled;
if (EventManager.GameOverEvent == null)
if (EventBus.GameOverEvent == null)
{
return;
}
@ -416,7 +418,7 @@ public partial class Player : CharacterTemplate
gameOverEvent.DeathInfo = await DeathInfoGenerator.GenerateDeathInfo(this, damageTemplate.Attacker);
}
EventManager.GameOverEvent.Invoke(gameOverEvent);
EventBus.GameOverEvent.Invoke(gameOverEvent);
}
protected override void EnterThePickingRangeBody(Node node)

View File

@ -14,31 +14,37 @@ public static class ContributorDataManager
private static readonly ContributorData[] ContributorArray =
[
new ContributorData
new()
{
Name = "Cold-Mint",
Url = "https://github.com/Cold-Mint",
ContributorTypes = [ContributorType.Coder],
},
new ContributorData
new()
{
Name = "霧雨烨",
Url = "https://github.com/Web13234",
ContributorTypes = [ContributorType.Coder]
},
new ContributorData
new()
{
Name = "[HYPERLINK BLOCKED]",
Url = "https://www.pixiv.net/users/74412798",
ContributorTypes = [ContributorType.Artist],
ToolTip = "贡献死灵法杖和背包的贴图。"
},
new ContributorData
new()
{
Name = "\u2605如爱生",
Url = "https://space.bilibili.com/425243934",
ContributorTypes = [ContributorType.Artist],
ToolTip = "贡献了一些枪械贴图。"
},
new()
{
Name = "Ride-A-Pig",
Url = "https://github.com/Ride-A-Pig",
ContributorTypes = [ContributorType.Coder],
}
];

View File

@ -0,0 +1,65 @@
using ColdMint.scripts.damage;
using Godot;
namespace ColdMint.scripts.furniture;
/// <summary>
/// <para>FurnitureTemplate</para>
/// <para>家具模板</para>
/// </summary>
public partial class Furniture : RigidBody2D
{
[Export] private int _initialDurability;
[Export] private int _maxDurability;
/// <summary>
/// <para></para>
/// <para>家具的耐久度</para>
/// </summary>
private int _durability;
public override void _Ready()
{
if (_maxDurability <= 0)
{
_maxDurability = Config.DefaultMaxDurability;
}
if (_initialDurability <= 0 || _initialDurability > _maxDurability)
{
_initialDurability = _maxDurability;
}
_durability = _initialDurability;
SetCollisionMaskValue(Config.LayerNumber.Wall, true);
SetCollisionMaskValue(Config.LayerNumber.Platform, true);
SetCollisionMaskValue(Config.LayerNumber.Floor, true);
}
public override void _PhysicsProcess(double delta)
{
if (Input.IsActionJustReleased("push"))
{
SetCollisionMaskValue(Config.LayerNumber.Player, false);
}
if (Input.IsActionJustPressed("push"))
{
SetCollisionMaskValue(Config.LayerNumber.Player, true);
}
}
/// <summary>
/// <para>This method is called when furniture is damaged</para>
/// <para>当家具损害时调用此方法</para>
/// </summary>
/// <param name="damageTemplate"></param>
/// <returns>
///<para>Return whether the damage completely destroyed the furniture</para>
///<para>返回本次伤害是否彻底破坏了家具</para>
/// </returns>
public bool Damage(DamageTemplate damageTemplate)
{
return false;
}
}

View File

@ -0,0 +1,47 @@
using Godot;
namespace ColdMint.scripts.furniture;
/// <summary>
/// <para>GUIFurnitureTemplate</para>
/// <para>带有图形用户页面的家居模板</para>
/// </summary>
public partial class GuiFurniture : Furniture
{
/// <summary>
/// <para>Operating range of furniture</para>
/// <para>家具的操作范围</para>
/// </summary>
/// <remarks>
///<para>For furniture with graphical user pages, the player must enter the action range and press the shortcut key to display the UI page.</para>
///<para>对于带有图形用户页面的家具来说玩家必须进入操作范围内按下快捷键才能显示UI页面。</para>
/// </remarks>
private Area2D? _operateArea2D;
public override void _Ready()
{
base._Ready();
_operateArea2D = GetNode<Area2D>("OperateArea2D");
_operateArea2D.BodyEntered += OnBodyEntered;
_operateArea2D.BodyExited += OnBodyExited;
}
private void OnBodyEntered(Node node)
{
}
private void OnBodyExited(Node2D node2D)
{
}
public override void _ExitTree()
{
if (_operateArea2D != null)
{
_operateArea2D.BodyEntered -= OnBodyEntered;
_operateArea2D.BodyExited -= OnBodyExited;
}
}
}

View File

@ -11,10 +11,9 @@ namespace ColdMint.scripts.inventory;
/// </summary>
public partial class Packsack : PickAbleTemplate
{
private PackedScene? _packedScene;
private PacksackUi? _packsackUi;
private const string Path = "res://prefab/ui/packsackUI.tscn";
[Export] public int NumberSlots { get; set; }
/// <summary>
/// <para>Whether to allow backpacks</para>
/// <para>是否允许放置背包</para>
@ -23,31 +22,22 @@ public partial class Packsack : PickAbleTemplate
///<para>Can a new backpack be placed in the slot of the backpack?</para>
///<para>即此背包的槽位内是否可以再放置新的背包?</para>
/// </remarks>
[Export] public bool BackpackAllowed { get; set; }
[Export]
public bool BackpackAllowed { get; set; }
public override bool CanPutInPack => false;
public override void Use(Node2D? owner, Vector2 targetGlobalPosition)
{
if (_packedScene == null)
GameSceneDepend.DynamicUiGroup?.ShowControl(Path, control =>
{
return;
}
if (_packsackUi == null)
{
_packsackUi = NodeUtils.InstantiatePackedScene<PacksackUi>(_packedScene);
if (_packsackUi != null)
if (control is PacksackUi packsackUi)
{
NodeUtils.CallDeferredAddChild(NodeUtils.FindContainerNode(_packsackUi, this), _packsackUi);
_packsackUi.Title = Name;
_packsackUi.ItemContainer = ItemContainer;
packsackUi.Title = Name;
packsackUi.ItemContainer = ItemContainer;
}
}
GameSceneDepend.BackpackUiContainer?.Show();
_packsackUi?.Show();
});
}
public IItemContainer? ItemContainer { get; private set; }
@ -71,6 +61,10 @@ public partial class Packsack : PickAbleTemplate
itemSlotNode.Hide();
}
_packedScene = GD.Load<PackedScene>("res://prefab/ui/packsackUI.tscn");
GameSceneDepend.DynamicUiGroup?.RegisterControl(Path, () =>
{
var packedScene = GD.Load<PackedScene>(Path);
return NodeUtils.InstantiatePackedScene<PacksackUi>(packedScene);
});
}
}

View File

@ -3,6 +3,7 @@ using ColdMint.scripts.inventory;
using ColdMint.scripts.map;
using ColdMint.scripts.map.LayoutParsingStrategy;
using ColdMint.scripts.map.layoutStrategy;
using ColdMint.scripts.map.miniMap;
using ColdMint.scripts.map.RoomPlacer;
using ColdMint.scripts.utils;
using Godot;
@ -30,8 +31,8 @@ public partial class GameSceneLoader : SceneLoaderTemplate
GameSceneDepend.HotBar = hotBar;
//Backpack Ui container
//背包Ui容器
var backpackUiContainer = GetNode<Control>("CanvasLayer/BackpackUIContainer");
GameSceneDepend.BackpackUiContainer = backpackUiContainer;
var backpackUiContainer = GetNode<UiGroup>("CanvasLayer/DynamicUiGroup");
GameSceneDepend.DynamicUiGroup = backpackUiContainer;
//Load operation prompt
//加载操作提示
var operationTip = GetNode<RichTextLabel>("CanvasLayer/Control/VBoxContainer/OperationTip");
@ -56,13 +57,10 @@ public partial class GameSceneLoader : SceneLoaderTemplate
//加载玩家容器
var playerContainer = GetNode<Node2D>("PlayerContainer");
GameSceneDepend.PlayerContainer = playerContainer;
//Load the room container node
//加载房间容器节点
var miniMapContainerNode = GetNode<Node2D>("CanvasLayer/Control/MapContainer/MiniMap/RoomPreviewContainer");
GameSceneDepend.MiniMapContainerNode = miniMapContainerNode;
//计算迷你地图的中点
var mapContainer = GetNode<NinePatchRect>("CanvasLayer/Control/MapContainer/MiniMap");
GameSceneDepend.MiniMapMidpointCoordinate = mapContainer.Size / 2;
//Setting up the mini map
//设置迷你地图
var miniMap = GetNode<MiniMap>("CanvasLayer/Control/MapContainer/MiniMap");
GameSceneDepend.MiniMap = miniMap;
return Task.CompletedTask;
}

View File

@ -22,7 +22,7 @@ public partial class GameOverLoaderMenuLoader : UiLoaderTemplate
_restartButton = GetNodeOrNull<Button>("CenterContainer/VBoxContainer/MarginContainer2/RestartButton");
_deathInfoLabel =
GetNode<Label>("CenterContainer/VBoxContainer/MarginContainer/CenterContainer2/DeathInfoLabel");
EventManager.GameOverEvent += OnGameOver;
EventBus.GameOverEvent += OnGameOver;
}
public override void LoadUiActions()
@ -32,7 +32,7 @@ public partial class GameOverLoaderMenuLoader : UiLoaderTemplate
_restartButton.Pressed += () =>
{
var replayEvent = new GameReplayEvent();
EventManager.GameReplayEvent?.Invoke(replayEvent);
EventBus.GameReplayEvent?.Invoke(replayEvent);
Hide();
};
}
@ -52,6 +52,6 @@ public partial class GameOverLoaderMenuLoader : UiLoaderTemplate
public override void _ExitTree()
{
base._ExitTree();
EventManager.GameOverEvent -= OnGameOver;
EventBus.GameOverEvent -= OnGameOver;
}
}

View File

@ -1,7 +1,6 @@
using System;
using System.Text;
using ColdMint.scripts.contribute;
using ColdMint.scripts.debug;
using ColdMint.scripts.utils;
using Godot;
@ -98,7 +97,6 @@ public partial class MainMenuLoader : UiLoaderTemplate
{
_levelGraphEditorButton.Pressed += () =>
{
LogCat.Log("level_graph_editor");
if (_levelGraphEditor == null)
{
return;

View File

@ -107,8 +107,7 @@ public partial class PacksackUi : UiLoaderTemplate
{
_exitButton.Pressed += () =>
{
GameSceneDepend.BackpackUiContainer?.Hide();
Hide();
GameSceneDepend.DynamicUiGroup?.HideControl(this);
};
}
}

View File

@ -23,7 +23,7 @@ public partial class AiCharacterSpawn : Marker2D
_packedScene = GD.Load<PackedScene>(ResPath);
}
EventManager.AiCharacterGenerateEvent += OnAiCharacterGenerateEvent;
EventBus.AiCharacterGenerateEvent += OnAiCharacterGenerateEvent;
}
/// <summary>
@ -55,6 +55,6 @@ public partial class AiCharacterSpawn : Marker2D
public override void _ExitTree()
{
EventManager.AiCharacterGenerateEvent -= OnAiCharacterGenerateEvent;
EventBus.AiCharacterGenerateEvent -= OnAiCharacterGenerateEvent;
}
}

View File

@ -16,7 +16,7 @@ public partial class ItemSpawn : Marker2D
{
base._Ready();
EventManager.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
EventBus.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
}
private void MapGenerationCompleteEvent(MapGenerationCompleteEvent mapGenerationCompleteEvent)
@ -38,6 +38,6 @@ public partial class ItemSpawn : Marker2D
public override void _ExitTree()
{
base._ExitTree();
EventManager.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
EventBus.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
}
}

View File

@ -7,7 +7,6 @@ using ColdMint.scripts.map.events;
using ColdMint.scripts.map.interfaces;
using ColdMint.scripts.map.LayoutParsingStrategy;
using ColdMint.scripts.map.layoutStrategy;
using ColdMint.scripts.map.preview;
using ColdMint.scripts.map.room;
using ColdMint.scripts.serialization;
using ColdMint.scripts.utils;
@ -140,7 +139,7 @@ public static class MapGenerator
}
_running = true;
EventManager.MapGenerationStartEvent?.Invoke(new MapGenerationStartEvent());
EventBus.MapGenerationStartEvent?.Invoke(new MapGenerationStartEvent());
if (_layoutStrategy == null || _roomPlacementStrategy == null || _layoutParsingStrategy == null ||
_mapRoot == null)
{
@ -149,11 +148,6 @@ public static class MapGenerator
return;
}
if (GameSceneDepend.MiniMapContainerNode != null)
{
NodeUtils.DeleteAllChild(GameSceneDepend.MiniMapContainerNode);
}
if (GameSceneDepend.AiCharacterContainer != null)
{
NodeUtils.DeleteAllChild(GameSceneDepend.AiCharacterContainer);
@ -288,7 +282,17 @@ public static class MapGenerator
continue;
}
await PlaceRoomAndAddRecord(roomNodeData.Id, roomPlacementData, roomDictionary);
if (await PlaceRoomAndAddRecord(roomNodeData.Id, roomPlacementData, roomDictionary))
{
MarkRoomSlot(roomPlacementData);
}
}
//Place barriers
//放置屏障
foreach (var roomDictionaryValue in roomDictionary.Values)
{
PlaceBarrier(roomDictionaryValue);
}
//All rooms have been placed.
@ -299,14 +303,90 @@ public static class MapGenerator
//调用地图生成完成事件
var eventObj = new MapGenerationCompleteEvent
{
RandomNumberGenerator = randomNumberGenerator
RandomNumberGenerator = randomNumberGenerator,
RoomDictionary = roomDictionary
};
EventManager.MapGenerationCompleteEvent?.Invoke(eventObj);
EventBus.MapGenerationCompleteEvent?.Invoke(eventObj);
var aiCharacterGenerateEvent = new AiCharacterGenerateEvent
{
Tag = AiCharacterGenerateEvent.TagMapGenerationComplete
};
EventManager.AiCharacterGenerateEvent?.Invoke(aiCharacterGenerateEvent);
EventBus.AiCharacterGenerateEvent?.Invoke(aiCharacterGenerateEvent);
}
/// <summary>
/// <para>Place barriers</para>
/// <para>放置屏障</para>
/// </summary>
/// <param name="room"></param>
/// <returns></returns>
private static void PlaceBarrier(Room? room)
{
if (room == null)
{
return;
}
var ground = room.GetTileMapLayer(Config.TileMapLayerName.Ground);
var barrier = room.GetTileMapLayer(Config.TileMapLayerName.Barrier);
if (ground == null || barrier == null)
{
return;
}
var roomSlots = room.RoomSlots;
if (roomSlots == null || roomSlots.Length == 0)
{
return;
}
foreach (var roomSlot in roomSlots)
{
if (roomSlot == null)
{
continue;
}
if (roomSlot.Matched)
{
continue;
}
//Place the corresponding coordinate tiles of the barrier layer on the ground level.
//将屏障层的对应坐标瓦片放到地面层。
CoordinateUtils.ForEachCell(roomSlot.StartPosition, roomSlot.EndPosition,
i =>
{
var cellSourceId = barrier.GetCellSourceId(i);
if (cellSourceId == -1)
{
return;
}
ground.SetCell(i, cellSourceId, barrier.GetCellAtlasCoords(i), barrier.GetCellAlternativeTile(i));
});
}
barrier.QueueFree();
}
/// <summary>
/// <para>Mark the room slot as matched</para>
/// <para>将房间槽标记为已匹配</para>
/// </summary>
/// <param name="roomPlacementData"></param>
private static void MarkRoomSlot(RoomPlacementData roomPlacementData)
{
if (roomPlacementData.ParentRoomSlot != null)
{
roomPlacementData.ParentRoomSlot.Matched = true;
}
if (roomPlacementData.NewRoomSlot != null)
{
roomPlacementData.NewRoomSlot.Matched = true;
}
}
/// <summary>
@ -341,26 +421,6 @@ public static class MapGenerator
return false;
}
//Create a room preview image.
//创建房间预览图。
var image = RoomPreview.CreateImage(roomPlacementData.NewRoom.GetTileMapLayer(Config.TileMapLayerName.Ground));
if (GameSceneDepend.MiniMapContainerNode == null || roomPlacementData.Position == null ||
image == null)
{
return false;
}
var sprite = new Sprite2D();
sprite.Scale = new Vector2(5, 5);
sprite.Texture = image;
//TODOCalculate the coordinates of the room preview view.
//TODO计算房间预览图的坐标。
sprite.Position = GameSceneDepend.MiniMapMidpointCoordinate +
roomPlacementData.Position.Value / Config.CellSize;
NodeUtils.CallDeferredAddChild(GameSceneDepend.MiniMapContainerNode, sprite);
//Rooms are added to the dictionary only after the preview is created.
//创建预览图后才将房间添加到字典。
dictionary.Add(roomNodeDataId, roomPlacementData.NewRoom);
LogCat.LogWithFormat("room_placement_information", LogCat.LogLabel.Default, LogCat.UploadFormat, roomNodeDataId,
roomPlacementData.Position.ToString());

View File

@ -19,15 +19,15 @@ public partial class PlayerSpawn : Marker2D
{
base._Ready();
_playerPackedScene = GD.Load<PackedScene>("res://prefab/entitys/Character.tscn");
EventManager.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
EventManager.GameReplayEvent += GameReplayEvent;
EventBus.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
EventBus.GameReplayEvent += GameReplayEvent;
}
private void GameReplayEvent(GameReplayEvent gameReplayEvent)
{
if (GameSceneDepend.Player != null)
{
GameSceneDepend.Player.Revive(GameSceneDepend.Player.MaxHp);
GameSceneDepend.Player.FullHpRevive();
GameSceneDepend.Player.GlobalPosition = GlobalPosition;
return;
}
@ -92,7 +92,7 @@ public partial class PlayerSpawn : Marker2D
public override void _ExitTree()
{
base._ExitTree();
EventManager.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
EventManager.GameReplayEvent -= GameReplayEvent;
EventBus.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
EventBus.GameReplayEvent -= GameReplayEvent;
}
}

View File

@ -1,4 +1,6 @@

using System.Collections.Generic;
using ColdMint.scripts.map.room;
using Godot;
namespace ColdMint.scripts.map.events;
@ -16,4 +18,10 @@ public class MapGenerationCompleteEvent
// ReSharper disable UnusedAutoPropertyAccessor.Global
public RandomNumberGenerator? RandomNumberGenerator { get; set; }
// ReSharper restore UnusedAutoPropertyAccessor.Global
/// <summary>
/// <para>All placed rooms</para>
/// <para>所有已放置的房间</para>
/// </summary>
public Dictionary<string, Room>? RoomDictionary { get; set; }
}

View File

@ -1,18 +0,0 @@
using ColdMint.scripts.character;
namespace ColdMint.scripts.map.events;
/// <summary>
/// <para>Player instance change event</para>
/// <para>玩家实例改变事件</para>
/// </summary>
public class PlayerInstanceChangeEvent
{
/// <summary>
/// <para>New player instance</para>
/// <para>新的玩家实例</para>
/// </summary>
// ReSharper disable UnusedAutoPropertyAccessor.Global
public Player? PlayerInstance { get; set; }
// ReSharper restore UnusedAutoPropertyAccessor.Global
}

View File

@ -0,0 +1,179 @@
using System.Collections.Generic;
using ColdMint.scripts.debug;
using ColdMint.scripts.map.dateBean;
using ColdMint.scripts.map.events;
using ColdMint.scripts.map.preview;
using ColdMint.scripts.map.room;
using ColdMint.scripts.utils;
using Godot;
namespace ColdMint.scripts.map.miniMap;
/// <summary>
/// <para>Mini Map</para>
/// <para>迷你地图</para>
/// </summary>
public partial class MiniMap : NinePatchRect
{
private Node2D? _roomPreviewContainer;
/// <summary>
/// <para>The midpoint coordinates of the mini map</para>
/// <para>迷你地图的中点坐标</para>
/// </summary>
private Vector2 _miniMapMidpointCoordinate;
/// <summary>
/// <para>Mapping of rooms and room preview images</para>
/// <para>房间和房间预览图的映射</para>
/// </summary>
private readonly Dictionary<Room, TextureRect> _roomToRoomPreviews = [];
/// <summary>
/// <para>The master node of the map</para>
/// <para>地图的主人节点</para>
/// </summary>
public Node2D? OwnerNode { get; set; }
public override void _Ready()
{
_roomPreviewContainer = GetNode<Node2D>("RoomPreviewContainer");
_miniMapMidpointCoordinate = Size / 2;
EventBus.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
EventBus.MapGenerationStartEvent += MapGenerationStartEvent;
}
/// <summary>
/// <para>Clean up all room preview images in the mini map</para>
/// <para>清理迷你地图内的所有房间预览图</para>
/// </summary>
private void Clear()
{
_roomToRoomPreviews.Clear();
if (_roomPreviewContainer != null)
{
NodeUtils.DeleteAllChild(_roomPreviewContainer);
}
}
private void MapGenerationStartEvent(MapGenerationStartEvent mapGenerationStartEvent)
{
Clear();
}
/// <summary>
/// <para>Display room preview image</para>
/// <para>显示房间预览图</para>
/// </summary>
/// <param name="room"></param>
public void ShowRoomPreview(Room room)
{
if (_roomToRoomPreviews.TryGetValue(room, out var roomPreview))
{
roomPreview.Show();
}
}
/// <summary>
/// <para>After the map generator completes placing the room</para>
/// <para>地图生成器放置房间完成后</para>
/// </summary>
/// <param name="mapGenerationCompleteEvent"></param>
private void MapGenerationCompleteEvent(MapGenerationCompleteEvent mapGenerationCompleteEvent)
{
if (mapGenerationCompleteEvent.RoomDictionary == null)
{
return;
}
foreach (var dictionaryKey in mapGenerationCompleteEvent.RoomDictionary.Keys)
{
var roomDictionaryValue = mapGenerationCompleteEvent.RoomDictionary[dictionaryKey];
var tileMapLayer = roomDictionaryValue.GetTileMapLayer(Config.TileMapLayerName.Ground);
var textureRect = CreateRoomPreview(tileMapLayer,
CalculateRelativePositionOnTheMinimap(roomDictionaryValue));
if (textureRect == null)
{
LogCat.LogErrorWithFormat("failed_to_create_room_preview", LogCat.LogLabel.Default, LogCat.UploadFormat,
dictionaryKey);
}
else
{
_roomToRoomPreviews[roomDictionaryValue] = textureRect;
}
}
}
/// <summary>
/// <para>CalculateRelativePositionOnTheMinimap</para>
/// <para>计算在迷你地图上的相对位置</para>
/// </summary>
/// <returns>
///<para>Returns the position relative to the point in the minimap container</para>
///<para>返回相对对于迷你地图容器中点的位置</para>
/// </returns>
private Vector2? CalculateRelativePositionOnTheMinimap(Room room)
{
if (room.RootNode == null)
{
return null;
}
return room.RootNode.Position / Config.CellSize * Config.RoomPreviewScale;
}
/// <summary>
/// <para>Create a room preview image.</para>
/// <para>创建房间预览图</para>
/// </summary>
/// <param name="groundTileMapLayer">
///<para>Layers that need to be drawn onto a minimap</para>
///<para>需要绘制到迷你地图上的图层</para>
/// </param>
/// <param name="position">
///<para>Relative to the position of the point in the minimap container</para>
///<para>相对于迷你地图容器中点的位置</para>
/// </param>
/// <returns></returns>
private TextureRect? CreateRoomPreview(TileMapLayer? groundTileMapLayer, Vector2? position)
{
if (_roomPreviewContainer == null || position == null)
{
return null;
}
var image = RoomPreview.CreateImage(groundTileMapLayer);
if (image == null)
{
return null;
}
var textureRect = new TextureRect();
textureRect.Scale = new Vector2(Config.RoomPreviewScale, Config.RoomPreviewScale);
textureRect.Texture = image;
textureRect.Position = _miniMapMidpointCoordinate + position.Value;
textureRect.Hide();
NodeUtils.CallDeferredAddChild(_roomPreviewContainer, textureRect);
return textureRect;
}
public override void _Process(double delta)
{
if (_roomPreviewContainer == null)
{
return;
}
if (OwnerNode != null)
{
_roomPreviewContainer.Position = -OwnerNode.GlobalPosition / Config.CellSize * Config.RoomPreviewScale;
}
}
public override void _ExitTree()
{
EventBus.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
EventBus.MapGenerationStartEvent -= MapGenerationStartEvent;
}
}

View File

@ -55,7 +55,7 @@ public static class RoomPreview
//Create an image.
//创建image。
var image = Image.CreateEmpty(width + 1, height + 1, false, Image.Format.Rgba8);
//image.Fill(Colors.Green);
image.Fill(Colors.Green);
//Fill in pixels
//填充像素点
foreach (var vector2I in cellsArray)

View File

@ -103,8 +103,10 @@ public class Room
_pointLight2D.Texture = AssetHolder.White100;
}
GameSceneDepend.MiniMap?.ShowRoomPreview(this);
ShowAllCharacterTemplate();
}else if (node is CharacterTemplate characterTemplate)
}
else if (node is CharacterTemplate characterTemplate)
{
if (_hasPlayer)
{

View File

@ -219,18 +219,6 @@ public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy
{
var index = randomNumberGenerator.Randi() % usableRoomPlacementData.Count;
var roomPlacementData = usableRoomPlacementData[(int)index];
//Be sure to mark its slot as a match when you use it.
//一定要在使用时,将其插槽标记为匹配。
if (roomPlacementData.ParentRoomSlot != null)
{
roomPlacementData.ParentRoomSlot.Matched = true;
}
if (roomPlacementData.NewRoomSlot != null)
{
roomPlacementData.NewRoomSlot.Matched = true;
}
return roomPlacementData;
}
}

View File

@ -77,7 +77,7 @@ public partial class PickAbleTemplate : RigidBody2D, IItem
public bool Picked { get; set; }
public int MaxQuantity { get; set; }
private Label? _tipLabel;
public virtual void Use(Node2D? owner, Vector2 targetGlobalPosition)
@ -91,6 +91,9 @@ public partial class PickAbleTemplate : RigidBody2D, IItem
_damageArea2D.BodyExited += OnBodyExited;
_tipLabel = GetNodeOrNull<Label>("TipLabel");
InputPickable = true;
SetCollisionMaskValue(Config.LayerNumber.Wall, true);
SetCollisionMaskValue(Config.LayerNumber.Platform, true);
SetCollisionMaskValue(Config.LayerNumber.Floor, true);
}
private void OnBodyExited(Node node)
@ -193,10 +196,12 @@ public partial class PickAbleTemplate : RigidBody2D, IItem
{
return;
}
if (_tipLabel == null)
{
return;
}
_tipLabel.Visible = true;
_tipLabel.Text = Name;
//Vertical Centering Tip
@ -213,6 +218,7 @@ public partial class PickAbleTemplate : RigidBody2D, IItem
{
return;
}
_tipLabel.Visible = false;
}
@ -236,6 +242,7 @@ public partial class PickAbleTemplate : RigidBody2D, IItem
{
return;
}
pickAbleTemplate.Id = Id;
}

View File

@ -1,4 +1,5 @@
using Godot;
using System;
using Godot;
namespace ColdMint.scripts.utils;
@ -74,4 +75,21 @@ public static class CoordinateUtils
return orientationDescribes;
}
/// <summary>
/// <para>传入矩形起点和终点,遍历瓦片地图上的每一个坐标</para>
/// </summary>
/// <param name="startPoint"></param>
/// <param name="endPosition"></param>
/// <param name="action"></param>
public static void ForEachCell(Vector2I startPoint,Vector2I endPosition,Action<Vector2I> action)
{
for (var x = startPoint.X; x <= endPosition.X; x++)
{
for (var y = startPoint.Y; y <= endPosition.Y; y++)
{
action.Invoke(new Vector2I(x, y));
}
}
}
}

View File

@ -245,9 +245,9 @@ public static class NodeUtils
return GameSceneDepend.PacksackContainer;
}
if (GameSceneDepend.BackpackUiContainer != null && childNode is PacksackUi)
if (GameSceneDepend.DynamicUiGroup != null && childNode is PacksackUi)
{
return GameSceneDepend.BackpackUiContainer;
return GameSceneDepend.DynamicUiGroup;
}
return defaultParentNode;

182
scripts/utils/UiGroup.cs Normal file
View File

@ -0,0 +1,182 @@
using System;
using System.Collections.Generic;
using Godot;
namespace ColdMint.scripts.utils;
/// <summary>
/// <para>UI Group</para>
/// <para>UI组</para>
/// </summary>
public partial class UiGroup : Control
{
private readonly HashSet<Control> _visibleControls = [];
private readonly Dictionary<string, Func<Control?>> _controlFunc = new();
/// <summary>
/// <para>Holds the node that has been instantiated</para>
/// <para>持有已实例化的节点</para>
/// </summary>
private readonly Dictionary<string, Control> _instantiatedControl = new();
/// <summary>
/// <para>Registered control node</para>
/// <para>注册控制节点</para>
/// </summary>
/// <param name="key">
///<para>key</para>
///<para>控制节点的key</para>
/// </param>
/// <param name="func">
///<para>Creates a function to control the node. UiGroup delays calling this function to create the node.</para>
///<para>创建控制节点的函数UiGroup会延迟调用这个函数创建节点。</para>
/// </param>
public void RegisterControl(string key, Func<Control?> func)
{
_controlFunc.TryAdd(key, func);
}
/// <summary>
/// <para>Obtain or create a controller node</para>
/// <para>获取或者创建控制节点</para>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
private Control? GetOrCreateControl(string key)
{
if (_instantiatedControl.TryGetValue(key, out var instantiatedControl))
{
return instantiatedControl;
}
if (!_controlFunc.TryGetValue(key, out var func))
{
return null;
}
var control = func.Invoke();
if (control == null)
{
return null;
}
control.Hide();
control.TreeExited += () => { OnTreeExited(key, control); };
NodeUtils.CallDeferredAddChild(this, control);
_instantiatedControl.Add(key, control);
return control;
}
/// <summary>
/// <para>Hide all nodes</para>
/// <para>隐藏全部节点</para>
/// </summary>
public void HideAllControl()
{
if (_visibleControls.Count == 0)
{
return;
}
foreach (var visibleControl in _visibleControls)
{
visibleControl.Hide();
}
_visibleControls.Clear();
Hide();
}
/// <summary>
/// <para>Hide a node</para>
/// <para>隐藏某个节点</para>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool HideControl(string key)
{
if (!_instantiatedControl.TryGetValue(key, out var control))
{
return false;
}
return HideControl(control);
}
/// <summary>
/// <para>Hide a node</para>
/// <para>隐藏某个节点</para>
/// </summary>
/// <param name="control"></param>
/// <returns></returns>
public bool HideControl(Control control)
{
if (!control.IsVisible())
{
return false;
}
control.Hide();
_visibleControls.Remove(control);
ChangeSelfVisibility();
return true;
}
/// <summary>
/// <para>Show node</para>
/// <para>显示某个节点</para>
/// </summary>
/// <param name="key"></param>
/// <param name="beforeDisplayControl">
///<para>A callback function before the display node where you can generate rendered page content. For example, set the title</para>
///<para>在显示节点之前的回调函数,您可以在此函数内生成渲染页面内容。例如:设置标题</para>
/// </param>
/// <returns></returns>
public bool ShowControl(string key, Action<Control>? beforeDisplayControl = null)
{
var control = GetOrCreateControl(key);
if (control == null)
{
return false;
}
if (control.IsVisible())
{
return false;
}
if (beforeDisplayControl != null)
{
beforeDisplayControl.Invoke(control);
}
control.Show();
_visibleControls.Add(control);
ChangeSelfVisibility();
return true;
}
/// <summary>
/// <para>ChangeSelfVisibility</para>
/// <para>改变自身的可见度</para>
/// </summary>
private void ChangeSelfVisibility()
{
if (_visibleControls.Count == 0)
{
Hide();
}
else
{
Show();
}
}
private void OnTreeExited(string key, Control control)
{
//The Hide method is not called when a node exits from the tree, so remove the node here to prevent empty references.
//当节点从节点树内退出时并不会调用Hide方法所以在这里移除节点防止产生空引用。
_visibleControls.Remove(control);
_instantiatedControl.Remove(key);
}
}

View File

@ -93,8 +93,7 @@ public abstract partial class WeaponTemplate : PickAbleTemplate
//我们在每次开火之前,检查武器的后坐力。
if (_recoilStrength != 0)
{
var force = -characterTemplate.GlobalPosition.DirectionTo(enemyGlobalPosition) * _recoilStrength * Config.CellSize;
characterTemplate.AddForce(force);
characterTemplate.AddForce(enemyGlobalPosition.DirectionTo(characterTemplate.GlobalPosition) * _recoilStrength * Config.CellSize);
}
}

BIN
sprites/ui/Null.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://qowlv0viyqbb"
path="res://.godot/imported/Null.png-df7e65aefa4cf6fc02334dbb7c788923.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://sprites/ui/Null.png"
dest_files=["res://.godot/imported/Null.png-df7e65aefa4cf6fc02334dbb7c788923.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

BIN
sprites/ui/mark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cfpcm0hkmpu38"
path="res://.godot/imported/mark.png-81a29d16cd3553688c08d78ed11d42ca.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://sprites/ui/mark.png"
dest_files=["res://.godot/imported/mark.png-81a29d16cd3553688c08d78ed11d42ca.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