Files
3DBlobici-WorkingTitle/3D blobici/Assets/Scripts/MapGen/MapGenManager.cs
2025-06-25 23:54:00 +02:00

203 lines
7.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class MapGenManager : MonoBehaviour
{
[Header("Room Prefabs")]
[SerializeField] private List<GameObject> mapPrefab = new List<GameObject>();
[Header("Player")]
[SerializeField] private GameObject Player;
[Header("Corridor Prefabs")]
[SerializeField] private GameObject CorridorStraight;
[SerializeField] private GameObject CorridorStraightUnlit;
[SerializeField] private GameObject DoorCorridor;
[Header("Layout")]
[SerializeField] private MapLayout layout;
[Header("Generation Settings")]
[SerializeField] private int RoomDistance = 3;
private Dictionary<Vector2Int, GameObject> gridToRoom = new();
private readonly Vector3 roomOriginOffset = Vector3.zero;
void Start() => GenerateFromLayout();
private void GenerateFromLayout()
{
if (layout == null || string.IsNullOrWhiteSpace(layout.grid))
{
Debug.LogError("Layout asset není přiřazený nebo je prázdný!");
return;
}
gridToRoom.Clear();
/* ---------- 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
Vector3 spawnPos = roomOriginOffset;
GameObject spawnRoom = Instantiate(spawnPrefab, spawnPos, Quaternion.identity, transform);
gridToRoom[new Vector2Int(0, 0)] = spawnRoom;
// hráče necháme na spawnu
if (Player != null)
{
Vector3 playerPos = spawnPos + new Vector3(0, 1, 3);
Instantiate(Player, playerPos, Quaternion.identity, transform);
}
/* ---------- 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;
/* ---------- 2) SMYČKA PŘES GRID ------------- */
for (int z = 0; z < rows; z++)
{
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
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 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();
}
private void BuildCorridors()
{
// 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 };
foreach (var kvp in gridToRoom)
{
Vector2Int cell = kvp.Key;
GameObject roomA = kvp.Value;
foreach (Vector2Int dir in stepDirs)
{
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)
{
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
}
else // dir == Vector2Int.up → svět +Z
{
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
}
// 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);
}
}
}