Files
3DBlobici-WorkingTitle/3D blobici/Assets/Scripts/MapGen/MapGenManager.cs

203 lines
7.7 KiB
C#
Raw Normal View History

2025-06-25 23:54:00 +02:00
using System.Collections.Generic;
2025-06-23 16:30:18 +02:00
using UnityEngine;
using System.Linq;
public class MapGenManager : MonoBehaviour
{
[Header("Room Prefabs")]
[SerializeField] private List<GameObject> mapPrefab = new List<GameObject>();
2025-06-24 16:59:41 +02:00
2025-06-23 16:30:18 +02:00
[Header("Player")]
[SerializeField] private GameObject Player;
2025-06-24 16:59:41 +02:00
2025-06-23 16:30:18 +02:00
[Header("Corridor Prefabs")]
[SerializeField] private GameObject CorridorStraight;
[SerializeField] private GameObject CorridorStraightUnlit;
[SerializeField] private GameObject DoorCorridor;
2025-06-25 23:54:00 +02:00
[Header("Layout")]
[SerializeField] private MapLayout layout;
2025-06-24 16:59:41 +02:00
2025-06-23 16:30:18 +02:00
[Header("Generation Settings")]
[SerializeField] private int RoomDistance = 3;
2025-06-23 16:30:18 +02:00
2025-06-25 23:54:00 +02:00
private Dictionary<Vector2Int, GameObject> gridToRoom = new();
2025-06-23 16:30:18 +02:00
2025-06-25 23:54:00 +02:00
private readonly Vector3 roomOriginOffset = Vector3.zero;
2025-06-23 16:30:18 +02:00
2025-06-25 23:54:00 +02:00
void Start() => GenerateFromLayout();
private void GenerateFromLayout()
2025-06-23 16:30:18 +02:00
{
2025-06-25 23:54:00 +02:00
if (layout == null || string.IsNullOrWhiteSpace(layout.grid))
{
Debug.LogError("Layout asset není přiřazený nebo je prázdný!");
return;
}
2025-06-24 16:59:41 +02:00
2025-06-25 23:54:00 +02:00
gridToRoom.Clear();
2025-06-24 16:59:41 +02:00
2025-06-25 23:54:00 +02:00
/* ---------- 0) VYTVOŘÍME SPAWN-ROOM ---------- */
GameObject spawnPrefab = mapPrefab[0];
PrefabSize spawnSizeComp = spawnPrefab.GetComponent<PrefabSize>();
Vector3 cellSize = spawnSizeComp != null
? new Vector3(spawnSizeComp.prefabSize.x, 0, spawnSizeComp.prefabSize.y)
: new Vector3(10, 0, 10); // fallback
2025-06-24 16:59:41 +02:00
2025-06-25 23:54:00 +02:00
Vector3 spawnPos = roomOriginOffset;
GameObject spawnRoom = Instantiate(spawnPrefab, spawnPos, Quaternion.identity, transform);
gridToRoom[new Vector2Int(0, 0)] = spawnRoom;
2025-06-24 16:59:41 +02:00
2025-06-25 23:54:00 +02:00
// hráče necháme na spawnu
if (Player != null)
2025-06-23 16:30:18 +02:00
{
2025-06-25 23:54:00 +02:00
Vector3 playerPos = spawnPos + new Vector3(0, 1, 3);
Instantiate(Player, playerPos, Quaternion.identity, transform);
2025-06-23 16:30:18 +02:00
}
2025-06-24 16:59:41 +02:00
2025-06-25 23:54:00 +02:00
/* ---------- 1) PARSOVÁNÍ LAYOUTU ---------- */
string[] lines = layout.grid
.Split('\n')
.Select(l => l.TrimEnd('\r'))
.Where(l => !string.IsNullOrEmpty(l))
.ToArray();
int rows = lines.Length;
2025-06-24 16:59:41 +02:00
2025-06-25 23:54:00 +02:00
/* ---------- 2) SMYČKA PŘES GRID ------------- */
for (int z = 0; z < rows; z++)
2025-06-24 16:59:41 +02:00
{
2025-06-25 23:54:00 +02:00
string line = lines[rows - 1 - z]; // dolní řádek layoutu = nejnižší Z v textu
for (int x = 0; x < line.Length; x++)
{
char c = line[x];
if (c == '-') continue; // prázdné místo
2025-06-24 16:59:41 +02:00
2025-06-25 23:54:00 +02:00
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
2025-06-24 16:59:41 +02:00
2025-06-25 23:54:00 +02:00
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;
}
}
2025-06-24 16:59:41 +02:00
2025-06-25 23:54:00 +02:00
/* ---------- 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 south = gridToRoom.ContainsKey(g + Vector2Int.right);
bool east = gridToRoom.ContainsKey(g + Vector2Int.up);
bool west = gridToRoom.ContainsKey(g + Vector2Int.down);
rh.SetEntrances(northOpen: north,
southOpen: south,
eastOpen: east,
westOpen: west);
}
BuildCorridors();
2025-06-23 16:30:18 +02:00
}
2025-06-25 23:54:00 +02:00
private void BuildCorridors()
2025-06-23 16:30:18 +02:00
{
2025-06-25 23:54:00 +02:00
// velikosti přímých dílů
float straightLengthZ = CorridorStraight.GetComponent<PrefabSize>().prefabSize.y;
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 };
2025-06-25 23:54:00 +02:00
foreach (var kvp in gridToRoom)
{
Vector2Int cell = kvp.Key;
GameObject roomA = kvp.Value;
2025-06-25 23:54:00 +02:00
foreach (Vector2Int dir in stepDirs)
{
2025-06-25 23:54:00 +02:00
Vector2Int neighKey = cell + dir;
if (!gridToRoom.TryGetValue(neighKey, out GameObject roomB))
continue; // není soused žádná chodba
// 1) Urči směr v prostoru
Vector3 axis, axisNeg; // +směr a směr podél stejné osy
float halfA, halfB; // půl šířky/hloubky pro start/end bod
Quaternion corridorRot; // natočení pro koridor
if (dir == Vector2Int.right) // grid +X (svět +X)
{
2025-06-25 23:54:00 +02:00
axis = Vector3.right;
axisNeg = Vector3.left;
halfA = roomA.GetComponent<PrefabSize>().prefabSize.x * 0.5f;
halfB = roomB.GetComponent<PrefabSize>().prefabSize.x * 0.5f;
corridorRot = Quaternion.Euler(0, 90, 0); // koridor leží po X
}
2025-06-25 23:54:00 +02:00
else // dir == Vector2Int.up → svět +Z
{
2025-06-25 23:54:00 +02:00
axis = Vector3.forward;
axisNeg = Vector3.back;
halfA = roomA.GetComponent<PrefabSize>().prefabSize.y * 0.5f;
halfB = roomB.GetComponent<PrefabSize>().prefabSize.y * 0.5f;
corridorRot = Quaternion.identity; // prefab míří po +Z
}
2025-06-25 23:54:00 +02:00
// 2) Vypočti start a end body (středy zdí)
Vector3 startPos = roomA.transform.position + axis * halfA;
Vector3 endPos = roomB.transform.position + axisNeg * halfB;
// 3) Vytvoř sekvenci dílů
CreateStraightCorridor(startPos, endPos, axis, corridorRot,
straightLengthZ, straightLengthX);
}
}
}
/// Vytvoří přímý koridor od startu k endu podél 'axis'.
private void CreateStraightCorridor(
Vector3 start, Vector3 end, Vector3 axis, Quaternion rot,
float stepLenZ, float stepLenX)
{
float fullDist = Vector3.Distance(start, end);
float stepLen = Mathf.Approximately(Mathf.Abs(axis.z), 1f) ? stepLenZ : stepLenX;
int segmentCount = Mathf.Max(1, Mathf.FloorToInt(fullDist / stepLen));
// 0) dveřní díl
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;
segPos = start + axis * (i * stepLen + stepLen * 0.5f);
Instantiate(prefab, segPos, rot, transform);
2025-06-23 16:30:18 +02:00
}
}
}