352 lines
14 KiB
C#
352 lines
14 KiB
C#
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> exitsInRoomType = new List<ExitsInRoomType>();
|
||
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<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;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
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());
|
||
}
|
||
}
|
||
|
||
}
|
||
} |