288 lines
10 KiB
C#
288 lines
10 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
namespace GameFramework
|
||
{
|
||
/// <summary>
|
||
/// 结算界面 UI 控制器 —— 支持胜利/失败双界面。
|
||
///
|
||
/// 胜利:显示"你做到了" + 魂灵数量 + 新记录标识(如有)
|
||
/// 失败:显示"你迷失了" + 去色底图
|
||
///
|
||
/// 通过 GameManager.GameState 判断胜负。
|
||
/// </summary>
|
||
public class ScoringUIController : MonoBehaviour
|
||
{
|
||
[Header("底图")]
|
||
[SerializeField] private Image bgImage;
|
||
[SerializeField] private Sprite bgSprite; // bg.png(胜利彩色/失败去色共用同一张)
|
||
|
||
[Header("胜利面板")]
|
||
[SerializeField] private GameObject winPanel;
|
||
[SerializeField] private Image winTitleImage; // "你做到了" 图片
|
||
[SerializeField] private Sprite winTitleSprite; // nizuodaol.png
|
||
[SerializeField] private Text soulCountText; // 魂灵数量
|
||
[SerializeField] private Image soulCountBgImage; // 魂灵数量底图
|
||
[SerializeField] private Sprite soulCountBgSprite; // bgpoint.png
|
||
[SerializeField] private Image newRecordImage; // "新记录" 图片
|
||
[SerializeField] private Sprite newRecordSprite; // 新纪录.png
|
||
[SerializeField] private Image scoreLabelImage; // "拯救魂灵" 图片
|
||
[SerializeField] private Sprite scoreLabelSprite;
|
||
|
||
[Header("失败面板")]
|
||
[SerializeField] private GameObject losePanel;
|
||
[SerializeField] private Image loseTitleImage; // "你迷失了" 图片
|
||
[SerializeField] private Sprite loseTitleSprite; // nizuodaol.png 副本
|
||
|
||
[Header("排行榜")]
|
||
[SerializeField] private GameObject leaderboardPanel;
|
||
[SerializeField] private Transform leaderboardContainer;
|
||
[SerializeField] private Text finalScoreText;
|
||
|
||
[Header("新纪录输入")]
|
||
[SerializeField] private GameObject newHighScorePanel;
|
||
[SerializeField] private InputField nameInputField;
|
||
[SerializeField] private Button submitButton;
|
||
[SerializeField] private Button cancelButton;
|
||
|
||
[Header("导航")]
|
||
[SerializeField] private Button mainMenuButton;
|
||
[SerializeField] private Image mainMenuButtonImage; // 主界面.png
|
||
[SerializeField] private Sprite mainMenuBtnSprite;
|
||
|
||
[Header("装饰")]
|
||
[SerializeField] private Image lineImage;
|
||
[SerializeField] private Sprite lineSprite;
|
||
[SerializeField] private Image bgPointImage;
|
||
[SerializeField] private Sprite bgPointSprite;
|
||
|
||
[Header("Audio")]
|
||
[SerializeField] private AudioData submitSFX;
|
||
[SerializeField] private AudioData cancelSFX;
|
||
|
||
private bool _isWin;
|
||
|
||
void Start()
|
||
{
|
||
// 判断胜负
|
||
_isWin = (GameManager.GameState == GameState.Victory);
|
||
|
||
// 绑定按钮
|
||
if (submitButton != null)
|
||
submitButton.onClick.AddListener(OnSubmitClick);
|
||
if (cancelButton != null)
|
||
cancelButton.onClick.AddListener(OnCancelClick);
|
||
if (mainMenuButton != null)
|
||
mainMenuButton.onClick.AddListener(OnMainMenuClick);
|
||
|
||
// 初始隐藏所有面板
|
||
SetPanelActive(winPanel, false);
|
||
SetPanelActive(losePanel, false);
|
||
SetPanelActive(leaderboardPanel, false);
|
||
SetPanelActive(newHighScorePanel, false);
|
||
|
||
// 设置底图(共用同一张,失败时去色)
|
||
if (bgImage != null && bgSprite != null)
|
||
{
|
||
bgImage.sprite = bgSprite;
|
||
bgImage.color = _isWin ? Color.white : new Color(0.4f, 0.4f, 0.45f, 1f); // 失败去色
|
||
}
|
||
|
||
// 设置装饰图片
|
||
if (lineImage != null && lineSprite != null)
|
||
lineImage.sprite = lineSprite;
|
||
if (bgPointImage != null && bgPointSprite != null)
|
||
bgPointImage.sprite = bgPointSprite;
|
||
|
||
// 设置返回主界面按钮图片
|
||
if (mainMenuButtonImage != null && mainMenuBtnSprite != null)
|
||
mainMenuButtonImage.sprite = mainMenuBtnSprite;
|
||
|
||
if (_isWin)
|
||
{
|
||
ShowWinScreen();
|
||
}
|
||
else
|
||
{
|
||
ShowLoseScreen();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示胜利界面。
|
||
/// </summary>
|
||
void ShowWinScreen()
|
||
{
|
||
SetPanelActive(winPanel, true);
|
||
SetPanelActive(losePanel, false);
|
||
|
||
// 设置“你做到了”图片
|
||
if (winTitleImage != null && winTitleSprite != null)
|
||
winTitleImage.sprite = winTitleSprite;
|
||
|
||
// 设置魂灵数量底图
|
||
if (soulCountBgImage != null && soulCountBgSprite != null)
|
||
soulCountBgImage.sprite = soulCountBgSprite;
|
||
|
||
// 显示魂灵数量(复用 ScoreManager)
|
||
int score = ScoreManager.Instance != null ? ScoreManager.Instance.CurrentScore : 0;
|
||
if (soulCountText != null)
|
||
soulCountText.text = score.ToString();
|
||
|
||
// 设置“拯救魂灵”图片
|
||
if (scoreLabelImage != null && scoreLabelSprite != null)
|
||
scoreLabelImage.sprite = scoreLabelSprite;
|
||
|
||
// 判断是否新纪录
|
||
bool isNewRecord = ScoreManager.Instance != null && ScoreManager.Instance.HasNewHighScore;
|
||
if (newRecordImage != null)
|
||
{
|
||
newRecordImage.gameObject.SetActive(isNewRecord);
|
||
if (isNewRecord && newRecordSprite != null)
|
||
newRecordImage.sprite = newRecordSprite;
|
||
}
|
||
|
||
// 新纪录时显示输入面板,否则直接显示排行榜
|
||
if (isNewRecord)
|
||
{
|
||
ShowNewHighScorePanel();
|
||
}
|
||
else
|
||
{
|
||
ShowLeaderboard();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示失败界面。
|
||
/// </summary>
|
||
void ShowLoseScreen()
|
||
{
|
||
SetPanelActive(winPanel, false);
|
||
SetPanelActive(losePanel, true);
|
||
|
||
// 设置"你迷失了"图片
|
||
if (loseTitleImage != null && loseTitleSprite != null)
|
||
loseTitleImage.sprite = loseTitleSprite;
|
||
|
||
// 失败也显示排行榜
|
||
ShowLeaderboard();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示新纪录输入面板。
|
||
/// </summary>
|
||
void ShowNewHighScorePanel()
|
||
{
|
||
SetPanelActive(newHighScorePanel, true);
|
||
SetPanelActive(leaderboardPanel, false);
|
||
|
||
if (nameInputField != null)
|
||
{
|
||
nameInputField.text = "";
|
||
nameInputField.ActivateInputField();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示排行榜。
|
||
/// </summary>
|
||
void ShowLeaderboard()
|
||
{
|
||
SetPanelActive(newHighScorePanel, false);
|
||
SetPanelActive(leaderboardPanel, true);
|
||
UpdateLeaderboardDisplay();
|
||
|
||
if (mainMenuButton != null)
|
||
mainMenuButton.Select();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新排行榜显示。
|
||
/// </summary>
|
||
void UpdateLeaderboardDisplay()
|
||
{
|
||
if (ScoreManager.Instance == null || leaderboardContainer == null) return;
|
||
|
||
var data = ScoreManager.Instance.LoadPlayerScoreData();
|
||
|
||
for (int i = 0; i < leaderboardContainer.childCount; i++)
|
||
{
|
||
Transform entry = leaderboardContainer.GetChild(i);
|
||
bool hasData = i < data.list.Count;
|
||
|
||
Text rankText = FindTextByName(entry, "Rank");
|
||
Text scoreText = FindTextByName(entry, "Score");
|
||
Text nameText = FindTextByName(entry, "Name");
|
||
|
||
if (hasData)
|
||
{
|
||
var score = data.list[i];
|
||
if (rankText != null) rankText.text = $"{i + 1}.";
|
||
if (scoreText != null) scoreText.text = score.score.ToString();
|
||
if (nameText != null) nameText.text = score.playerName;
|
||
entry.gameObject.SetActive(true);
|
||
}
|
||
else
|
||
{
|
||
if (rankText != null) rankText.text = $"{i + 1}.";
|
||
if (scoreText != null) scoreText.text = "---";
|
||
if (nameText != null) nameText.text = "---";
|
||
entry.gameObject.SetActive(true);
|
||
}
|
||
}
|
||
}
|
||
|
||
Text FindTextByName(Transform parent, string name)
|
||
{
|
||
Transform t = parent.Find(name);
|
||
if (t != null)
|
||
return t.GetComponent<Text>();
|
||
return parent.GetComponent<Text>();
|
||
}
|
||
|
||
void SetPanelActive(GameObject panel, bool active)
|
||
{
|
||
if (panel != null)
|
||
panel.SetActive(active);
|
||
}
|
||
|
||
#region Button Handlers
|
||
void OnSubmitClick()
|
||
{
|
||
string playerName = "";
|
||
if (nameInputField != null)
|
||
playerName = nameInputField.text;
|
||
if (string.IsNullOrEmpty(playerName))
|
||
playerName = "Player";
|
||
|
||
if (ScoreManager.Instance != null)
|
||
ScoreManager.Instance.SavePlayerScore(playerName);
|
||
|
||
if (AudioManager.Instance != null && submitSFX != null)
|
||
AudioManager.Instance.PlaySFX(submitSFX);
|
||
|
||
ShowLeaderboard();
|
||
}
|
||
|
||
void OnCancelClick()
|
||
{
|
||
if (ScoreManager.Instance != null)
|
||
ScoreManager.Instance.SavePlayerScore("Player");
|
||
|
||
if (AudioManager.Instance != null && cancelSFX != null)
|
||
AudioManager.Instance.PlaySFX(cancelSFX);
|
||
|
||
ShowLeaderboard();
|
||
}
|
||
|
||
void OnMainMenuClick()
|
||
{
|
||
if (SceneLoader.Instance != null)
|
||
SceneLoader.Instance.LoadMainMenuScene();
|
||
}
|
||
#endregion
|
||
}
|
||
}
|