using UnityEngine; using System.Collections.Generic; public class MapGenerator : MonoBehaviour { private static readonly Vector2Int[] directions = { new Vector2Int(0, 1), // up new Vector2Int(1, 0), // right new Vector2Int(0, -1), // down new Vector2Int(-1, 0), // left }; public static void Generate(Tile[,] tiles, GameObject[] prefabs, int width, int height, int seed) { Random.InitState(seed); Dictionary<(int, int), List> connections = new(); // 1. Minimum spanning tree connection graph var visited = new HashSet<(int, int)>(); var edges = new List<(int x, int y, int dir)>(); int startX = Random.Range(0, width); int startY = Random.Range(0, height); visited.Add((startX, startY)); AddEdges(startX, startY, visited, width, height, edges); while (visited.Count < width * height && edges.Count > 0) { int idx = Random.Range(0, edges.Count); var (x, y, dir) = edges[idx]; edges.RemoveAt(idx); int nx = x + directions[dir].x; int ny = y + directions[dir].y; if (nx < 0 || nx >= width || ny < 0 || ny >= height || visited.Contains((nx, ny))) continue; visited.Add((nx, ny)); AddEdges(nx, ny, visited, width, height, edges); AddConnection(connections, x, y, dir); AddConnection(connections, nx, ny, (dir + 2) % 4); // Opposite direction } float offsetX = -((width - 1) / 2f); float offsetY = ((height - 1) / 2f); // 2. Create Tiles and save the solution for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { var dirList = connections.ContainsKey((x, y)) ? connections[(x, y)] : new List(); string type = GetTileType(dirList); int rotation = GetRotation(dirList, type); GameObject prefab = FindPrefab(prefabs, type); GameObject tileObj = GameObject.Instantiate(prefab); tileObj.transform.position = new Vector2(offsetX + x, offsetY - y); Tile tile = tileObj.GetComponent(); tile.X = x; tile.Y = y; tile.baseConnections = GetBaseConnections(type); tile.graphicRotationOffset = GetGraphicOffset(type); tile.ApplyRotation(rotation); tile.SolutionRotation = rotation; tile.SetConnectionState(true); // Set as connected texture (green) tiles[x, y] = tile; } } // 3. Shuffle (random rotation) foreach (var tile in tiles) { if (!tile.locked) tile.RandomRotate(); tile.SetConnectionState(false); // Set as disconnected texture (black) } } private static void AddEdges(int x, int y, HashSet<(int, int)> visited, int width, int height, List<(int, int, int)> edges) { for (int dir = 0; dir < 4; dir++) { int nx = x + directions[dir].x; int ny = y + directions[dir].y; if (nx >= 0 && nx < width && ny >= 0 && ny < height && !visited.Contains((nx, ny))) edges.Add((x, y, dir)); } } private static void AddConnection(Dictionary<(int, int), List> map, int x, int y, int dir) { var key = (x, y); if (!map.ContainsKey(key)) map[key] = new List(); map[key].Add(dir); } private static string GetTileType(List dirs) { switch (dirs.Count) { case 1: return "Node"; case 2: if ((dirs[0] + 2) % 4 == dirs[1]) return "Straight"; else return "Corner"; case 3: return "TriCorner"; case 4: return "Node"; default: return "Node"; } } private static int GetRotation(List dirs, string type) { dirs.Sort(); switch (type) { case "Node": return dirs.Count > 0 ? dirs[0] : 0; case "Straight": return dirs.Contains(0) && dirs.Contains(2) ? 0 : 1; case "Corner": if (dirs.Contains(0) && dirs.Contains(1)) return 0; if (dirs.Contains(1) && dirs.Contains(2)) return 1; if (dirs.Contains(2) && dirs.Contains(3)) return 2; return 3; case "TriCorner": for (int i = 0; i < 4; i++) if (!dirs.Contains(i)) return i; return 0; default: return 0; } } private static GameObject FindPrefab(GameObject[] prefabs, string type) { foreach (var p in prefabs) { if (p.name.Contains(type)) return p; } Debug.LogError($"No prefab found for type: {type}"); return prefabs[0]; } private static int[] GetBaseConnections(string type) { switch (type) { case "Straight": return new int[] { 3, 1 }; // left and right case "Corner": return new int[] { 3, 0 }; // left and up case "TriCorner": return new int[] { 3, 0, 1 }; // left, up, and right case "Node": return new int[] { 0 }; // up default: return new int[0]; } } private static int GetGraphicOffset(string type) { return 0; // No offset needed as the texture direction is consistent } }