191 lines
6.8 KiB
C#
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
|
|
}
|
|
}
|