Map gen changes
This commit is contained in:
@@ -1,11 +1,13 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
public class MapGenManager : MonoBehaviour
|
public class MapGenManager : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
/* ------------------ INSPECTOR FIELDS ------------------ */
|
||||||
[Header("Room Prefabs")]
|
[Header("Room Prefabs")]
|
||||||
[SerializeField] private List<GameObject> mapPrefab = new List<GameObject>();
|
[SerializeField] private List<GameObject> mapPrefab = new();
|
||||||
|
|
||||||
[Header("Player")]
|
[Header("Player")]
|
||||||
[SerializeField] private GameObject Player;
|
[SerializeField] private GameObject Player;
|
||||||
@@ -21,12 +23,13 @@ public class MapGenManager : MonoBehaviour
|
|||||||
[Header("Generation Settings")]
|
[Header("Generation Settings")]
|
||||||
[SerializeField] private int RoomDistance = 3;
|
[SerializeField] private int RoomDistance = 3;
|
||||||
|
|
||||||
private Dictionary<Vector2Int, GameObject> gridToRoom = new();
|
private readonly Dictionary<Vector2Int, GameObject> gridToRoom = new();
|
||||||
|
|
||||||
private readonly Vector3 roomOriginOffset = Vector3.zero;
|
private readonly Vector3 roomOriginOffset = Vector3.zero;
|
||||||
|
|
||||||
|
|
||||||
void Start() => GenerateFromLayout();
|
void Start() => GenerateFromLayout();
|
||||||
|
|
||||||
|
|
||||||
private void GenerateFromLayout()
|
private void GenerateFromLayout()
|
||||||
{
|
{
|
||||||
if (layout == null || string.IsNullOrWhiteSpace(layout.grid))
|
if (layout == null || string.IsNullOrWhiteSpace(layout.grid))
|
||||||
@@ -37,167 +40,216 @@ public class MapGenManager : MonoBehaviour
|
|||||||
|
|
||||||
gridToRoom.Clear();
|
gridToRoom.Clear();
|
||||||
|
|
||||||
/* ---------- 0) VYTVOŘÍME SPAWN-ROOM ---------- */
|
/* ----------- Create a spawn room ----------- */
|
||||||
GameObject spawnPrefab = mapPrefab[0];
|
GameObject spawnPrefab = mapPrefab[0];
|
||||||
PrefabSize spawnSizeComp = spawnPrefab.GetComponent<PrefabSize>();
|
Vector3 cellSize = GetPrefabXZ(spawnPrefab);
|
||||||
Vector3 cellSize = spawnSizeComp != null
|
|
||||||
? new Vector3(spawnSizeComp.prefabSize.x, 0, spawnSizeComp.prefabSize.y)
|
/* ---------- Text layout to grid ---------- */
|
||||||
: new Vector3(10, 0, 10); // fallback
|
string[] lines = layout.grid
|
||||||
|
.Split('\n')
|
||||||
|
.Select(line => line.TrimEnd('\r'))
|
||||||
|
.Where(line => !string.IsNullOrWhiteSpace(line))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
|
||||||
|
Vector2 firstRoomPos = GetFirstOrLastRoom(lines);
|
||||||
|
int bottomRowIdx = (int)firstRoomPos.y;
|
||||||
|
int spawnGridX = (int)firstRoomPos.x;
|
||||||
|
|
||||||
|
/* ---------- Create spawn room properly ---------- */
|
||||||
|
Vector3 spawnPos = roomOriginOffset + new Vector3(
|
||||||
|
spawnGridX * (cellSize.x + RoomDistance), // X
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
Vector3 spawnPos = roomOriginOffset;
|
|
||||||
GameObject spawnRoom = Instantiate(spawnPrefab, spawnPos, Quaternion.identity, transform);
|
GameObject spawnRoom = Instantiate(spawnPrefab, spawnPos, Quaternion.identity, transform);
|
||||||
gridToRoom[new Vector2Int(0, 0)] = spawnRoom;
|
gridToRoom[new Vector2Int(spawnGridX, 0)] = spawnRoom;
|
||||||
|
|
||||||
// hráče necháme na spawnu
|
/* ---------- Instantiate player ---------- */
|
||||||
if (Player != null)
|
if (Player)
|
||||||
{
|
{
|
||||||
Vector3 playerPos = spawnPos + new Vector3(0, 1, 3);
|
Vector3 playerPos = spawnPos + new Vector3(0, 1, 3);
|
||||||
Instantiate(Player, playerPos, Quaternion.identity, transform);
|
Instantiate(Player, playerPos, Quaternion.identity, transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- 1) PARSOVÁNÍ LAYOUTU ---------- */
|
/* ---------- Build the rest of rooms ---------- */
|
||||||
string[] lines = layout.grid
|
|
||||||
.Split('\n')
|
|
||||||
.Select(l => l.TrimEnd('\r'))
|
|
||||||
.Where(l => !string.IsNullOrEmpty(l))
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
int rows = lines.Length;
|
BuildRooms(lines, bottomRowIdx, cellSize);
|
||||||
|
|
||||||
/* ---------- 2) SMYČKA PŘES GRID ------------- */
|
/* ---------- Open walls based on aproximity to other rooms ---------- */
|
||||||
for (int z = 0; z < rows; z++)
|
foreach (var keyValuePair in gridToRoom)
|
||||||
{
|
{
|
||||||
string line = lines[rows - 1 - z]; // dolní řádek layoutu = nejnižší Z v textu
|
Vector2Int g = keyValuePair.Key;
|
||||||
for (int x = 0; x < line.Length; x++)
|
RoomHandler rh = keyValuePair.Value.GetComponent<RoomHandler>();
|
||||||
{
|
|
||||||
char c = line[x];
|
|
||||||
if (c == '-') continue; // prázdné místo
|
|
||||||
|
|
||||||
if (!char.IsDigit(c))
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"Neznámý znak {c} v layoutu – ignorováno.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = c - '0';
|
|
||||||
if (index >= mapPrefab.Count)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"Index {index} mimo rozsah mapPrefab!");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameObject prefab = mapPrefab[index];
|
|
||||||
|
|
||||||
PrefabSize roomSize = prefab.GetComponent<PrefabSize>();
|
|
||||||
Vector3 rCell = roomSize != null
|
|
||||||
? new Vector3(roomSize.prefabSize.x, 0, roomSize.prefabSize.y)
|
|
||||||
: cellSize; // použij spawn-size jako fallback
|
|
||||||
|
|
||||||
Vector3 worldPos = roomOriginOffset + new Vector3(
|
|
||||||
x * (cellSize.x + RoomDistance),
|
|
||||||
0,
|
|
||||||
(z + 1) * (cellSize.z + RoomDistance));
|
|
||||||
|
|
||||||
GameObject room = Instantiate(prefab, worldPos, Quaternion.identity, transform);
|
|
||||||
gridToRoom[new Vector2Int(x, z + 1)] = room;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- 3) OTEVŘEME ZDI VŠEM MÍSTNOSTEM ---------- */
|
|
||||||
foreach (var kvp in gridToRoom)
|
|
||||||
{
|
|
||||||
Vector2Int g = kvp.Key;
|
|
||||||
RoomHandler rh = kvp.Value.GetComponent<RoomHandler>();
|
|
||||||
|
|
||||||
bool north = gridToRoom.ContainsKey(g + Vector2Int.left);
|
bool north = gridToRoom.ContainsKey(g + Vector2Int.left);
|
||||||
bool south = gridToRoom.ContainsKey(g + Vector2Int.right);
|
bool south = gridToRoom.ContainsKey(g + Vector2Int.right);
|
||||||
bool east = gridToRoom.ContainsKey(g + Vector2Int.up);
|
bool east = gridToRoom.ContainsKey(g + Vector2Int.up);
|
||||||
bool west = gridToRoom.ContainsKey(g + Vector2Int.down);
|
bool west = gridToRoom.ContainsKey(g + Vector2Int.down);
|
||||||
|
|
||||||
rh.SetEntrances(northOpen: north,
|
rh.SetEntrances(northOpen: north, southOpen: south, eastOpen: east, westOpen: west);
|
||||||
southOpen: south,
|
|
||||||
eastOpen: east,
|
|
||||||
westOpen: west);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------- 5) CHODBY ---------- */
|
||||||
BuildCorridors();
|
BuildCorridors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Build corridors between rooms
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
private void BuildCorridors()
|
private void BuildCorridors()
|
||||||
{
|
{
|
||||||
// velikosti přímých dílů
|
float straightZ = CorridorStraight.GetComponent<PrefabSize>().prefabSize.y;
|
||||||
float straightLengthZ = CorridorStraight.GetComponent<PrefabSize>().prefabSize.y;
|
float straightX = CorridorStraight.GetComponent<PrefabSize>().prefabSize.x;
|
||||||
float straightLengthX = CorridorStraight.GetComponent<PrefabSize>().prefabSize.x;
|
|
||||||
|
|
||||||
// Abychom každý pár řešili jen jednou, projdeme jen Right a Up souseda
|
|
||||||
Vector2Int[] stepDirs = { Vector2Int.right, Vector2Int.up };
|
Vector2Int[] stepDirs = { Vector2Int.right, Vector2Int.up };
|
||||||
|
|
||||||
foreach (var kvp in gridToRoom)
|
foreach (var kv in gridToRoom)
|
||||||
{
|
{
|
||||||
Vector2Int cell = kvp.Key;
|
Vector2Int cell = kv.Key;
|
||||||
GameObject roomA = kvp.Value;
|
GameObject roomA = kv.Value;
|
||||||
|
|
||||||
foreach (Vector2Int dir in stepDirs)
|
foreach (Vector2Int dir in stepDirs)
|
||||||
{
|
{
|
||||||
Vector2Int neighKey = cell + dir;
|
Vector2Int nKey = cell + dir;
|
||||||
if (!gridToRoom.TryGetValue(neighKey, out GameObject roomB))
|
if (!gridToRoom.TryGetValue(nKey, out GameObject roomB)) continue;
|
||||||
continue; // není soused – žádná chodba
|
|
||||||
|
|
||||||
// 1) Urči směr v prostoru
|
Vector3 axis, axisNeg;
|
||||||
Vector3 axis, axisNeg; // +směr a −směr podél stejné osy
|
float halfA, halfB;
|
||||||
float halfA, halfB; // půl šířky/hloubky pro start/end bod
|
Quaternion rot;
|
||||||
Quaternion corridorRot; // natočení pro koridor
|
|
||||||
|
|
||||||
if (dir == Vector2Int.right) // grid +X (svět +X)
|
if (dir == Vector2Int.right)
|
||||||
{
|
{
|
||||||
axis = Vector3.right;
|
axis = Vector3.right; axisNeg = Vector3.left;
|
||||||
axisNeg = Vector3.left;
|
halfA = GetPrefabXZ(roomA).x * 0.5f;
|
||||||
halfA = roomA.GetComponent<PrefabSize>().prefabSize.x * 0.5f;
|
halfB = GetPrefabXZ(roomB).x * 0.5f;
|
||||||
halfB = roomB.GetComponent<PrefabSize>().prefabSize.x * 0.5f;
|
rot = Quaternion.Euler(0, 90, 0);
|
||||||
corridorRot = Quaternion.Euler(0, 90, 0); // koridor leží po X
|
|
||||||
}
|
}
|
||||||
else // dir == Vector2Int.up → svět +Z
|
else
|
||||||
{
|
{
|
||||||
axis = Vector3.forward;
|
axis = Vector3.forward; axisNeg = Vector3.back;
|
||||||
axisNeg = Vector3.back;
|
halfA = GetPrefabXZ(roomA).z * 0.5f;
|
||||||
halfA = roomA.GetComponent<PrefabSize>().prefabSize.y * 0.5f;
|
halfB = GetPrefabXZ(roomB).z * 0.5f;
|
||||||
halfB = roomB.GetComponent<PrefabSize>().prefabSize.y * 0.5f;
|
rot = Quaternion.identity;
|
||||||
corridorRot = Quaternion.identity; // prefab míří po +Z
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) Vypočti start a end body (středy zdí)
|
Vector3 start = roomA.transform.position + axis * halfA;
|
||||||
Vector3 startPos = roomA.transform.position + axis * halfA;
|
Vector3 end = roomB.transform.position + axisNeg * halfB;
|
||||||
Vector3 endPos = roomB.transform.position + axisNeg * halfB;
|
|
||||||
|
|
||||||
// 3) Vytvoř sekvenci dílů
|
CreateStraightCorridor(start, end, axis, rot, straightZ, straightX);
|
||||||
CreateStraightCorridor(startPos, endPos, axis, corridorRot,
|
|
||||||
straightLengthZ, straightLengthX);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Vytvoří přímý koridor od startu k endu podél 'axis'.
|
|
||||||
|
/// <summary>
|
||||||
|
/// Build all rooms based on the layout grid
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lines"></param>
|
||||||
|
/// <param name="bottomRowIdx"></param>
|
||||||
|
/// <param name="cellSize"></param>
|
||||||
|
private void BuildRooms(string[] lines, int bottomRowIdx, Vector3 cellSize)
|
||||||
|
{
|
||||||
|
int rows = lines.Length;
|
||||||
|
|
||||||
|
for (int rowsIter = 0; rowsIter < rows; rowsIter++)
|
||||||
|
{
|
||||||
|
string line = lines[rowsIter];
|
||||||
|
int gridZ = bottomRowIdx - rowsIter + 1;
|
||||||
|
|
||||||
|
for (int x = 0; x < line.Length; x++)
|
||||||
|
{
|
||||||
|
char ch = line[x];
|
||||||
|
if (ch == '-') continue;
|
||||||
|
if (!char.IsDigit(ch))
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Neznámý znak '{ch}' v layoutu – ignoruji.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idx = ch - '0';
|
||||||
|
if (idx >= mapPrefab.Count)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Index {idx} mimo rozsah mapPrefab!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject prefab = mapPrefab[idx];
|
||||||
|
Vector3 worldPos = roomOriginOffset + new Vector3(
|
||||||
|
x * (cellSize.x + RoomDistance),
|
||||||
|
0,
|
||||||
|
gridZ * (cellSize.z + RoomDistance));
|
||||||
|
|
||||||
|
GameObject room = Instantiate(prefab, worldPos, Quaternion.identity, transform);
|
||||||
|
gridToRoom[new Vector2Int(x, gridZ)] = room;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the (x, y) coordinates of the room with closest aproximity to spawn or the furthest aproximity to spawn
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lines"></param>
|
||||||
|
/// <param name="last"></param>
|
||||||
|
/// <returns>Vector2(x, y) where x is the line index and y is the column index</returns>
|
||||||
|
private Vector2 GetFirstOrLastRoom(string[] lines, bool last = false)
|
||||||
|
{
|
||||||
|
int colIdx = -1;
|
||||||
|
int spawnGridX = 0;
|
||||||
|
|
||||||
|
int rows = lines.Length;
|
||||||
|
|
||||||
|
for (int rowsIter = rows - 1; rowsIter >= 0; rowsIter--)
|
||||||
|
{
|
||||||
|
string line = lines[rowsIter];
|
||||||
|
for (int c = 0; c < line.Length; c++)
|
||||||
|
{
|
||||||
|
if (char.IsDigit(line[c]))
|
||||||
|
{
|
||||||
|
colIdx = rowsIter;
|
||||||
|
spawnGridX = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (colIdx != -1) break;
|
||||||
|
}
|
||||||
|
if (colIdx == -1)
|
||||||
|
{
|
||||||
|
Debug.LogError("Layout neobsahuje žádnou číslici (místnost)!");
|
||||||
|
return Vector2.zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Vector2(spawnGridX, colIdx);
|
||||||
|
}
|
||||||
|
|
||||||
private void CreateStraightCorridor(
|
private void CreateStraightCorridor(
|
||||||
Vector3 start, Vector3 end, Vector3 axis, Quaternion rot,
|
Vector3 start, Vector3 end, Vector3 axis, Quaternion rot,
|
||||||
float stepLenZ, float stepLenX)
|
float stepLenZ, float stepLenX)
|
||||||
{
|
{
|
||||||
float fullDist = Vector3.Distance(start, end);
|
float dist = Vector3.Distance(start, end);
|
||||||
float stepLen = Mathf.Approximately(Mathf.Abs(axis.z), 1f) ? stepLenZ : stepLenX;
|
float step = Mathf.Approximately(Mathf.Abs(axis.z), 1f) ? stepLenZ : stepLenX;
|
||||||
|
int count = Mathf.Max(1, Mathf.FloorToInt(dist / step));
|
||||||
|
|
||||||
int segmentCount = Mathf.Max(1, Mathf.FloorToInt(fullDist / stepLen));
|
Vector3 segPos = start + axis * (step * 0.5f);
|
||||||
|
var door = Instantiate(DoorCorridor, segPos, rot, transform);
|
||||||
|
door.GetComponent<DoorController>()?.OpenDoor();
|
||||||
|
|
||||||
// 0) dveřní díl
|
for (int i = 1; i < count; i++)
|
||||||
Vector3 segPos = start + axis * (stepLen * 0.5f);
|
|
||||||
GameObject door = Instantiate(DoorCorridor, segPos, rot, transform);
|
|
||||||
door.GetComponent<DoorController>()?.OpenDoor(); // pokud existuje
|
|
||||||
|
|
||||||
// 1) zbytek – střídavě osvětlené / neosvětlené
|
|
||||||
for (int i = 1; i < segmentCount; i++)
|
|
||||||
{
|
{
|
||||||
GameObject prefab = (i % 2 == 0) ? CorridorStraight : CorridorStraightUnlit;
|
GameObject prefab = (i % 2 == 0) ? CorridorStraight : CorridorStraightUnlit;
|
||||||
|
segPos = start + axis * (i * step + step * 0.5f);
|
||||||
segPos = start + axis * (i * stepLen + stepLen * 0.5f);
|
|
||||||
Instantiate(prefab, segPos, rot, transform);
|
Instantiate(prefab, segPos, rot, transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the size of a prefab room
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prefab"> Choose a prefab from available ones</param>
|
||||||
|
/// <returns>Size of the prefab as Vector3</returns>
|
||||||
|
private static Vector3 GetPrefabXZ(GameObject prefab)
|
||||||
|
{
|
||||||
|
var ps = prefab.GetComponent<PrefabSize>();
|
||||||
|
return ps ? new Vector3(ps.prefabSize.x, 0, ps.prefabSize.y) : new Vector3(10, 0, 10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user