-добавил проверку на размер для сгенерированной комнаты
This commit is contained in:
parent
b4e619a93e
commit
e84940b8fe
@ -10,7 +10,7 @@ namespace _Project.Scripts.LevelGenerating
|
||||
public static List<Room> Rooms = new List<Room>();
|
||||
[SerializeField] private readonly int curFloor;
|
||||
|
||||
public void AddRoom(ref Room room)
|
||||
public void AddRoom(Room room)
|
||||
{
|
||||
Rooms.Add(room);
|
||||
}
|
||||
|
||||
@ -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<ExitsInRoomType> 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<ExitsInRoomType> exits { get; set; }
|
||||
|
||||
}
|
||||
|
||||
@ -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<ExitsInRoomType> 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<ExitsInRoomType>();
|
||||
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<ExitsInRoomType> GetThreeAvailableSides(EntranceToRoomType entrance)
|
||||
private bool IsRoomCanFit(Vector2 vector2, ExitsInRoomType exitForCor)
|
||||
{
|
||||
List<ExitsInRoomType> sides = new List<ExitsInRoomType>();
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user