using System.Collections.Generic; using System.ComponentModel.Design.Serialization; using System.Linq; using UnityEngine; namespace _Project.Scripts.LevelGenerating { public class WallsGenerator : MonoBehaviour { [SerializeField] private int roomCountMin; [SerializeField] private int roomCountMax; [SerializeField] private int floorsCount; [SerializeField] private int lengthWallMin; [SerializeField] private int lengthWallMax; [SerializeField] private int lengthStartRoom; [SerializeField] private int lengthFloor; [SerializeField] private int corridorLength; [SerializeField] private int corridorWigth; [SerializeField] private GameObject GameObjectA; [SerializeField] private GameObject GameObjectB; private int RoomCount; private LevelManager levelManager; void Start() { levelManager = LevelManager.Instance; CreateStartRoom(); } void GenerateRooms() { RoomCount = Random.Range(roomCountMin, roomCountMax); LevelManager.Rooms.Add(new Room(Vector2.zero,lengthStartRoom, lengthStartRoom,RoomType.Start)); } Room CreateCorridor(Vector2 posRoom, int Length, int Wigth, ExitsInRoomType exitType) { Vector2 corridorPos = Vector2.zero; int cLength = 0; int cWidth = 0; EntranceToRoomType entranceToRoomType = EntranceToRoomType.Null; List exitsInRoomType = new List(); switch (exitType) { // Выход направо (+X) case ExitsInRoomType.XAxisP: // Начинается у правой стены комнаты (posRoom.x + Length) // Центрируем коридор по высоте/оси Z: смещаем на половину разницы ширин exitsInRoomType.Add (ExitsInRoomType.XAxisP); entranceToRoomType = EntranceToRoomType.XAxisN; corridorPos = new Vector2( posRoom.x + Length, posRoom.y + (Wigth - corridorWigth) / 2f ); cLength = corridorLength; cWidth = corridorWigth; break; // Выход налево (-X) case ExitsInRoomType.XAxisN: // Начинается слева от комнаты, отступая на длину коридора exitsInRoomType .Add (ExitsInRoomType.XAxisN); entranceToRoomType = EntranceToRoomType.XAxisP; corridorPos = new Vector2( posRoom.x - corridorLength, posRoom.y + (Wigth - corridorWigth) / 2f ); cLength = corridorLength; cWidth = corridorWigth; break; // Выход вперед/вверх (+Z / в Vector2 это Y) case ExitsInRoomType.ZAxisP: entranceToRoomType = EntranceToRoomType.ZAxisN; exitsInRoomType.Add (ExitsInRoomType.ZAxisP); // Начинается у верхней стены комнаты (posRoom.y + Wigth) // Центрируем коридор по горизонтали/оси X: corridorPos = new Vector2( posRoom.x + (Length - corridorWigth) / 2f, posRoom.y + Wigth ); // По оси X коридор узкий, по оси Z — длинный: cLength = corridorWigth; cWidth = corridorLength; break; // Выход назад/вниз (-Z / в Vector2 это Y) case ExitsInRoomType.ZAxisN: entranceToRoomType = EntranceToRoomType.ZAxisP; exitsInRoomType.Add (ExitsInRoomType.ZAxisN); // Начинается ниже комнаты, отступая на длину коридора corridorPos = new Vector2( posRoom.x + (Length - corridorWigth) / 2f, posRoom.y - corridorLength ); cLength = corridorWigth; cWidth = corridorLength; break; } // Создаем коридор как отдельную комнату Room corridor = new Room(corridorPos, cLength, cWidth, RoomType.Corridor,false, EntranceToRoomType.Null,exitsInRoomType); LevelManager.Rooms.Add(corridor); // Визуализация коридора (расставляем маркеры по углам коридора для наглядности) Instantiate(GameObjectB, new Vector3(corridorPos.x, 0, corridorPos.y), Quaternion.identity); Instantiate(GameObjectB, new Vector3(corridorPos.x + cLength, 0, corridorPos.y), Quaternion.identity); Instantiate(GameObjectB, new Vector3(corridorPos.x + cLength, 0, corridorPos.y + cWidth), Quaternion.identity); Instantiate(GameObjectB, new Vector3(corridorPos.x, 0, corridorPos.y + cWidth), Quaternion.identity); return corridor; } void TryPlaceRoom(Room prevRoom,ExitsInRoomType exitForCor) { if (prevRoom == null || prevRoom.exits.Count == 0) return; switch (exitForCor) { case ExitsInRoomType.XAxisP: { if (IsRoomCanFit(new Vector2(prevRoom.Position.x + prevRoom.Length, prevRoom.Position.y / 2), exitForCor)) { 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); CreateCorridor(newRoom.Position,newRoom.Length,newRoom.Wigth,exitForCor); } else { newRoom.isWallable = true; EditRoomFoFitting(newRoom,exitForCor); levelManager.AddRoom(newRoom); } } break; } } } private void EditRoomFoFitting(Room room) { if (room.Position.x + room.Length - lengthFloor <= 0) { } } private bool IsRoomCanFit(Vector2 vector2, ExitsInRoomType exitForCor) { switch (exitForCor) { 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 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() { int a = Random.Range(lengthWallMin, lengthWallMax); int b = Random.Range(lengthWallMin, lengthWallMax); Room room = new Room(); room.Length = a; room.Wigth = b; return room; } void CreateStartRoom() { float randValue = Random.value; int xR, zR; Vector2Int posStartRoom = new Vector2Int(); Room room = new Room( lengthStartRoom, lengthStartRoom, RoomType.Start); if (randValue < 0.25f) //1 квадрант { xR = Random.Range(0,lengthFloor/2-lengthStartRoom); if (xR + lengthStartRoom <= lengthFloor / 4) { room.exits.Add(ExitsInRoomType.XAxisP); zR = Random.Range(0, lengthFloor/2-lengthStartRoom); } else { room.exits.Add(ExitsInRoomType.ZAxisP); zR = Random.Range(0, lengthFloor/4-lengthStartRoom); } } else if (randValue < 0.5f) // 2 квадрант { xR = Random.Range(lengthFloor/2, lengthFloor-lengthStartRoom);//от половины до конца if (xR + lengthStartRoom <= lengthFloor * 3/4) { room.exits.Add(ExitsInRoomType.ZAxisP); zR = Random.Range(0, lengthFloor/4-lengthStartRoom); } else { room.exits.Add(ExitsInRoomType.XAxisN); zR = Random.Range(0, lengthFloor/2-lengthStartRoom); } } else if (randValue < 0.75f) { xR = Random.Range(lengthFloor / 2, lengthFloor - lengthStartRoom); if (xR + lengthStartRoom <= lengthFloor * 3 / 4) { room.exits.Add(ExitsInRoomType.ZAxisN); zR = Random.Range(lengthFloor * 3 / 4, lengthFloor - lengthStartRoom); } else { room.exits.Add(ExitsInRoomType.XAxisN); zR = Random.Range(lengthFloor / 2, lengthFloor - lengthStartRoom); } } else { xR = Random.Range(0, lengthFloor / 2 - lengthStartRoom); if (xR + lengthStartRoom <= lengthFloor / 4) { room.exits.Add(ExitsInRoomType.XAxisP); zR = Random.Range(lengthFloor / 2, lengthFloor - lengthStartRoom); } else { room.exits.Add(ExitsInRoomType.ZAxisN); zR = Random.Range(lengthFloor * 3 / 4, lengthFloor - lengthStartRoom); } } room.entrance = EntranceToRoomType.Null; LevelManager.Rooms.Add(room); Instantiate(GameObjectA, new Vector3(0,-1,0), Quaternion.identity); Instantiate(GameObjectB, new Vector3(xR,0,zR), Quaternion.identity); Instantiate(GameObjectB, new Vector3(xR+lengthStartRoom,0,zR), Quaternion.identity); Instantiate(GameObjectB, new Vector3(xR+lengthStartRoom,0,zR+lengthStartRoom), Quaternion.identity); Instantiate(GameObjectB, new Vector3(xR,0,zR+lengthStartRoom), Quaternion.identity); CreateCorridor(new Vector2Int(xR, zR),lengthStartRoom,lengthStartRoom,room.exits.First()); Room firstCorridor = CreateCorridor(new Vector2(xR, zR), lengthStartRoom, lengthStartRoom, room.exits.First()); if (firstCorridor != null) { TryPlaceRoom(room,room.exits.First()); } } } }