using System.Collections.Generic; using UnityEngine; namespace MazeGen { /// /// Single entry point for milestone 1: drop this on one empty GameObject in the scene /// and press Play. It creates the generator, agent and path visualizer, spawns the /// start room(s), and lets you click yellow exit markers to walk the agent through them. /// [RequireComponent(typeof(MazeGenerator))] public class MazeSceneBuilder : MonoBehaviour { [SerializeField, Min(1)] private int startRoomCount = 1; [SerializeField] private float startRoomSpread = 6f; private MazeGenerator _generator; private MazeAgentController _agentController; private PathVisualizer _pathVisualizer; private MazeCameraController _cameraController; private readonly Dictionary _exitMarkers = new Dictionary(); private void Awake() { _generator = GetComponent(); _generator.RoomGenerated += OnRoomGenerated; _generator.ExitAdded += OnExitAdded; var agentGO = new GameObject("Agent"); agentGO.transform.SetParent(transform, false); _agentController = agentGO.AddComponent(); _agentController.Initialize(_generator); var pathGO = new GameObject("PathVisualizer"); pathGO.transform.SetParent(transform, false); pathGO.AddComponent(); _pathVisualizer = pathGO.AddComponent(); var cam = Camera.main; if (cam != null) { _cameraController = cam.GetComponent(); if (_cameraController == null) _cameraController = cam.gameObject.AddComponent(); } } private void Start() { Room firstStartRoom = null; for (int i = 0; i < startRoomCount; i++) { float angle = startRoomCount > 1 ? (360f / startRoomCount) * i : 0f; Vector2 pos = startRoomCount > 1 ? new Vector2(Mathf.Cos(angle * Mathf.Deg2Rad), Mathf.Sin(angle * Mathf.Deg2Rad)) * startRoomSpread : Vector2.zero; var room = _generator.GenerateStartRoom(pos); firstStartRoom ??= room; } // Milestone 1: single agent spawns in the first start room. _agentController.Spawn(firstStartRoom); _agentController.Agent.RoomEntered += room => _pathVisualizer.AppendPoint(room.Position); _agentController.Agent.RoomEntered += room => _cameraController?.FocusOn(room.Position); _agentController.Agent.ReachedExitRoom += room => Debug.Log($"[MazeGen] Agent reached the exit room (id {room.Id})!"); _pathVisualizer.AppendPoint(firstStartRoom.Position); _cameraController?.SnapTo(firstStartRoom.Position); RefreshMarkerVisuals(); } private void OnRoomGenerated(Room room) { var roomGO = new GameObject($"Room_{room.Id}_{room.Kind}"); roomGO.transform.SetParent(transform, false); roomGO.AddComponent().Initialize(room); foreach (var exit in room.Exits) SpawnExitMarker(room, exit); } private void OnExitAdded(Room room, Exit exit) { SpawnExitMarker(room, exit); RefreshMarkerVisuals(); } private void SpawnExitMarker(Room room, Exit exit) { var markerGO = new GameObject($"Exit_{exit.Id}"); markerGO.transform.SetParent(transform, false); var marker = markerGO.AddComponent(); marker.Initialize(room, exit); _exitMarkers[exit.Id] = marker; } private void Update() { if (!MazeInput.WasLeftClickedThisFrame()) return; Camera cam = Camera.main; if (cam == null) return; Ray ray = cam.ScreenPointToRay(MazeInput.GetPointerScreenPosition()); RaycastHit2D hit = Physics2D.GetRayIntersection(ray, Mathf.Infinity); if (hit.collider != null && hit.collider.TryGetComponent(out ExitMarker marker)) OnExitClicked(marker.ExitData); } private void OnExitClicked(Exit exit) { if (_agentController.Agent == null || exit.OwnerRoomId != _agentController.Agent.CurrentRoom.Id) { Debug.Log("[MazeGen] That exit isn't reachable from your current room."); return; } if (_agentController.TryUseExit(exit)) RefreshMarkerVisuals(); } private void RefreshMarkerVisuals() { Room currentRoom = _agentController.Agent?.CurrentRoom; MazeAgent agent = _agentController.Agent; foreach (var marker in _exitMarkers.Values) marker.UpdateVisual(currentRoom, agent); } } }