using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Tilemaps; public class GridManager : MonoBehaviour { #region Statication public static GridManager instance; private void Awake() { if (instance != null && instance != this) { Destroy(gameObject); return; } instance = this; } #endregion [Header("Size")] [SerializeField] private int width; [SerializeField] private int height; [Header("Cache")] [SerializeField] private TileObject tilePrefab; [SerializeField] Camera cam; [SerializeField] private Transform grid; [SerializeField] LayerMask environmentLayer; private Dictionary allTiles = new(); private void Start() { GenerateGrid(); cam.transform.position = new Vector3((float)width / 2, (float)height / 2, 0); foreach (PlayerEntity player in TurnHandler.instance.playerEntities) { player.currentTile = GetTileFromWorldPos(player.transform.position); player.currentTile.hasUnit = player; } foreach (Enemy enemy in TurnHandler.instance.enemyEntities) { enemy.currentTile = GetTileFromWorldPos(enemy.transform.position); enemy.currentTile.hasUnit = enemy; } foreach (Transform spawnLocation in EnemySpawner.instance.spawnLocationPos) { EnemySpawner.instance.spawnLocations.Add(GetTileFromWorldPos(spawnLocation.position)); } } private void GenerateGrid() { for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { Vector2 pos = new Vector2(x - ((float)width / 2) + 0.5f, y - ((float)height / 2) + 0.5f); TileObject newTile = Instantiate(tilePrefab, pos, Quaternion.identity); newTile.name = $"Tile {x} {y}"; allTiles[pos] = newTile; newTile.transform.SetParent(grid); Collider2D isBlocked = Physics2D.OverlapCircle(newTile.transform.position, 0.05f, environmentLayer); if (isBlocked) { newTile.blocked = true; } } } GetTileNeighbors(); } private void GetTileNeighbors() { for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { Vector2 pos = new Vector2(x - ((float)width / 2) + 0.5f, y - ((float)height / 2) + 0.5f); TileObject currentTile = allTiles[pos]; TileObject upTile = GetTileFromWorldPos(pos + Vector2.up); if (upTile && !upTile.blocked) { currentTile.neighbors.Add(upTile);} TileObject downTile = GetTileFromWorldPos(pos + Vector2.down); if (downTile && !downTile.blocked) { currentTile.neighbors.Add(downTile);} TileObject leftTile = GetTileFromWorldPos(pos + Vector2.left); if (leftTile && !leftTile.blocked) { currentTile.neighbors.Add(leftTile);} TileObject rightTile = GetTileFromWorldPos(pos + Vector2.right); if (rightTile && !rightTile.blocked) { currentTile.neighbors.Add(rightTile);} } } } public TileObject GetTileFromWorldPos(Vector2 pos) { if (allTiles.TryGetValue(pos, out TileObject tile)) { return tile; } return null; } public TileObject FindClosestEmptyTile(TileObject requestedTile) { if (!requestedTile.hasUnit) { return requestedTile; } Queue frontier = new(); List visited = new(); frontier.Enqueue(requestedTile); while (frontier.Count > 0) { TileObject currentTile = frontier.Dequeue(); foreach (TileObject neighbor in currentTile.neighbors) { if (!visited.Contains(neighbor)) { if (!neighbor.hasUnit && !neighbor.blocked) { return neighbor; } visited.Add(neighbor); frontier.Enqueue(neighbor); } } } return null; } }