Files
AppleHillsProduction/Assets/Scripts/Minigames/BirdPooper/BirdPooperGameManager.cs
2025-11-21 11:33:49 +01:00

188 lines
5.8 KiB
C#

using UnityEngine;
using Core.Lifecycle;
namespace Minigames.BirdPooper
{
/// <summary>
/// Central game manager for Bird Pooper minigame.
/// Manages game flow, UI, obstacle spawning, and reacts to player events.
/// Singleton pattern for easy access.
/// </summary>
public class BirdPooperGameManager : ManagedBehaviour
{
private static BirdPooperGameManager _instance;
public static BirdPooperGameManager Instance => _instance;
[Header("References")]
[SerializeField] private BirdPlayerController player;
[SerializeField] private ObstacleSpawner obstacleSpawner;
[SerializeField] private TargetSpawner targetSpawner;
[SerializeField] private GameOverScreen gameOverScreen;
[SerializeField] private GameObject poopPrefab;
[Header("Game State")]
private int targetsHit;
private bool isGameOver;
internal override void OnManagedAwake()
{
base.OnManagedAwake();
// Set singleton instance
if (_instance != null && _instance != this)
{
Debug.LogWarning("[BirdPooperGameManager] Multiple instances detected! Destroying duplicate.");
Destroy(gameObject);
return;
}
_instance = this;
// Validate references
if (player == null)
{
Debug.LogError("[BirdPooperGameManager] Player reference not assigned!");
}
if (obstacleSpawner == null)
{
Debug.LogError("[BirdPooperGameManager] ObstacleSpawner reference not assigned!");
}
if (targetSpawner == null)
{
Debug.LogWarning("[BirdPooperGameManager] TargetSpawner reference not assigned! Targets will not spawn.");
}
if (gameOverScreen == null)
{
Debug.LogError("[BirdPooperGameManager] GameOverScreen reference not assigned!");
}
else
{
// Hide game over screen on start
gameOverScreen.gameObject.SetActive(false);
}
if (poopPrefab == null)
{
Debug.LogWarning("[BirdPooperGameManager] Poop prefab not assigned!");
}
}
internal override void OnManagedStart()
{
base.OnManagedStart();
// Initialize game state
isGameOver = false;
targetsHit = 0;
// Subscribe to player events
if (player != null)
{
player.OnPlayerDamaged.AddListener(HandlePlayerDamaged);
Debug.Log("[BirdPooperGameManager] Subscribed to player damaged event");
}
// Start obstacle spawning
if (obstacleSpawner != null)
{
obstacleSpawner.StartSpawning();
Debug.Log("[BirdPooperGameManager] Started obstacle spawning");
}
// Start target spawning
if (targetSpawner != null)
{
targetSpawner.StartSpawning();
Debug.Log("[BirdPooperGameManager] Started target spawning");
}
}
internal override void OnManagedDestroy()
{
// Unsubscribe from player events
if (player != null)
{
player.OnPlayerDamaged.RemoveListener(HandlePlayerDamaged);
}
// Clear singleton
if (_instance == this)
{
_instance = null;
}
base.OnManagedDestroy();
}
/// <summary>
/// Called when player takes damage/dies.
/// Shows game over screen.
/// </summary>
private void HandlePlayerDamaged()
{
if (isGameOver) return;
isGameOver = true;
Debug.Log($"[BirdPooperGameManager] Player damaged - Game Over! Targets Hit: {targetsHit}");
// Stop spawning obstacles
if (obstacleSpawner != null)
{
obstacleSpawner.StopSpawning();
}
// Stop spawning targets
if (targetSpawner != null)
{
targetSpawner.StopSpawning();
}
// Show game over screen
if (gameOverScreen != null)
{
gameOverScreen.Show();
}
else
{
Debug.LogError("[BirdPooperGameManager] GameOverScreen reference missing!");
}
}
/// <summary>
/// Spawns a poop projectile at the player's current position.
/// Called by UI button OnClick event.
/// </summary>
public void SpawnPoop()
{
if (isGameOver || player == null || poopPrefab == null)
return;
Vector3 spawnPosition = player.transform.position;
Instantiate(poopPrefab, spawnPosition, Quaternion.identity);
Debug.Log($"[BirdPooperGameManager] Spawned poop at {spawnPosition}");
}
/// <summary>
/// Called when a target is successfully hit by poop (Phase 5).
/// </summary>
public void OnTargetHit()
{
if (isGameOver) return;
targetsHit++;
Debug.Log($"[BirdPooperGameManager] Target Hit! Total: {targetsHit}");
}
#region Public Accessors
public bool IsGameOver => isGameOver;
public int TargetsHit => targetsHit;
#endregion
}
}