Initial Commit

This commit is contained in:
2026-03-16 14:38:46 +02:00
commit b8f7327a21
2327 changed files with 253610 additions and 0 deletions
+135
View File
@@ -0,0 +1,135 @@
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using Zenject;
using FlappyBird.Core;
namespace FlappyBird.UI
{
public class GameUIView : MonoBehaviour
{
[Header("Score Display")]
[SerializeField] private Component currentScoreText;
[SerializeField] private Component bestScoreText;
[SerializeField] private RectTransform popupContainer;
[SerializeField] private float scorePopScale = 1.4f;
[SerializeField] private float scorePopDuration = 0.1f;
[Header("Screens")]
[SerializeField] private CanvasGroup tapToStartGroup;
[SerializeField] private CanvasGroup gameOverGroup;
[SerializeField] private float fadeSpeed = 5f;
[Header("Game Over Details")]
[SerializeField] private Component gameOverScoreText;
[SerializeField] private Component gameOverBestScoreText;
private IGameUIController _controller;
private RectTransform _currentScoreRect;
private Vector3 _currentScoreBaseScale;
private float _scorePopTimer;
private List<ScorePopupView> _activePopups = new List<ScorePopupView>();
public Transform PopupTransform => transform;
public RectTransform PopupContainer => popupContainer != null ? popupContainer : (transform as RectTransform);
[Inject]
public void Construct(IGameUIController controller)
{
_controller = controller;
}
private void Awake()
{
if (currentScoreText != null)
{
_currentScoreRect = currentScoreText.transform as RectTransform;
_currentScoreBaseScale = _currentScoreRect.localScale;
}
}
private void Start() => _controller.Bind(this);
private void Update()
{
UpdateScorePop();
UpdateScreenFades();
UpdateMenuPulse();
HandlePopupCleanup();
}
public void ShowScoreGain()
{
_scorePopTimer = scorePopDuration;
}
public void SetCurrentScore(int score)
{
SetText(currentScoreText, score.ToString());
SetText(gameOverScoreText, score.ToString());
}
public void SetBestScore(int bestScore)
{
SetText(bestScoreText, $"BEST: {bestScore}");
SetText(gameOverBestScoreText, bestScore.ToString());
}
private void UpdateScorePop()
{
if (_scorePopTimer <= 0) return;
_scorePopTimer -= Time.unscaledDeltaTime;
// Use an animation curve feel: pop out fast, shrink back
float t = _scorePopTimer / scorePopDuration;
float scale = Mathf.Lerp(1f, scorePopScale, t);
_currentScoreRect.localScale = _currentScoreBaseScale * scale;
}
private void UpdateScreenFades()
{
float step = fadeSpeed * Time.unscaledDeltaTime;
// Smoothly fade groups based on their active state handled in Controller
tapToStartGroup.alpha = Mathf.MoveTowards(tapToStartGroup.alpha, tapToStartGroup.interactable ? 1 : 0, step);
gameOverGroup.alpha = Mathf.MoveTowards(gameOverGroup.alpha, gameOverGroup.interactable ? 1 : 0, step);
}
private void UpdateMenuPulse()
{
if (tapToStartGroup.interactable)
{
float pulse = 1f + Mathf.Sin(Time.unscaledTime * 4f) * 0.05f;
tapToStartGroup.transform.localScale = Vector3.one * pulse;
}
}
public void SetTapToStartVisible(bool visible)
{
tapToStartGroup.interactable = visible;
tapToStartGroup.blocksRaycasts = visible;
}
public void SetGameOverVisible(bool visible)
{
gameOverGroup.interactable = visible;
gameOverGroup.blocksRaycasts = visible;
}
public void SetCurrentScoreVisible(bool visible)
{
currentScoreText.gameObject.SetActive(visible);
}
private void HandlePopupCleanup()
{
// Logic to return expired popups to pool would go here via the Controller
}
private static void SetText(Component target, string value)
{
if (target == null) return;
var prop = target.GetType().GetProperty("text");
prop?.SetValue(target, value, null);
}
}
}