From e84940b8fe8a6da063efffdae3b3f5494564e482 Mon Sep 17 00:00:00 2001 From: vladislove Date: Fri, 2 Oct 2026 16:19:34 +0300 Subject: [PATCH] =?UTF-8?q?-=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83=20=D0=BD=D0=B0?= =?UTF-8?q?=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D1=81=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D0=BE=D0=B9=20=D0=BA=D0=BE=D0=BC=D0=BD=D0=B0?= =?UTF-8?q?=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scripts/LevelGenerating/LevelManager.cs | 2 +- .../_Project/Scripts/LevelGenerating/Room.cs | 12 + .../Scripts/LevelGenerating/WallsGenerator.cs | 235 +++++++++--------- 3 files changed, 134 insertions(+), 115 deletions(-) diff --git a/Assets/_Project/Scripts/LevelGenerating/LevelManager.cs b/Assets/_Project/Scripts/LevelGenerating/LevelManager.cs index c67ef56..8e2b076 100644 --- a/Assets/_Project/Scripts/LevelGenerating/LevelManager.cs +++ b/Assets/_Project/Scripts/LevelGenerating/LevelManager.cs @@ -10,7 +10,7 @@ namespace _Project.Scripts.LevelGenerating public static List Rooms = new List(); [SerializeField] private readonly int curFloor; - public void AddRoom(ref Room room) + public void AddRoom(Room room) { Rooms.Add(room); } diff --git a/Assets/_Project/Scripts/LevelGenerating/Room.cs b/Assets/_Project/Scripts/LevelGenerating/Room.cs index 58572a0..c1d8823 100644 --- a/Assets/_Project/Scripts/LevelGenerating/Room.cs +++ b/Assets/_Project/Scripts/LevelGenerating/Room.cs @@ -35,11 +35,23 @@ namespace _Project.Scripts.LevelGenerating this.rt = rt; } + public Room(Vector2 position, int wigth, int length, RoomType rt, bool isWallable, EntranceToRoomType entrance, List exits) + { + Position = position; + Wigth = wigth; + Length = length; + this.rt = rt; + this.entrance = entrance; + this.isWallable = isWallable; + this.exits = exits; + } + public int Wigth { get; set; } public int Length { get; set; } public Vector2 Position; public RoomType rt { get; set; } public EntranceToRoomType entrance { get; set; } + public bool isWallable { get; set; } public List exits { get; set; } } diff --git a/Assets/_Project/Scripts/LevelGenerating/WallsGenerator.cs b/Assets/_Project/Scripts/LevelGenerating/WallsGenerator.cs index 4ed12c6..b81ce88 100644 --- a/Assets/_Project/Scripts/LevelGenerating/WallsGenerator.cs +++ b/Assets/_Project/Scripts/LevelGenerating/WallsGenerator.cs @@ -120,135 +120,142 @@ namespace _Project.Scripts.LevelGenerating return corridor; } - void TryPlaceRoom(Room corridor) + void TryPlaceRoom(Room prevRoom,ExitsInRoomType exitForCor) { - // Базовая защита: если коридора нет или у него нет направления выхода - if (corridor == null || corridor.exits.Count == 0) return; + if (prevRoom == null || prevRoom.exits.Count == 0) return; - ExitsInRoomType corridorDirection = corridor.exits.Last(); - - // Создаем новую комнату со случайными размерами - Room newRoom = GenerateRandomRoom(); - newRoom.rt = RoomType.Undefined; - - Vector2 roomPos = Vector2.zero; - EntranceToRoomType entrance = EntranceToRoomType.Null; - - // 1. Стыкуем вход новой комнаты с выходом из коридора - switch (corridorDirection) + switch (exitForCor) { - case ExitsInRoomType.XAxisP: // Коридор шел вправо (+X) - roomPos = new Vector2( - corridor.Position.x + corridor.Length, - corridor.Position.y + (corridor.Wigth - newRoom.Wigth) / 2f - ); - entrance = EntranceToRoomType.XAxisN; // Вход в комнату с левой стены (-X) - break; - - case ExitsInRoomType.XAxisN: // Коридор шел влево (-X) - roomPos = new Vector2( - corridor.Position.x - newRoom.Length, - corridor.Position.y + (corridor.Wigth - newRoom.Wigth) / 2f - ); - entrance = EntranceToRoomType.XAxisP; // Вход с правой стены (+X) - break; - - case ExitsInRoomType.ZAxisP: // Коридор шел вверх (+Z) - roomPos = new Vector2( - corridor.Position.x + (corridor.Length - newRoom.Length) / 2f, - corridor.Position.y + corridor.Wigth - ); - entrance = EntranceToRoomType.ZAxisN; // Вход с нижней стены (-Z) - break; - - case ExitsInRoomType.ZAxisN: // Коридор шел вниз (-Z) - roomPos = new Vector2( - corridor.Position.x + (corridor.Length - newRoom.Length) / 2f, - corridor.Position.y - newRoom.Wigth - ); - entrance = EntranceToRoomType.ZAxisP; // Вход с верхней стены (+Z) - break; - } - - // 2. Проверяем: влезает ли комната в границы и не накладывается ли на другие комнаты/коридоры - if (!IsAreaClear(roomPos, newRoom.Length, newRoom.Wigth)) - { - // Не влезла — эта ветка лабиринта затухает сама - return; - } - - // Если всё чисто, сохраняем параметры и добавляем в список - newRoom.Position = roomPos; - newRoom.entrance = entrance; - LevelManager.Rooms.Add(newRoom); - - // Визуализация новой комнаты (маркеры по углам) - Instantiate(GameObjectB, new Vector3(newRoom.Position.x, 0, newRoom.Position.y), Quaternion.identity); - Instantiate(GameObjectB, new Vector3(newRoom.Position.x + newRoom.Length, 0, newRoom.Position.y), Quaternion.identity); - Instantiate(GameObjectB, new Vector3(newRoom.Position.x + newRoom.Length, 0, newRoom.Position.y + newRoom.Wigth), Quaternion.identity); - Instantiate(GameObjectB, new Vector3(newRoom.Position.x, 0, newRoom.Position.y + newRoom.Wigth), Quaternion.identity); - - // 3. РЕКУРСИЯ: получаем 3 свободные стены (все кроме той, где вход) - List availableSides = GetThreeAvailableSides(entrance); - - // Перемешиваем стороны, чтобы ветвление шло в случайном порядке - availableSides = availableSides.OrderBy(x => Random.value).ToList(); - - foreach (var exitSide in availableSides) - { - // Шанс ветвления 65%: чтобы этаж не забивался сплошным ковром комнат, - // а оставались тупики и коридорные развилки - if (Random.value < 0.65f) + case ExitsInRoomType.XAxisP: { - // Пытаемся построить коридор в эту сторону - Room nextCorridor = CreateCorridor(newRoom.Position, newRoom.Length, newRoom.Wigth, exitSide); - - if (nextCorridor != null) + if (IsRoomCanFit(new Vector2(prevRoom.Position.x + prevRoom.Length, prevRoom.Position.y / 2), + exitForCor)) { - // Рекурсивный шаг: пытаемся пристроить комнату к концу нового коридора - TryPlaceRoom(nextCorridor); + Room newRoom = GenerateRandomRoom(); + newRoom.Position = new Vector2(); + newRoom.rt = RoomType.Undefined; + newRoom.entrance = EntranceToRoomType.XAxisP; + newRoom.exits = new List(); + if (IsRoomCanFit(new Vector2(prevRoom.Position.x + prevRoom.Length, prevRoom.Position.y / 2), + newRoom.Length, newRoom.Wigth, exitForCor)) + { + newRoom.isWallable = false; + levelManager.AddRoom(newRoom); + } } + break; } } + + + } - // Вспомогательный метод 1: возвращает 3 стены, исключая стену входа - List GetThreeAvailableSides(EntranceToRoomType entrance) + private bool IsRoomCanFit(Vector2 vector2, ExitsInRoomType exitForCor) { - List sides = new List(); - - if (entrance != EntranceToRoomType.XAxisN) sides.Add(ExitsInRoomType.XAxisN); - if (entrance != EntranceToRoomType.XAxisP) sides.Add(ExitsInRoomType.XAxisP); - if (entrance != EntranceToRoomType.ZAxisN) sides.Add(ExitsInRoomType.ZAxisN); - if (entrance != EntranceToRoomType.ZAxisP) sides.Add(ExitsInRoomType.ZAxisP); - - return sides; - } - - // Вспомогательный метод 2: проверка на границы этажа и пересечение с существующими объектами - bool IsAreaClear(Vector2 pos, int length, int wigth) - { - // Проверка границ этажа [0 .. lengthFloor] - if (pos.x < 0 || pos.y < 0 || - pos.x + length > lengthFloor || - pos.y + wigth > lengthFloor) + switch (exitForCor) { - return false; - } - - Rect newRect = new Rect(pos.x, pos.y, length, wigth); - - // Проверка наложения на все уже созданные комнаты и коридоры - foreach (var existing in LevelManager.Rooms) - { - Rect existingRect = new Rect(existing.Position.x, existing.Position.y, existing.Length, existing.Wigth); - if (newRect.Overlaps(existingRect)) + case ExitsInRoomType.XAxisP: { + if ((lengthFloor - (vector2.x + lengthWallMin) >= 0) + && (lengthFloor - (vector2.y + lengthWallMin / 2f) >= 0) + && (vector2.y - lengthWallMin/ 2f) >= 0) + { + return true; + } + return false; } - } + case ExitsInRoomType.XAxisN: + { + if ((vector2.x - lengthWallMin >= 0) + && (lengthFloor - (vector2.y + lengthWallMin / 2f) >= 0) + && (vector2.y - lengthWallMin/ 2f) >= 0) + { + return true; + } - return true; + return false; + } + case ExitsInRoomType.ZAxisP: + { + if ((lengthFloor - (vector2.y + lengthWallMin) >= 0) + && (lengthFloor - (vector2.x + lengthWallMin / 2f) >= 0) + && (vector2.x - lengthWallMin/ 2f) >= 0) + { + return true; + } + + return false; + } + case ExitsInRoomType.ZAxisN: + { + if ((vector2.y - lengthWallMin >= 0) + && (lengthFloor - (vector2.x + lengthWallMin / 2f) >= 0) + && (vector2.x - lengthWallMin/ 2f) >= 0) + { + return true; + } + + return false; + } + case ExitsInRoomType.Null: + default: + return false; + } + } + private bool IsRoomCanFit(Vector2 vector2,int lengthX,int lengthZ, ExitsInRoomType exitForCor) + { + switch (exitForCor) + { + case ExitsInRoomType.XAxisP: + { + if ((lengthFloor - (vector2.x + lengthX) >= 0) + && (lengthFloor - (vector2.y + lengthZ / 2f) >= 0) + && (vector2.y - lengthZ/2f) >= 0) + { + return true; + } + + return false; + } + case ExitsInRoomType.XAxisN: + { + if ((vector2.x - lengthX >= 0) + && (lengthFloor - (vector2.y + lengthZ / 2f) >= 0) + && (vector2.y - lengthZ/2f) >= 0) + { + return true; + } + + return false; + } + case ExitsInRoomType.ZAxisP: + { + if ((lengthFloor - (vector2.y + lengthZ) >= 0) + && (lengthFloor - (vector2.x + lengthX / 2f) >= 0) + && (vector2.x - lengthX/2f) >= 0) + { + return true; + } + + return false; + } + case ExitsInRoomType.ZAxisN: + { + if ((vector2.y - lengthZ >= 0) + && (lengthFloor - (vector2.x + lengthX / 2f) >= 0) + && (vector2.x - lengthX/2) >= 0) + { + return true; + } + + return false; + } + case ExitsInRoomType.Null: + default: + return false; + } } Room GenerateRandomRoom() { @@ -337,7 +344,7 @@ namespace _Project.Scripts.LevelGenerating Room firstCorridor = CreateCorridor(new Vector2(xR, zR), lengthStartRoom, lengthStartRoom, room.exits.First()); if (firstCorridor != null) { - TryPlaceRoom(firstCorridor); + TryPlaceRoom(room,room.exits.First()); } }