From ace9ba5b65da874c9ef61b88b6ef21259b7d7308 Mon Sep 17 00:00:00 2001 From: Cold-Mint Date: Sun, 26 May 2024 00:02:00 +0800 Subject: [PATCH] =?UTF-8?q?Solve=20the=20problem=20of=20room=20overlap.=20?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E6=88=BF=E9=97=B4=E9=87=8D=E5=8F=A0=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefab/roomTemplates/dungeon/initialRoom.tscn | 4 +- prefab/roomTemplates/dungeon/utilityRoom.tscn | 4 +- scripts/loader/sceneLoader/GameSceneLoader.cs | 3 +- .../SequenceLayoutParsingStrategy.cs | 2 - scripts/map/MapGenerator.cs | 6 + .../map/interfaces/IRoomPlacementStrategy.cs | 18 +++ scripts/map/room/Room.cs | 26 ++- .../PatchworkRoomPlacementStrategy.cs | 152 ++++++++++++++++-- 8 files changed, 192 insertions(+), 23 deletions(-) diff --git a/prefab/roomTemplates/dungeon/initialRoom.tscn b/prefab/roomTemplates/dungeon/initialRoom.tscn index 8c0540a..b4d42d8 100644 --- a/prefab/roomTemplates/dungeon/initialRoom.tscn +++ b/prefab/roomTemplates/dungeon/initialRoom.tscn @@ -3,7 +3,7 @@ [ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="1_rn2om"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"] -size = Vector2(511.5, 254) +size = Vector2(508.75, 254) [sub_resource type="RectangleShape2D" id="RectangleShape2D_jxmys"] size = Vector2(18, 57.75) @@ -24,7 +24,7 @@ layer_2/tile_data = PackedInt32Array(0, 1, 3, 65536, 131073, 1, 131072, 131073, [node name="RoomArea" type="Area2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="RoomArea"] -position = Vector2(257, 129) +position = Vector2(255.625, 128) shape = SubResource("RectangleShape2D_kiih8") [node name="RoomSlotList" type="Node2D" parent="."] diff --git a/prefab/roomTemplates/dungeon/utilityRoom.tscn b/prefab/roomTemplates/dungeon/utilityRoom.tscn index 17a4c2a..4260c24 100644 --- a/prefab/roomTemplates/dungeon/utilityRoom.tscn +++ b/prefab/roomTemplates/dungeon/utilityRoom.tscn @@ -3,7 +3,7 @@ [ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="1_rn2om"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"] -size = Vector2(735.375, 512.5) +size = Vector2(681, 453) [sub_resource type="RectangleShape2D" id="RectangleShape2D_o85u0"] size = Vector2(20, 48) @@ -31,7 +31,7 @@ layer_2/tile_data = PackedInt32Array(0, 1, 3, 65536, 131073, 1, 131072, 131073, collision_mask = 0 [node name="CollisionShape2D" type="CollisionShape2D" parent="RoomArea"] -position = Vector2(369.313, 253.75) +position = Vector2(371.5, 254.5) shape = SubResource("RectangleShape2D_kiih8") [node name="RoomSlotList" type="Node2D" parent="."] diff --git a/scripts/loader/sceneLoader/GameSceneLoader.cs b/scripts/loader/sceneLoader/GameSceneLoader.cs index a7de563..5683de9 100644 --- a/scripts/loader/sceneLoader/GameSceneLoader.cs +++ b/scripts/loader/sceneLoader/GameSceneLoader.cs @@ -61,7 +61,8 @@ public partial class GameSceneLoader : SceneLoaderTemplate { //2757235769 房间边框重叠! //4175259928 房间内容重叠! - MapGenerator.Seed = "4175259928"; + //212782913 起始房间重叠! + MapGenerator.Seed = GuidUtils.GetGuid(); if (_seedLabel != null) { //If you have a seedLabel, then set the seed to it. diff --git a/scripts/map/LayoutParsingStrategy/SequenceLayoutParsingStrategy.cs b/scripts/map/LayoutParsingStrategy/SequenceLayoutParsingStrategy.cs index 51bc925..2c51fe3 100644 --- a/scripts/map/LayoutParsingStrategy/SequenceLayoutParsingStrategy.cs +++ b/scripts/map/LayoutParsingStrategy/SequenceLayoutParsingStrategy.cs @@ -1,9 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using ColdMint.scripts.debug; using ColdMint.scripts.levelGraphEditor; -using ColdMint.scripts.serialization; namespace ColdMint.scripts.map.LayoutParsingStrategy; diff --git a/scripts/map/MapGenerator.cs b/scripts/map/MapGenerator.cs index b55b410..f375907 100644 --- a/scripts/map/MapGenerator.cs +++ b/scripts/map/MapGenerator.cs @@ -97,6 +97,11 @@ public static class MapGenerator } NodeUtils.DeleteAllChild(_mapRoot); + if (!await _roomPlacementStrategy.StartGeneration(_mapRoot)) + { + return; + } + //Get the layout data //拿到布局图数据 var levelGraphEditorSaveData = await _layoutStrategy.GetLayout(); @@ -169,6 +174,7 @@ public static class MapGenerator } //All rooms have been placed. //所有房间已放置完毕。 + await _roomPlacementStrategy.GeneratedComplete(_mapRoot); } /// diff --git a/scripts/map/interfaces/IRoomPlacementStrategy.cs b/scripts/map/interfaces/IRoomPlacementStrategy.cs index 68b1881..540e05c 100644 --- a/scripts/map/interfaces/IRoomPlacementStrategy.cs +++ b/scripts/map/interfaces/IRoomPlacementStrategy.cs @@ -12,6 +12,24 @@ namespace ColdMint.scripts.map.interfaces; /// public interface IRoomPlacementStrategy { + /// + /// This method is called when the map generator starts generating the map + /// 当地图生成器开始生成地图时调用此方法 + /// + /// + /// + ///Returning false terminates the build + ///返回false则终止生成 + /// + public Task StartGeneration(Node mapRoot); + + /// + /// Call this method after the build is complete + /// 生成完成后调用此方法 + /// + /// + public Task GeneratedComplete(Node mapRoot); + /// /// Place the room in the designated location /// 在指定的位置放置房间 diff --git a/scripts/map/room/Room.cs b/scripts/map/room/Room.cs index 11c37e7..51797b4 100644 --- a/scripts/map/room/Room.cs +++ b/scripts/map/room/Room.cs @@ -20,6 +20,23 @@ public class Room private Node2D? _rootNode; private RoomSlot?[]? _roomSlots; private TileMap? _tileMap; + private Area2D? _area2D; + private CollisionShape2D? _collisionShape2D; + + /// + /// The collision shape of the room + /// 房间的碰撞形状 + /// + public CollisionShape2D? RoomCollisionShape2D + { + get => _collisionShape2D; + set => _collisionShape2D = value; + } + public Area2D? Area2D + { + get => _area2D; + set => _area2D = value; + } public PackedScene? RoomScene { @@ -50,7 +67,10 @@ public class Room _rootNode = node2D; _tileMap = node2D.GetNode("TileMap"); - _roomSlots = GetRoomSlots(_tileMap, node2D.GetNode("RoomArea"), + _area2D = node2D.GetNode("RoomArea"); + _area2D.Monitorable = true; + _collisionShape2D = _area2D.GetChild(0); + _roomSlots = GetRoomSlots(_tileMap, _area2D, node2D.GetNode("RoomSlotList")); } @@ -90,6 +110,10 @@ public class Room //Got the object in the room slot //拿到了房间槽对象 var area2D = slotList.GetChild(i); + //Prevent other areas from detecting the room slot + //禁止其他区域检测到房间槽 + area2D.Monitorable = false; + var collisionShape2D = area2D.GetChild(0); var rect2 = collisionShape2D.Shape.GetRect(); //Round the size of the impactor to the tile size For example, the impactor size 44 is converted to the tile size 44/32=1.375 rounded to 1 diff --git a/scripts/map/roomPlacer/PatchworkRoomPlacementStrategy.cs b/scripts/map/roomPlacer/PatchworkRoomPlacementStrategy.cs index 1e2d056..879d155 100644 --- a/scripts/map/roomPlacer/PatchworkRoomPlacementStrategy.cs +++ b/scripts/map/roomPlacer/PatchworkRoomPlacementStrategy.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading.Tasks; using ColdMint.scripts.debug; using ColdMint.scripts.levelGraphEditor; @@ -20,6 +21,82 @@ namespace ColdMint.scripts.map.RoomPlacer; /// public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy { + /// + /// We use a temporary area to measure whether the rooms overlap + /// 我们使用一个临时区域进行测量房间是否重叠 + /// + private Area2D? _measuringArea2D; + + private CollisionShape2D? _measuringCollisionShape2D; + + private Area2D? _selfArea2D; + + /// + /// How many rooms overlap with the new rooms that will be placed + /// 有多少个房间与将要放置的新房间重叠 + /// + private int _overlapQuantity; + + public Task StartGeneration(Node mapRoot) + { + if (_measuringArea2D == null) + { + _measuringArea2D = new Area2D(); + _measuringArea2D.Monitoring = true; + _measuringArea2D.AreaEntered += body => + { + if (_selfArea2D != null && body == _selfArea2D) + { + return; + } + + //Room overlap detected + //检测到房间重叠 + _overlapQuantity++; + }; + _measuringArea2D.AreaExited += body => + { + if (_selfArea2D != null && body == _selfArea2D) + { + return; + } + + //Rooms no longer overlap + //房间不再重叠 + _overlapQuantity--; + }; + mapRoot.AddChild(_measuringArea2D); + } + + if (_measuringCollisionShape2D == null) + { + _measuringCollisionShape2D = new CollisionShape2D(); + _measuringArea2D.AddChild(_measuringCollisionShape2D); + } + + return Task.FromResult(true); + } + + public Task GeneratedComplete(Node mapRoot) + { + if (_measuringCollisionShape2D != null) + { + _measuringCollisionShape2D?.QueueFree(); + _measuringArea2D?.RemoveChild(_measuringCollisionShape2D); + _measuringCollisionShape2D = null; + } + + if (_measuringArea2D != null) + { + _measuringArea2D?.QueueFree(); + mapRoot.RemoveChild(_measuringArea2D); + _measuringArea2D = null; + } + + return Task.CompletedTask; + } + + public Task PlaceRoom(Node mapRoot, RoomPlacementData roomPlacementData) { if (roomPlacementData.Room == null || roomPlacementData.Position == null) @@ -38,30 +115,30 @@ public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy return Task.FromResult(true); } - public Task CalculateNewRoomPlacementData(RandomNumberGenerator randomNumberGenerator, + public async Task CalculateNewRoomPlacementData(RandomNumberGenerator randomNumberGenerator, Room? parentRoomNode, RoomNodeData newRoomNodeData) { if (newRoomNodeData.RoomTemplateSet == null || newRoomNodeData.RoomTemplateSet.Length == 0) { - return Task.FromResult(null); + return null; } if (parentRoomNode == null) { - return Task.FromResult(null); + return null; } var roomResArray = RoomFactory.RoomTemplateSetToRoomRes(newRoomNodeData.RoomTemplateSet); if (roomResArray.Length == 0) { - return Task.FromResult(null); + return null; } var roomSlots = parentRoomNode.RoomSlots; if (roomSlots == null || roomSlots.Length == 0) { - return Task.FromResult(null); + return null; } //Saves all data in the room template that matches the parent room. @@ -87,8 +164,7 @@ public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy continue; } - var position = CalculatedPosition(parentRoomNode, newRoom, mainRoomSlot, newRoomSlot, false) - .Result; + var position = await CalculatedPosition(parentRoomNode, newRoom, mainRoomSlot, newRoomSlot, false); if (position == null) continue; var roomPlacementData = new RoomPlacementData { @@ -100,12 +176,12 @@ public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy if (useableRoomPlacementData.Count == 0) { - return Task.FromResult(null); + return null; } else { var index = randomNumberGenerator.Randi() % useableRoomPlacementData.Count; - return Task.FromResult(useableRoomPlacementData[(int)index]); + return useableRoomPlacementData[(int)index]; } } @@ -210,7 +286,7 @@ public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy { continue; } - + mainRoomSlot.Matched = true; newRoomSlot.Matched = true; outMainRoomSlot = mainRoomSlot; @@ -224,7 +300,32 @@ public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy return Task.FromResult(false); } - private Task CalculatedPosition(Room mainRoom, Room newRoom, RoomSlot? mainRoomSlot, + /// + /// Calculate room position + /// 计算房间位置 + /// + /// + ///Main room + ///主房间 + /// + /// + ///New room + ///新房间 + /// + /// + ///Main room slot + ///主房间插槽 + /// + /// + ///New room slot + ///新房间插槽 + /// + /// + ///Whether room slots allow overlays + ///房间插槽是否允许覆盖 + /// + /// + private async Task CalculatedPosition(Room mainRoom, Room newRoom, RoomSlot? mainRoomSlot, RoomSlot? newRoomSlot, bool roomSlotOverlap) { if (mainRoom.RootNode == null || newRoom.RootNode == null || newRoom.TileMap == null || @@ -232,7 +333,7 @@ public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy newRoom.TileMap == null || mainRoomSlot == null || newRoomSlot == null) { - return Task.FromResult(null); + return null; } //Main room slot location description @@ -245,7 +346,7 @@ public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy { //If the room slot is described as null, null is returned //若房间槽描述为null,那么返回null - return Task.FromResult(null); + return null; } var mainRoomSlotPosition = mainRoom.TileMap.MapToLocal(mainRoomSlot.StartPosition); @@ -285,6 +386,27 @@ public class PatchworkRoomPlacementStrategy : IRoomPlacementStrategy } } } - return Task.FromResult(result); + + //Do calculations overlap with other rooms? + //计算结果是否与其他房间重叠? + if (newRoom.RoomCollisionShape2D != null && _measuringArea2D != null && _measuringCollisionShape2D != null) + { + //Ignore yourself when detecting room overlap + //检测房间重叠时应忽略自身 + _selfArea2D = newRoom.Area2D; + _measuringArea2D.Position = result; + _measuringCollisionShape2D.Shape = newRoom.RoomCollisionShape2D.Shape; + //Calculate the offset of the shape. + //计算形状的偏移量。 + _measuringCollisionShape2D.Position = newRoom.RoomCollisionShape2D.Shape.GetRect().Size / 2; + await Task.Delay(TimeSpan.FromMilliseconds(50)); + if (_overlapQuantity > 0) + { + return null; + } + } + + + return result; } } \ No newline at end of file