Initial Commit
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user