using System; using FlappyBird.Core; using UnityEngine; using Zenject; namespace FlappyBird.UI { public class GameUIController : IGameUIController, IInitializable, IDisposable { private readonly IGameManager _gameManager; private readonly IScoreManager _scoreManager; private readonly IObjectPoolManager _poolManager; private readonly GameObject _popupPrefab; private GameUIView _view; [Inject] public GameUIController( IGameManager gameManager, IScoreManager scoreManager, IObjectPoolManager poolManager, [Inject(Id = "ScorePopupPrefab")] GameObject popupPrefab) { _gameManager = gameManager; _scoreManager = scoreManager; _poolManager = poolManager; _popupPrefab = popupPrefab; } public void Initialize() { _poolManager.RegisterPool(_popupPrefab, 5); _gameManager.OnGameStateChanged += HandleGameStateChanged; _scoreManager.OnScoreChanged += HandleScoreChanged; } public void Dispose() { _gameManager.OnGameStateChanged -= HandleGameStateChanged; _scoreManager.OnScoreChanged -= HandleScoreChanged; } public void Bind(GameUIView view) { _view = view; RefreshView(); } private void HandleScoreChanged(int score) { if (_view == null || score == 0) return; _view.SetCurrentScore(score); _view.ShowScoreGain(); // 1. Get from pool var popup = _poolManager.Get(); // 2. Use the container provided by the View // 'worldPositionStays: false' is CRITICAL for UI elements popup.transform.SetParent(_view.PopupContainer, false); // 3. Reset local position to zero (the center of the container) popup.transform.localPosition = Vector3.zero; } private void HandleGameStateChanged(GameState state) => ApplyState(state); private void ApplyState(GameState state) { if (_view == null) return; _view.SetTapToStartVisible(state == GameState.Menu); _view.SetGameOverVisible(state == GameState.GameOver); _view.SetCurrentScoreVisible(state == GameState.Playing); } private void RefreshView() { _view.SetCurrentScore(_scoreManager.CurrentScore); _view.SetBestScore(_scoreManager.BestScore); ApplyState(_gameManager.CurrentState); } } }