191 lines
6.8 KiB
C#

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
namespace Streamingle.Contents.BossRaid
{
/// <summary>
/// 승리 결과 화면 UI.
/// "YOU WIN!" + 전투 스탯 요약.
/// </summary>
public class VictoryScreen : MonoBehaviour
{
#region Fields
[Header("설정")]
[SerializeField] private float titleAppearDelay = 0.3f;
[SerializeField] private float statsAppearDelay = 0.8f;
[SerializeField] private float statLineInterval = 0.2f;
[Header("비주얼")]
[SerializeField] private Color titleColor = new Color(1f, 0.85f, 0.2f);
[SerializeField] private Color statLabelColor = new Color(0.7f, 0.7f, 0.7f);
[SerializeField] private Color statValueColor = new Color(0.3f, 1f, 0.5f);
private Canvas _canvas;
private CanvasGroup _canvasGroup;
private Text _titleText;
private Text _statsText;
private Coroutine _showCoroutine;
private Font _font;
#endregion
#region Unity Messages
private void Awake()
{
_font = BossRaidFontLoader.Load();
CreateUI();
_canvasGroup.alpha = 0f;
}
#endregion
#region Public Methods
public void Show(BossRaidResult result)
{
if (_showCoroutine != null)
StopCoroutine(_showCoroutine);
_showCoroutine = StartCoroutine(ShowCoroutine(result));
}
public void Hide()
{
if (_showCoroutine != null)
{
StopCoroutine(_showCoroutine);
_showCoroutine = null;
}
_canvasGroup.alpha = 0f;
}
#endregion
#region Private Methods
private IEnumerator ShowCoroutine(BossRaidResult result)
{
_canvasGroup.alpha = 1f;
_titleText.text = "";
_statsText.text = "";
yield return new WaitForSecondsRealtime(titleAppearDelay);
_titleText.text = "YOU WIN!";
yield return StartCoroutine(PunchScale(_titleText.rectTransform, 0.4f, 1.5f));
yield return new WaitForSecondsRealtime(statsAppearDelay);
string[] lines = new string[]
{
$"Boss: {result.bossName}",
$"Time: {FormatTime(result.elapsedTime)}",
$"Total Damage: {result.totalDamage:N0}",
$"Hits: {result.hitCount}",
$"Criticals: {result.criticalCount}",
$"Max Combo: {result.maxCombo}",
};
_statsText.text = "";
foreach (var line in lines)
{
_statsText.text += line + "\n";
yield return new WaitForSecondsRealtime(statLineInterval);
}
}
private IEnumerator PunchScale(RectTransform rect, float duration, float punchSize)
{
Vector3 baseScale = Vector3.one;
Vector3 punchScale = baseScale * punchSize;
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.unscaledDeltaTime;
float t = elapsed / duration;
float ease = 1f - Mathf.Pow(2f, -10f * t) * Mathf.Cos(t * Mathf.PI * 3f);
rect.localScale = Vector3.LerpUnclamped(punchScale, baseScale, ease);
yield return null;
}
rect.localScale = baseScale;
}
private string FormatTime(float seconds)
{
int min = Mathf.FloorToInt(seconds / 60f);
float sec = seconds % 60f;
return min > 0 ? $"{min}m {sec:F1}s" : $"{sec:F1}s";
}
private void CreateUI()
{
var canvasObj = new GameObject("BossRaid_VictoryScreen");
canvasObj.transform.SetParent(transform);
_canvas = canvasObj.AddComponent<Canvas>();
_canvas.renderMode = RenderMode.ScreenSpaceOverlay;
_canvas.sortingOrder = 200;
_canvasGroup = canvasObj.AddComponent<CanvasGroup>();
_canvasGroup.interactable = false;
_canvasGroup.blocksRaycasts = false;
var scaler = canvasObj.AddComponent<CanvasScaler>();
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
scaler.referenceResolution = new Vector2(1920, 1080);
// 배경
var bgObj = new GameObject("Victory_BG");
bgObj.transform.SetParent(canvasObj.transform, false);
var bgRect = bgObj.AddComponent<RectTransform>();
bgRect.anchorMin = Vector2.zero;
bgRect.anchorMax = Vector2.one;
bgRect.offsetMin = Vector2.zero;
bgRect.offsetMax = Vector2.zero;
var bgImg = bgObj.AddComponent<Image>();
bgImg.color = new Color(0f, 0f, 0f, 0.5f);
bgImg.raycastTarget = false;
// 타이틀
var titleObj = new GameObject("Victory_Title");
titleObj.transform.SetParent(canvasObj.transform, false);
var titleRect = titleObj.AddComponent<RectTransform>();
titleRect.anchorMin = new Vector2(0.1f, 0.55f);
titleRect.anchorMax = new Vector2(0.9f, 0.85f);
titleRect.offsetMin = Vector2.zero;
titleRect.offsetMax = Vector2.zero;
_titleText = titleObj.AddComponent<Text>();
_titleText.fontSize = 80;
_titleText.color = titleColor;
_titleText.alignment = TextAnchor.MiddleCenter;
_titleText.fontStyle = FontStyle.Bold;
_titleText.raycastTarget = false;
if (_font != null) _titleText.font = _font;
var titleOutline = titleObj.AddComponent<Outline>();
titleOutline.effectColor = Color.black;
titleOutline.effectDistance = new Vector2(3f, -3f);
// 스탯
var statsObj = new GameObject("Victory_Stats");
statsObj.transform.SetParent(canvasObj.transform, false);
var statsRect = statsObj.AddComponent<RectTransform>();
statsRect.anchorMin = new Vector2(0.25f, 0.1f);
statsRect.anchorMax = new Vector2(0.75f, 0.55f);
statsRect.offsetMin = Vector2.zero;
statsRect.offsetMax = Vector2.zero;
_statsText = statsObj.AddComponent<Text>();
_statsText.fontSize = 28;
_statsText.color = statValueColor;
_statsText.alignment = TextAnchor.UpperCenter;
_statsText.lineSpacing = 1.5f;
_statsText.raycastTarget = false;
if (_font != null) _statsText.font = _font;
var statsOutline = statsObj.AddComponent<Outline>();
statsOutline.effectColor = new Color(0f, 0f, 0f, 0.8f);
statsOutline.effectDistance = new Vector2(1f, -1f);
}
#endregion
}
}