| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- using UnityEngine;
- using System.Collections.Generic;
- /// <summary>
- /// Manages fog of war for the maze - only shows explored areas
- /// AI entities can only see areas they've visited or are within their vision range
- /// </summary>
- public class MazeFogOfWar : MonoBehaviour
- {
- [Header("Fog Settings")]
- [SerializeField] private MazeController mazeController;
- [Header("Rendering")]
- [SerializeField] private ChunkedMazeRenderer chunkedRenderer;
- [SerializeField] private MeshMazeRenderer meshRenderer;
- [SerializeField] private Color fogColor = new Color(0.1f, 0.1f, 0.1f, 0.8f);
- [SerializeField] private Material fogMaterial;
- private HashSet<Vector2Int> exploredTiles = new();
- private Dictionary<GameObject, HashSet<Vector2Int>> entityVisionRanges = new();
- void Start()
- {
- if (fogMaterial == null)
- {
- CreateFogMaterial();
- }
- if (meshRenderer == null)
- {
- meshRenderer = GetComponent<MeshMazeRenderer>() ?? FindFirstObjectByType<MeshMazeRenderer>();
- }
- }
- /// <summary>
- /// Marks a tile as explored
- /// </summary>
- public void ExploreTile(Vector2Int tilePos)
- {
- exploredTiles.Add(tilePos);
- UpdateRendering();
- }
- /// <summary>
- /// Marks multiple tiles as explored
- /// </summary>
- public void ExploreTiles(IEnumerable<Vector2Int> tiles)
- {
- foreach (var tile in tiles)
- {
- exploredTiles.Add(tile);
- }
- UpdateRendering();
- }
- /// <summary>
- /// Updates vision range for an entity
- /// </summary>
- public void UpdateEntityVision(GameObject entity, Vector2Int position, float range)
- {
- HashSet<Vector2Int> visibleTiles = GetVisibleTiles(position, range);
- if (!entityVisionRanges.ContainsKey(entity))
- {
- entityVisionRanges[entity] = new HashSet<Vector2Int>();
- }
- // Remove old vision
- foreach (var tile in entityVisionRanges[entity])
- {
- if (!exploredTiles.Contains(tile) && !IsTileVisibleByOtherEntities(tile))
- {
- // Tile should be hidden
- }
- }
- // Add new vision
- entityVisionRanges[entity] = visibleTiles;
- foreach (var tile in visibleTiles)
- {
- exploredTiles.Add(tile);
- }
- UpdateRendering();
- }
- /// <summary>
- /// Gets all tiles visible from a position within range
- /// </summary>
- private HashSet<Vector2Int> GetVisibleTiles(Vector2Int center, float range)
- {
- HashSet<Vector2Int> visible = new();
- var maze = mazeController.GetCurrentMaze();
- if (maze == null) return visible;
- int rangeInt = Mathf.CeilToInt(range);
- for (int x = center.x - rangeInt; x <= center.x + rangeInt; x++)
- {
- for (int y = center.y - rangeInt; y <= center.y + rangeInt; y++)
- {
- Vector2Int tilePos = new Vector2Int(x, y);
- if (Vector2Int.Distance(center, tilePos) <= range)
- {
- if (maze.IsInBounds(x, y) && HasLineOfSight(center, tilePos))
- {
- visible.Add(tilePos);
- }
- }
- }
- }
- return visible;
- }
- /// <summary>
- /// Checks if there's line of sight between two points
- /// </summary>
- private bool HasLineOfSight(Vector2Int from, Vector2Int to)
- {
- var maze = mazeController.GetCurrentMaze();
- if (maze == null) return false;
- // Simple line of sight check - can be enhanced with proper raycasting
- Vector2Int delta = to - from;
- int steps = Mathf.Max(Mathf.Abs(delta.x), Mathf.Abs(delta.y));
- for (int i = 1; i < steps; i++)
- {
- float t = (float)i / steps;
- Vector2Int checkPos = new Vector2Int(
- Mathf.RoundToInt(from.x + delta.x * t),
- Mathf.RoundToInt(from.y + delta.y * t)
- );
- if (!maze.IsWalkable(checkPos.x, checkPos.y))
- {
- return false;
- }
- }
- return true;
- }
- /// <summary>
- /// Checks if a tile is visible by any other entity
- /// </summary>
- private bool IsTileVisibleByOtherEntities(Vector2Int tile)
- {
- foreach (var vision in entityVisionRanges.Values)
- {
- if (vision.Contains(tile))
- {
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// Updates the rendering to show only explored areas
- /// </summary>
- private void UpdateRendering()
- {
- if (chunkedRenderer != null)
- {
- // The chunked renderer will handle showing/hiding tiles based on exploration
- chunkedRenderer.RefreshVisibleChunks();
- }
- if (meshRenderer != null)
- {
- meshRenderer.RefreshFogOfWar();
- }
- }
- /// <summary>
- /// Creates a default fog material
- /// </summary>
- private void CreateFogMaterial()
- {
- fogMaterial = new Material(Shader.Find("Sprites/Default"));
- fogMaterial.color = fogColor;
- }
- /// <summary>
- /// Checks if a tile is explored
- /// </summary>
- public bool IsTileExplored(Vector2Int tile)
- {
- return exploredTiles.Contains(tile);
- }
- /// <summary>
- /// Gets all explored tiles
- /// </summary>
- public HashSet<Vector2Int> GetExploredTiles()
- {
- return new HashSet<Vector2Int>(exploredTiles);
- }
- /// <summary>
- /// Removes an entity from vision tracking
- /// </summary>
- public void RemoveEntity(GameObject entity)
- {
- entityVisionRanges.Remove(entity);
- UpdateRendering();
- }
- }
|