есть комната лифта
This commit is contained in:
parent
47f59350c8
commit
490c534cfa
@ -13821,6 +13821,7 @@ GameObject:
|
|||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 740097205}
|
- component: {fileID: 740097205}
|
||||||
- component: {fileID: 740097204}
|
- component: {fileID: 740097204}
|
||||||
|
- component: {fileID: 740097206}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: WallsGenerator
|
m_Name: WallsGenerator
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@ -13841,14 +13842,20 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::_Project.Scripts.LevelGenerating.WallsGenerator
|
m_EditorClassIdentifier: Assembly-CSharp::_Project.Scripts.LevelGenerating.WallsGenerator
|
||||||
floorsCount: 10
|
floorsCount: 10
|
||||||
lengthWallMin: 5
|
lengthWallMin: 10
|
||||||
lengthWallMax: 25
|
lengthWallMax: 25
|
||||||
lengthStartRoom: 10
|
lengthStartRoom: 10
|
||||||
|
lengthLiftRoom: 10
|
||||||
|
widthLiftRoom: 5
|
||||||
lengthFloor: 100
|
lengthFloor: 100
|
||||||
corridorLength: 5
|
corridorLength: 5
|
||||||
corridorWigth: 4
|
corridorWigth: 4
|
||||||
|
_minDepthLiftRoom: 0
|
||||||
GameObjectA: {fileID: 8066171868259172852, guid: e46748b8eb8a6074d9bb87701cebe84b, type: 3}
|
GameObjectA: {fileID: 8066171868259172852, guid: e46748b8eb8a6074d9bb87701cebe84b, type: 3}
|
||||||
GameObjectB: {fileID: 4641718306729093824, guid: 3905eab8a5f6b3049a83378b1acf1ebc, type: 3}
|
GameObjectB: {fileID: 4641718306729093824, guid: 3905eab8a5f6b3049a83378b1acf1ebc, type: 3}
|
||||||
|
maxRooms: 15
|
||||||
|
branchChance: 0.7
|
||||||
|
roomMargin: 2
|
||||||
--- !u!4 &740097205
|
--- !u!4 &740097205
|
||||||
Transform:
|
Transform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -13864,6 +13871,18 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &740097206
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 740097203}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 4998e3ff3051468998a4d4d904be1956, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::_Project.Scripts.LevelGenerating.LevelManager
|
||||||
--- !u!1001 &740364276
|
--- !u!1001 &740364276
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.Design.Serialization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Random = UnityEngine.Random;
|
using Random = UnityEngine.Random;
|
||||||
@ -9,476 +7,378 @@ namespace _Project.Scripts.LevelGenerating
|
|||||||
{
|
{
|
||||||
public class WallsGenerator : MonoBehaviour
|
public class WallsGenerator : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
|
||||||
[SerializeField] private int floorsCount;
|
[SerializeField] private int floorsCount;
|
||||||
[SerializeField] private int lengthWallMin;
|
[SerializeField] private int lengthWallMin;
|
||||||
[SerializeField] private int lengthWallMax;
|
[SerializeField] private int lengthWallMax;
|
||||||
[SerializeField] private int lengthStartRoom;
|
[SerializeField] private int lengthStartRoom;
|
||||||
|
[SerializeField] private int lengthLiftRoom;
|
||||||
|
[SerializeField] private int widthLiftRoom;
|
||||||
[SerializeField] private int lengthFloor;
|
[SerializeField] private int lengthFloor;
|
||||||
[SerializeField] private int corridorLength;
|
[SerializeField] private int corridorLength;
|
||||||
[SerializeField] private int corridorWigth;
|
[SerializeField] private int corridorWigth;
|
||||||
|
[SerializeField] private int _minDepthLiftRoom;
|
||||||
[SerializeField] private GameObject GameObjectA;
|
[SerializeField] private GameObject GameObjectA;
|
||||||
[SerializeField] private GameObject GameObjectB;
|
[SerializeField] private GameObject GameObjectB;
|
||||||
|
|
||||||
private int RoomCount;
|
[Header("Генерация")] [SerializeField] private int maxRooms = 15;
|
||||||
|
[SerializeField, Range(0f, 1f)] private float branchChance = 0.7f;
|
||||||
|
[SerializeField] private float roomMargin = 2f; // зазор между комнатами
|
||||||
|
|
||||||
|
private int _curRooms;
|
||||||
|
private readonly Dictionary<Room, int> _depth = new Dictionary<Room, int>();
|
||||||
private LevelManager levelManager;
|
private LevelManager levelManager;
|
||||||
|
|
||||||
|
private static readonly ExitsInRoomType[] AllDirs =
|
||||||
|
{
|
||||||
|
ExitsInRoomType.XAxisP, ExitsInRoomType.XAxisN,
|
||||||
|
ExitsInRoomType.ZAxisP, ExitsInRoomType.ZAxisN
|
||||||
|
};
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
levelManager = LevelManager.Instance;
|
levelManager = LevelManager.Instance;
|
||||||
GenerateFloor();
|
GenerateFloor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PlaceElevator()
|
||||||
|
{
|
||||||
|
var start = levelManager.GetRooms().First(r => r.rt == RoomType.Start);
|
||||||
|
|
||||||
|
// максимум шагов, при равенстве выбираем самую дальнюю от старта по прямой
|
||||||
|
var best = _depth
|
||||||
|
.OrderByDescending(p => p.Value)
|
||||||
|
.ThenByDescending(p => (p.Key.Position - start.Position).sqrMagnitude)
|
||||||
|
.First();
|
||||||
|
|
||||||
|
if (best.Key == start || best.Value <= _minDepthLiftRoom)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
best.Key.rt = RoomType.Lift; // добавь значение в enum RoomType
|
||||||
|
best.Key.Length = lengthLiftRoom;
|
||||||
|
best.Key.Width = widthLiftRoom;
|
||||||
|
best.Key.exits.Clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
void GenerateFloor()
|
void GenerateFloor()
|
||||||
{
|
{
|
||||||
|
LevelManager.Rooms.Clear();
|
||||||
|
_depth.Clear();// статический список мог остаться с прошлого запуска
|
||||||
|
_curRooms = 0;
|
||||||
|
|
||||||
CreateStartRoom();
|
CreateStartRoom();
|
||||||
|
|
||||||
|
if (!PlaceElevator())
|
||||||
|
{
|
||||||
|
GenerateFloor();
|
||||||
|
}
|
||||||
|
|
||||||
Instantiate(GameObjectA, new Vector3(0, -1, 0), Quaternion.identity);
|
Instantiate(GameObjectA, new Vector3(0, -1, 0), Quaternion.identity);
|
||||||
|
|
||||||
foreach (var room in levelManager.GetRooms())
|
foreach (var room in levelManager.GetRooms())
|
||||||
{
|
{
|
||||||
|
|
||||||
float x = room.Position.x;
|
float x = room.Position.x;
|
||||||
float z = room.Position.y; // В Vector2 ось Y отвечает за Z в 3D пространстве Unity
|
float z = room.Position.y; // Vector2.y -> Z в 3D
|
||||||
float length = room.Length;
|
float length = room.Length;
|
||||||
float width = room.Width;
|
float width = room.Width;
|
||||||
|
|
||||||
// 4 угла комнаты:
|
|
||||||
// 1. Нижний левый (X, Z)
|
|
||||||
Instantiate(GameObjectB, new Vector3(x, 0, z), Quaternion.identity);
|
Instantiate(GameObjectB, new Vector3(x, 0, z), Quaternion.identity);
|
||||||
// 2. Нижний правый (X + Length, Z)
|
|
||||||
Instantiate(GameObjectB, new Vector3(x + length, 0, z), Quaternion.identity);
|
Instantiate(GameObjectB, new Vector3(x + length, 0, z), Quaternion.identity);
|
||||||
// 3. Верхний правый (X + Length, Z + Width)
|
|
||||||
Instantiate(GameObjectB, new Vector3(x + length, 0, z + width), Quaternion.identity);
|
Instantiate(GameObjectB, new Vector3(x + length, 0, z + width), Quaternion.identity);
|
||||||
// 4. Верхний левый (X, Z + Width)
|
|
||||||
Instantiate(GameObjectB, new Vector3(x, 0, z + width), Quaternion.identity);
|
Instantiate(GameObjectB, new Vector3(x, 0, z + width), Quaternion.identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Room CreateCorridor(Vector2 posRoom, int Length, int Wigth, ExitsInRoomType exitType)
|
// ---------- Вспомогательные ----------
|
||||||
|
|
||||||
|
private static ExitsInRoomType Opposite(ExitsInRoomType d)
|
||||||
{
|
{
|
||||||
Vector2 corridorPos = Vector2.zero;
|
switch (d)
|
||||||
int cLength = 0;
|
{
|
||||||
int cWidth = 0;
|
case ExitsInRoomType.XAxisP: return ExitsInRoomType.XAxisN;
|
||||||
EntranceToRoomType entranceToRoomType = EntranceToRoomType.Null;
|
case ExitsInRoomType.XAxisN: return ExitsInRoomType.XAxisP;
|
||||||
List<ExitsInRoomType> exitsInRoomType = new List<ExitsInRoomType>();
|
case ExitsInRoomType.ZAxisP: return ExitsInRoomType.ZAxisN;
|
||||||
switch (exitType)
|
default: return ExitsInRoomType.ZAxisP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EntranceToRoomType ToEntrance(ExitsInRoomType d)
|
||||||
|
{
|
||||||
|
switch (d)
|
||||||
|
{
|
||||||
|
case ExitsInRoomType.XAxisP: return EntranceToRoomType.XAxisN;
|
||||||
|
case ExitsInRoomType.XAxisN: return EntranceToRoomType.XAxisP;
|
||||||
|
case ExitsInRoomType.ZAxisP: return EntranceToRoomType.ZAxisN;
|
||||||
|
default: return EntranceToRoomType.ZAxisP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Rect RoomRect(Room r) => new Rect(r.Position.x, r.Position.y, r.Length, r.Width);
|
||||||
|
|
||||||
|
// Прямоугольник коридора, ведущего из prev в направлении dir
|
||||||
|
private Rect CorridorRect(Room prev, ExitsInRoomType dir)
|
||||||
|
{
|
||||||
|
switch (dir)
|
||||||
{
|
{
|
||||||
// Выход направо (+X)
|
|
||||||
case ExitsInRoomType.XAxisP:
|
case ExitsInRoomType.XAxisP:
|
||||||
// Начинается у правой стены комнаты (posRoom.x + Length)
|
return new Rect(prev.Position.x + prev.Length,
|
||||||
// Центрируем коридор по высоте/оси Z: смещаем на половину разницы ширин
|
prev.Position.y + (prev.Width - corridorWigth) / 2f,
|
||||||
exitsInRoomType.Add (ExitsInRoomType.XAxisP);
|
corridorLength, corridorWigth);
|
||||||
entranceToRoomType = EntranceToRoomType.XAxisN;
|
|
||||||
corridorPos = new Vector2(
|
|
||||||
posRoom.x + Length,
|
|
||||||
posRoom.y + (Wigth - corridorWigth) / 2f
|
|
||||||
);
|
|
||||||
cLength = corridorLength;
|
|
||||||
cWidth = corridorWigth;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Выход налево (-X)
|
|
||||||
case ExitsInRoomType.XAxisN:
|
case ExitsInRoomType.XAxisN:
|
||||||
// Начинается слева от комнаты, отступая на длину коридора
|
return new Rect(prev.Position.x - corridorLength,
|
||||||
exitsInRoomType .Add (ExitsInRoomType.XAxisN);
|
prev.Position.y + (prev.Width - corridorWigth) / 2f,
|
||||||
entranceToRoomType = EntranceToRoomType.XAxisP;
|
corridorLength, corridorWigth);
|
||||||
corridorPos = new Vector2(
|
|
||||||
posRoom.x - corridorLength,
|
|
||||||
posRoom.y + (Wigth - corridorWigth) / 2f
|
|
||||||
);
|
|
||||||
cLength = corridorLength;
|
|
||||||
cWidth = corridorWigth;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Выход вперед/вверх (+Z / в Vector2 это Y)
|
|
||||||
case ExitsInRoomType.ZAxisP:
|
case ExitsInRoomType.ZAxisP:
|
||||||
entranceToRoomType = EntranceToRoomType.ZAxisN;
|
return new Rect(prev.Position.x + (prev.Length - corridorWigth) / 2f,
|
||||||
|
prev.Position.y + prev.Width,
|
||||||
exitsInRoomType.Add (ExitsInRoomType.ZAxisP);
|
corridorWigth, corridorLength);
|
||||||
// Начинается у верхней стены комнаты (posRoom.y + Wigth)
|
default: // ZAxisN
|
||||||
// Центрируем коридор по горизонтали/оси X:
|
return new Rect(prev.Position.x + (prev.Length - corridorWigth) / 2f,
|
||||||
corridorPos = new Vector2(
|
prev.Position.y - corridorLength,
|
||||||
posRoom.x + (Length - corridorWigth) / 2f,
|
corridorWigth, corridorLength);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Создаем коридор как отдельную комнату
|
// Центр стены новой комнаты, куда упирается коридор
|
||||||
|
private Vector2 EntryPoint(Room prev, ExitsInRoomType dir)
|
||||||
|
{
|
||||||
|
switch (dir)
|
||||||
|
{
|
||||||
|
case ExitsInRoomType.XAxisP:
|
||||||
|
return new Vector2(prev.Position.x + prev.Length + corridorLength,
|
||||||
|
prev.Position.y + prev.Width / 2f);
|
||||||
|
case ExitsInRoomType.XAxisN:
|
||||||
|
return new Vector2(prev.Position.x - corridorLength,
|
||||||
|
prev.Position.y + prev.Width / 2f);
|
||||||
|
case ExitsInRoomType.ZAxisP:
|
||||||
|
return new Vector2(prev.Position.x + prev.Length / 2f,
|
||||||
|
prev.Position.y + prev.Width + corridorLength);
|
||||||
|
default:
|
||||||
|
return new Vector2(prev.Position.x + prev.Length / 2f,
|
||||||
|
prev.Position.y - corridorLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Room corridor = new Room(corridorPos,
|
private bool IsAreaFree(Rect rect, Room ignore = null)
|
||||||
cLength, cWidth, RoomType.Corridor,false,
|
{
|
||||||
EntranceToRoomType.Null,exitsInRoomType);
|
foreach (var other in levelManager.GetRooms())
|
||||||
|
{
|
||||||
|
if (other == ignore) continue;
|
||||||
|
if (rect.Overlaps(RoomRect(other))) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Коридор ----------
|
||||||
|
|
||||||
|
Room CreateCorridor(Room prev, ExitsInRoomType dir)
|
||||||
|
{
|
||||||
|
Rect r = CorridorRect(prev, dir);
|
||||||
|
|
||||||
|
Room corridor = new Room(r.position,
|
||||||
|
Mathf.RoundToInt(r.width), Mathf.RoundToInt(r.height),
|
||||||
|
RoomType.Corridor, false,
|
||||||
|
ToEntrance(dir), new List<ExitsInRoomType> { dir });
|
||||||
|
|
||||||
LevelManager.Rooms.Add(corridor);
|
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;
|
return corridor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TryPlaceRoom(Room prevRoom,ExitsInRoomType exitForCor)
|
private bool FitRoom(Room prev, Room n, ExitsInRoomType dir, out bool shrunk)
|
||||||
{
|
{
|
||||||
if (prevRoom == null || prevRoom.exits.Count == 0) return;
|
Vector2 e = EntryPoint(prev, dir);
|
||||||
|
int origLen = n.Length, origWid = n.Width;
|
||||||
|
|
||||||
// if (IsRoomCanFit(new Vector2(prevRoom.Position.x + prevRoom.Length, prevRoom.Position.y / 2),
|
switch (dir)
|
||||||
// exitForCor))
|
{
|
||||||
// {
|
case ExitsInRoomType.XAxisP:
|
||||||
// Room newRoom = GenerateRandomRoom();
|
case ExitsInRoomType.XAxisN:
|
||||||
// newRoom.Position = new Vector2();
|
{
|
||||||
// newRoom.rt = RoomType.Undefined;
|
float maxAlong = dir == ExitsInRoomType.XAxisP ? lengthFloor - e.x : e.x;
|
||||||
// newRoom.entrance = EntranceToRoomType.XAxisP;
|
float maxCross = 2f * Mathf.Min(e.y, lengthFloor - e.y);
|
||||||
// newRoom.exits = new List<ExitsInRoomType>();
|
n.Length = Mathf.Min(n.Length, Mathf.FloorToInt(maxAlong));
|
||||||
// if (IsRoomCanFit(new Vector2(prevRoom.Position.x + prevRoom.Length, prevRoom.Position.y / 2),
|
n.Width = Mathf.Min(n.Width, Mathf.FloorToInt(maxCross));
|
||||||
// newRoom.Length, newRoom.Width, exitForCor))
|
float x = dir == ExitsInRoomType.XAxisP ? e.x : e.x - n.Length;
|
||||||
// {
|
n.Position = new Vector2(x, e.y - n.Width / 2f);
|
||||||
// newRoom.isWallable = false;
|
break;
|
||||||
// levelManager.AddRoom(newRoom);
|
}
|
||||||
// CreateCorridor(newRoom.Position, newRoom.Length, newRoom.Width, exitForCor);
|
default: // Z
|
||||||
// }
|
{
|
||||||
// else
|
float maxAlong = dir == ExitsInRoomType.ZAxisP ? lengthFloor - e.y : e.y;
|
||||||
// {
|
float maxCross = 2f * Mathf.Min(e.x, lengthFloor - e.x);
|
||||||
// newRoom.isWallable = true;
|
n.Width = Mathf.Min(n.Width, Mathf.FloorToInt(maxAlong));
|
||||||
// EditRoomFoFitting(newRoom);
|
n.Length = Mathf.Min(n.Length, Mathf.FloorToInt(maxCross));
|
||||||
// levelManager.AddRoom(newRoom);
|
float y = dir == ExitsInRoomType.ZAxisP ? e.y : e.y - n.Width;
|
||||||
// CreateCorridor(newRoom.Position, newRoom.Length, newRoom.Width, exitForCor);
|
n.Position = new Vector2(e.x - n.Length / 2f, y);
|
||||||
// }
|
break;
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shrunk = n.Length != origLen || n.Width != origWid;
|
||||||
|
return n.Length >= lengthWallMin && n.Width >= lengthWallMin;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryPlaceRoom(Room prevRoom, ExitsInRoomType dir)
|
||||||
|
{
|
||||||
|
if (prevRoom == null || _curRooms >= maxRooms) return false;
|
||||||
|
|
||||||
Room newRoom = GenerateRandomRoom();
|
Room newRoom = GenerateRandomRoom();
|
||||||
newRoom.rt = RoomType.Undefined;
|
newRoom.rt = RoomType.Undefined;
|
||||||
newRoom.exits = new List<ExitsInRoomType>();
|
newRoom.exits = new List<ExitsInRoomType>(); // заполнится по факту построенных выходов
|
||||||
|
newRoom.entrance = ToEntrance(dir);
|
||||||
|
|
||||||
Vector2 newRoomPos = Vector2.zero;
|
if (!FitRoom(prevRoom, newRoom, dir, out bool shrunk)) return false;
|
||||||
|
newRoom.isWallable = shrunk;
|
||||||
|
|
||||||
// Вычисляем позицию новой комнаты и откуда в нее входит коридор
|
// Пересечения: комната (с зазором, без prevRoom) и коридор к ней
|
||||||
switch (exitForCor)
|
Rect roomArea = RoomRect(newRoom);
|
||||||
{
|
float m = Mathf.Min(roomMargin, corridorLength);
|
||||||
// Если вышли направо, новая комната слева получает вход (-X)
|
roomArea.xMin -= m; roomArea.yMin -= m;
|
||||||
case ExitsInRoomType.XAxisP:
|
roomArea.xMax += m; roomArea.yMax += m;
|
||||||
newRoom.entrance = EntranceToRoomType.XAxisN;
|
|
||||||
newRoomPos = new Vector2(
|
|
||||||
prevRoom.Position.x + prevRoom.Length + corridorLength, // Сдвигаем на ширину пред. комнаты и коридор
|
|
||||||
prevRoom.Position.y + (prevRoom.Width / 2f) - (newRoom.Width / 2f) // Центрируем по оси Y (Z)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Если вышли налево
|
if (!IsAreaFree(roomArea, prevRoom)) return false;
|
||||||
case ExitsInRoomType.XAxisN:
|
if (!IsAreaFree(CorridorRect(prevRoom, dir))) return false;
|
||||||
newRoom.entrance = EntranceToRoomType.XAxisP;
|
|
||||||
newRoomPos = new Vector2(
|
|
||||||
prevRoom.Position.x - corridorLength - newRoom.Length, // Отступаем влево на коридор и ширину новой комнаты
|
|
||||||
prevRoom.Position.y + (prevRoom.Width / 2f) - (newRoom.Width / 2f)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Если вышли вверх (+Z/Y)
|
// Всё хорошо - фиксируем
|
||||||
case ExitsInRoomType.ZAxisP:
|
|
||||||
newRoom.entrance = EntranceToRoomType.ZAxisN;
|
|
||||||
newRoomPos = new Vector2(
|
|
||||||
prevRoom.Position.x + (prevRoom.Length / 2f) - (newRoom.Length / 2f), // Центрируем по оси X
|
|
||||||
prevRoom.Position.y + prevRoom.Width + corridorLength
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Если вышли вниз (-Z/Y)
|
|
||||||
case ExitsInRoomType.ZAxisN:
|
|
||||||
newRoom.entrance = EntranceToRoomType.ZAxisP;
|
|
||||||
newRoomPos = new Vector2(
|
|
||||||
prevRoom.Position.x + (prevRoom.Length / 2f) - (newRoom.Length / 2f),
|
|
||||||
prevRoom.Position.y - corridorLength - newRoom.Width
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Устанавливаем просчитанную позицию
|
|
||||||
newRoom.Position = newRoomPos;
|
|
||||||
|
|
||||||
// Проверяем, помещается ли комната с ее реальными размерами
|
|
||||||
if (IsRoomCanFit(newRoom.Position, newRoom.Length, newRoom.Width, exitForCor))
|
|
||||||
{
|
|
||||||
newRoom.isWallable = false;
|
|
||||||
levelManager.AddRoom(newRoom);
|
levelManager.AddRoom(newRoom);
|
||||||
CreateCorridor(newRoom.Position, newRoom.Length, newRoom.Width, exitForCor);
|
_depth[newRoom] = _depth[prevRoom] + 1;
|
||||||
|
CreateCorridor(prevRoom, dir);
|
||||||
|
_curRooms++;
|
||||||
|
if (!prevRoom.exits.Contains(dir)) prevRoom.exits.Add(dir);
|
||||||
|
|
||||||
|
// Ветвление: случайный порядок, назад не идём
|
||||||
|
foreach (var d in AllDirs.OrderBy(_ => Random.value))
|
||||||
|
{
|
||||||
|
if (d == Opposite(dir)) continue;
|
||||||
|
if (Random.value > branchChance) continue;
|
||||||
|
TryPlaceRoom(newRoom, d);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
newRoom.isWallable = true;
|
|
||||||
EditRoomFoFitting(newRoom); // Подгоняем размеры под границы карты
|
|
||||||
|
|
||||||
// Проверяем, вмещается ли хотя бы комната минимального размера после обрезки
|
|
||||||
if (newRoom.Length >= lengthWallMin && newRoom.Width >= lengthWallMin)
|
|
||||||
{
|
|
||||||
levelManager.AddRoom(newRoom);
|
|
||||||
CreateCorridor(newRoom.Position, newRoom.Length, newRoom.Width, exitForCor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Места не хватило даже для минимальной комнаты.
|
|
||||||
// Отменяем создание этой комнаты и завершаем ветку.
|
|
||||||
// При необходимости здесь можно удалить сгенерированный к ней коридор.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (exitForCor != ExitsInRoomType.XAxisN) TryPlaceRoom(newRoom, ExitsInRoomType.XAxisP);
|
|
||||||
|
|
||||||
// 2. Влево (-X): идем, только если TryPlaceRoomНЕ слеа (XAxisP)
|
|
||||||
if (exitForCor != ExitsInRoomType.XAxisP) TryPlaceRoom(newRoom, ExitsInRoomType.XAxisN);
|
|
||||||
|
|
||||||
// 3. Вверх/Вперед (+Z): идем, только TryPlaceRoomпришли НЕ верху (ZAxisN)
|
|
||||||
if (exitForCor != ExitsInRoomType.ZAxisN) TryPlaceRoom(newRoom, ExitsInRoomType.ZAxisP);
|
|
||||||
|
|
||||||
// 4. Вниз/Назад (-Z): идем, только если TryPlaceRoomишли НЕ сниу (ZAxisP)
|
|
||||||
if (exitForCor != ExitsInRoomType.ZAxisP) TryPlaceRoom(newRoom, ExitsInRoomType.ZAxisN);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void EditRoomFoFitting(Room room)
|
|
||||||
{
|
|
||||||
if (lengthFloor - room.Position.x + room.Length <= 0)
|
|
||||||
{
|
|
||||||
room.Length = lengthFloor - Convert.ToInt32(room.Position.x);
|
|
||||||
}
|
|
||||||
if (lengthFloor - room.Position.y + room.Width <= 0)
|
|
||||||
{
|
|
||||||
room.Width = lengthFloor - Convert.ToInt32(room.Position.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (room.Position.x < 0)
|
|
||||||
{
|
|
||||||
room.Position.x = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (room.Position.y < 0)
|
|
||||||
{
|
|
||||||
room.Position.y = 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 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()
|
Room GenerateRandomRoom()
|
||||||
{
|
{
|
||||||
int a = Random.Range(lengthWallMin, lengthWallMax);
|
// Range(int,int) не включает верхнюю границу, поэтому +1
|
||||||
int b = Random.Range(lengthWallMin, lengthWallMax);
|
int a = Random.Range(lengthWallMin, lengthWallMax + 1);
|
||||||
|
int b = Random.Range(lengthWallMin, lengthWallMax + 1);
|
||||||
Room room = new Room();
|
Room room = new Room();
|
||||||
room.Length = a;
|
room.Length = a;
|
||||||
room.Width = b;
|
room.Width = b;
|
||||||
return room;
|
return room;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------- Стартовая комната ----------
|
||||||
|
|
||||||
void CreateStartRoom()
|
void CreateStartRoom()
|
||||||
{
|
{
|
||||||
float randValue = Random.value;
|
float randValue = Random.value;
|
||||||
int xR, zR;
|
int xR, zR;
|
||||||
Vector2Int posStartRoom = new Vector2Int();
|
ExitsInRoomType firstDir;
|
||||||
|
|
||||||
Room room = new Room(lengthStartRoom, lengthStartRoom, RoomType.Start);
|
Room room = new Room(lengthStartRoom, lengthStartRoom, RoomType.Start);
|
||||||
|
room.exits = new List<ExitsInRoomType>();
|
||||||
|
room.entrance = EntranceToRoomType.Null;
|
||||||
|
|
||||||
if (randValue < 0.25f) // 1 квадрант
|
if (randValue < 0.25f) // 1 квадрант
|
||||||
{
|
{
|
||||||
xR = Random.Range(0, lengthFloor / 2 - lengthStartRoom);
|
xR = Random.Range(0, lengthFloor / 2 - lengthStartRoom);
|
||||||
if (xR + lengthStartRoom <= lengthFloor / 4)
|
if (xR + lengthStartRoom <= lengthFloor / 4)
|
||||||
{
|
{
|
||||||
room.exits.Add(ExitsInRoomType.XAxisP);
|
firstDir = ExitsInRoomType.XAxisP;
|
||||||
zR = Random.Range(0, lengthFloor / 2 - lengthStartRoom);
|
zR = Random.Range(0, lengthFloor / 2 - lengthStartRoom);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
room.exits.Add(ExitsInRoomType.ZAxisP);
|
firstDir = ExitsInRoomType.ZAxisP;
|
||||||
zR = Random.Range(0, lengthFloor / 4 - lengthStartRoom);
|
zR = Random.Range(0, lengthFloor / 4 - lengthStartRoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (randValue < 0.5f) // 2 квадрант
|
else if (randValue < 0.5f) // 2 квадрант
|
||||||
{
|
{
|
||||||
xR = Random.Range(lengthFloor/2, lengthFloor-lengthStartRoom);//от половины до конца
|
xR = Random.Range(lengthFloor / 2, lengthFloor - lengthStartRoom);
|
||||||
if (xR + lengthStartRoom <= lengthFloor * 3 / 4)
|
if (xR + lengthStartRoom <= lengthFloor * 3 / 4)
|
||||||
{
|
{
|
||||||
room.exits.Add(ExitsInRoomType.ZAxisP);
|
firstDir = ExitsInRoomType.ZAxisP;
|
||||||
zR = Random.Range(0, lengthFloor / 4 - lengthStartRoom);
|
zR = Random.Range(0, lengthFloor / 4 - lengthStartRoom);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
room.exits.Add(ExitsInRoomType.XAxisN);
|
firstDir = ExitsInRoomType.XAxisN;
|
||||||
zR = Random.Range(0, lengthFloor / 2 - lengthStartRoom);
|
zR = Random.Range(0, lengthFloor / 2 - lengthStartRoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (randValue < 0.75f)
|
else if (randValue < 0.75f) // 3 квадрант
|
||||||
{
|
{
|
||||||
xR = Random.Range(lengthFloor / 2, lengthFloor - lengthStartRoom);
|
xR = Random.Range(lengthFloor / 2, lengthFloor - lengthStartRoom);
|
||||||
if (xR + lengthStartRoom <= lengthFloor * 3 / 4)
|
if (xR + lengthStartRoom <= lengthFloor * 3 / 4)
|
||||||
{
|
{
|
||||||
room.exits.Add(ExitsInRoomType.ZAxisN);
|
firstDir = ExitsInRoomType.ZAxisN;
|
||||||
zR = Random.Range(lengthFloor * 3 / 4, lengthFloor - lengthStartRoom);
|
zR = Random.Range(lengthFloor * 3 / 4, lengthFloor - lengthStartRoom);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
room.exits.Add(ExitsInRoomType.XAxisN);
|
firstDir = ExitsInRoomType.XAxisN;
|
||||||
zR = Random.Range(lengthFloor / 2, lengthFloor - lengthStartRoom);
|
zR = Random.Range(lengthFloor / 2, lengthFloor - lengthStartRoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else // 4 квадрант
|
||||||
{
|
{
|
||||||
xR = Random.Range(0, lengthFloor / 2 - lengthStartRoom);
|
xR = Random.Range(0, lengthFloor / 2 - lengthStartRoom);
|
||||||
if (xR + lengthStartRoom <= lengthFloor / 4)
|
if (xR + lengthStartRoom <= lengthFloor / 4)
|
||||||
{
|
{
|
||||||
room.exits.Add(ExitsInRoomType.XAxisP);
|
firstDir = ExitsInRoomType.XAxisP;
|
||||||
zR = Random.Range(lengthFloor / 2, lengthFloor - lengthStartRoom);
|
zR = Random.Range(lengthFloor / 2, lengthFloor - lengthStartRoom);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
room.exits.Add(ExitsInRoomType.ZAxisN);
|
firstDir = ExitsInRoomType.ZAxisN;
|
||||||
zR = Random.Range(lengthFloor * 3 / 4, lengthFloor - lengthStartRoom);
|
zR = Random.Range(lengthFloor * 3 / 4, lengthFloor - lengthStartRoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
room.entrance = EntranceToRoomType.Null;
|
room.Position = new Vector2(xR, zR);
|
||||||
LevelManager.Rooms.Add(room);
|
LevelManager.Rooms.Add(room);
|
||||||
// Instantiate(GameObjectA, new Vector3(0,-1,0), Quaternion.identity);
|
_depth[room] = 0;
|
||||||
//
|
_curRooms = 1; // стартовая комната считается
|
||||||
// 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,
|
if (TryPlaceRoom(room, firstDir)) return;
|
||||||
lengthStartRoom, room.exits.First());
|
foreach (var d in AllDirs.Where(x => x != firstDir).OrderBy(_ => Random.value))
|
||||||
if (firstCorridor != null)
|
if (TryPlaceRoom(room, d)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Отладка ----------
|
||||||
|
|
||||||
|
void OnDrawGizmos()
|
||||||
{
|
{
|
||||||
TryPlaceRoom(room,room.exits.First());
|
var rooms = LevelManager.Rooms;
|
||||||
}
|
if (rooms == null) return;
|
||||||
}
|
|
||||||
|
foreach (var r in rooms)
|
||||||
|
{
|
||||||
|
switch (r.rt)
|
||||||
|
{
|
||||||
|
case RoomType.Start:
|
||||||
|
Gizmos.color = Color.green;
|
||||||
|
break;
|
||||||
|
case RoomType.Corridor:
|
||||||
|
Gizmos.color = Color.yellow;
|
||||||
|
break;
|
||||||
|
case RoomType.Lift:
|
||||||
|
Gizmos.color = Color.rebeccaPurple;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Gizmos.color = Color.cyan;
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gizmos.color = r.rt == RoomType.Start ? Color.green
|
||||||
|
// : r.rt == RoomType.Corridor ? Color.yellow : Color.cyan;
|
||||||
|
Vector3 c = new Vector3(r.Position.x + r.Length / 2f, 0, r.Position.y + r.Width / 2f);
|
||||||
|
Gizmos.DrawWireCube(c, new Vector3(r.Length, 0.1f, r.Width));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
8
Assets/_Recovery.meta
Normal file
8
Assets/_Recovery.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 84eb6de198d910900976ddcf95a673d1
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
44737
Assets/_Recovery/0.unity
Normal file
44737
Assets/_Recovery/0.unity
Normal file
File diff suppressed because it is too large
Load Diff
7
Assets/_Recovery/0.unity.meta
Normal file
7
Assets/_Recovery/0.unity.meta
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 943b8b6b2cd9053bf9f84a4a0fc57620
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Loading…
Reference in New Issue
Block a user