using UnityEngine; using TMPro; using UnityEngine.UI; using System.Collections; using System.Collections.Generic; using UnityEngine.SceneManagement; public class ScoreManager : MonoBehaviour { [Header("UI References")] public TextMeshProUGUI scoreText; public TextMeshProUGUI timerText; public GameObject resultCanvas; public TextMeshProUGUI resultStatusText; public TextMeshProUGUI resultScoreText; public Button restartButton; [Header("Distance Floating UI")] public GameObject distanceCanvas; public TextMeshProUGUI distanceText; [Header("Audio Clips")] public List scoreSounds; // Danh sách các âm thanh vào rổ ngẫu nhiên public AudioClip winSound; public AudioClip loseSound; public AudioClip buttonClickSound; public AudioClip flashSound; public AudioClip bgMusic; public AudioClip alarmSound; [Header("Game Settings")] public float gameDuration = 60f; public int targetScore = 50; private int currentScore = 0; private float timeRemaining; private bool isGameOver = false; private AudioSource musicSource; private bool alarmPlayed = false; void Start() { currentScore = 0; timeRemaining = gameDuration; isGameOver = false; alarmPlayed = false; musicSource = gameObject.AddComponent(); if (bgMusic != null) { musicSource.clip = bgMusic; musicSource.loop = true; musicSource.volume = 0.5f; musicSource.Play(); } UpdateScoreUI(); if (distanceCanvas != null) distanceCanvas.SetActive(false); if (resultCanvas != null) resultCanvas.SetActive(false); if (restartButton != null) { restartButton.onClick.RemoveAllListeners(); restartButton.onClick.AddListener(() => { if (AudioPool.Instance != null) AudioPool.Instance.PlaySound(buttonClickSound); RestartGame(); }); } } void Update() { if (isGameOver) return; if (timeRemaining > 0) { timeRemaining -= Time.deltaTime; UpdateTimerUI(); if (timeRemaining <= 10f) { timerText.color = Mathf.PingPong(Time.time * 5, 1) > 0.5f ? Color.red : Color.white; if (!alarmPlayed && alarmSound != null) { if (AudioPool.Instance != null) AudioPool.Instance.PlaySound(alarmSound); alarmPlayed = true; } } } else { timeRemaining = 0; UpdateTimerUI(); CheckGameEnd(); } } void CheckGameEnd() { if (currentScore >= targetScore) { EndGame("YOU WIN!", Color.green, winSound); StartCoroutine(CelebrationEffect()); } else { EndGame("GAME OVER", Color.red, loseSound); } } private void OnTriggerEnter(Collider other) { ProcessScore(other.gameObject); } private void OnCollisionEnter(Collision collision) { ProcessScore(collision.gameObject); } void ProcessScore(GameObject obj) { if (isGameOver) return; BouncyBall ball = obj.GetComponent(); if (ball == null || ball.isScored) return; ball.isScored = true; #if UNITY_ANDROID || UNITY_IOS Handheld.Vibrate(); #endif // Chọn ngẫu nhiên âm thanh vào rổ if (AudioPool.Instance != null && scoreSounds != null && scoreSounds.Count > 0) { AudioClip randomClip = scoreSounds[Random.Range(0, scoreSounds.Count)]; AudioPool.Instance.PlaySound(randomClip, 1f, true); } float distance = Vector3.Distance(ball.shotPosition, transform.position); int points = CalculatePoints(distance); currentScore += points; UpdateScoreUI(); StartCoroutine(FlashScoreUI()); if (distanceCanvas != null) { StopAllCoroutines(); // Dùng cái này để đảm bảo reset mọi hiệu ứng cũ StartCoroutine(ShowDistanceUI(distance)); StartCoroutine(CelebrationEffect()); // Chỉ chạy nếu đã win } ball.enabled = false; Destroy(obj, 1f); } int CalculatePoints(float distance) { if (distance >= 20f) return 3; if (distance >= 10f) return 2; if (distance >= 6f) return 1; return 1; } void UpdateScoreUI() { if (scoreText != null) scoreText.text = "Score: " + currentScore; } void UpdateTimerUI() { if (timerText != null) { int minutes = Mathf.FloorToInt(timeRemaining / 60); int seconds = Mathf.FloorToInt(timeRemaining % 60); timerText.text = string.Format("{0:00}:{1:00}", minutes, seconds); } } IEnumerator ShowDistanceUI(float distance) { if (distanceText != null) distanceText.text = $"{distance:F1}m"; distanceCanvas.SetActive(true); for (int i = 0; i < 5; i++) { distanceText.enabled = !distanceText.enabled; if (distanceText.enabled && AudioPool.Instance != null) AudioPool.Instance.PlaySound(flashSound, 0.7f, true); yield return new WaitForSeconds(0.2f); } distanceText.enabled = true; yield return new WaitForSeconds(1.0f); distanceCanvas.SetActive(false); } IEnumerator FlashScoreUI() { for (int i = 0; i < 3; i++) { scoreText.color = Color.yellow; yield return new WaitForSeconds(0.1f); scoreText.color = Color.white; yield return new WaitForSeconds(0.1f); } } IEnumerator CelebrationEffect() { while (isGameOver) { resultStatusText.color = new Color(Random.value, Random.value, Random.value); resultScoreText.transform.localScale = Vector3.one * (1f + Mathf.PingPong(Time.time * 2, 0.2f)); yield return new WaitForSeconds(0.1f); } } void EndGame(string status, Color statusColor, AudioClip endClip) { isGameOver = true; if (musicSource != null) musicSource.Stop(); if (AudioPool.Instance != null) AudioPool.Instance.PlaySound(endClip); if (resultCanvas != null) { resultCanvas.SetActive(true); resultStatusText.text = status; resultStatusText.color = statusColor; resultScoreText.text = "Final Score: " + currentScore; } } public void RestartGame() { SceneManager.LoadScene(SceneManager.GetActiveScene().name); } }