using UnityEngine; using Zenject; using FlappyBird.Core; namespace FlappyBird.Gameplay.Bird { /// /// Thin MonoBehaviour on the bird GameObject. /// Responsibilities: /// - Detect solid pipe collisions (OnCollisionEnter2D) /// - Detect trigger-based pipe collisions (OnTriggerEnter2D, tag "Obstacle") /// - Check vertical screen bounds every frame /// On any death condition: calls IDeathHandler then notifies GameManagerView. /// NO death logic lives here. /// [RequireComponent(typeof(Collider2D))] public sealed class BirdCollisionView : MonoBehaviour { private GameManagerView _gameManagerView; private BirdSettings _birdSettings; private IGameStateManager _gameStateManager; private IDeathHandler _deathHandler; [Inject] private void Construct( GameManagerView gameManagerView, BirdSettings birdSettings, IGameStateManager gameStateManager, IDeathHandler deathHandler) { _gameManagerView = gameManagerView; _birdSettings = birdSettings; _gameStateManager = gameStateManager; _deathHandler = deathHandler; } // ── Unity lifecycle ──────────────────────────────────────────────── private void Update() { // Bounds check only runs while playing — prevents re-triggering death. if (_gameStateManager.CurrentState != GameState.Playing) return; CheckBounds(); } private void OnCollisionEnter2D(Collision2D other) { Die(); } private void OnTriggerEnter2D(Collider2D other) { // Ignore the score trigger that sits in the gap centre. if (other.CompareTag("Bird")) return; if (other.CompareTag("Obstacle")) Die(); } // ── Private helpers ──────────────────────────────────────────────── /// /// Position-based ceiling/floor check. /// No boundary collider objects are required in the scene. /// private void CheckBounds() { float y = transform.position.y; if (y > _birdSettings.MaxY || y < _birdSettings.MinY) Die(); } /// /// Single death entry-point — applies side-effects then triggers GameOver. /// Guard inside NotifyBirdDied prevents double-firing. /// private void Die() { _deathHandler.HandleDeath(); _gameManagerView.NotifyBirdDied(); } } }