Files
Travel_Run/Assets/Scripts/Flow/Screens/ResultScreenView.cs
T
2026-07-09 02:50:48 +09:00

378 lines
18 KiB
C#

using TMPro;
using UnityEngine;
using UnityEngine.UI;
public partial class GameFlowManager {
private void ShowResult() {
if(TryLoadFlowScene(ResultSceneName))
{
return;
}
EnsureOverlay();
ClearOverlay();
SetOverlayVisible(true);
BuildResultScreen();
}
private void BuildResultScreen() {
ApplyResultAirportBackground();
MapDefinition resultMap = completedMap != null ? completedMap : currentMap;
int rewardMileage = lastResultCleared && resultMap != null ? resultMap.clearMileageReward : 0;
int gainedMileage = Mathf.Max(0, lastResultMileage) + rewardMileage;
int targetDistance = resultMap != null ? Mathf.FloorToInt(resultMap.targetDistance) : 0;
int shownDistance = targetDistance > 0
? Mathf.Clamp(Mathf.FloorToInt(lastResultDistance), 0, targetDistance)
: Mathf.Max(0, Mathf.FloorToInt(lastResultDistance));
RectTransform passportRect = AddResultPassportPanel();
AddResultHeader(passportRect, resultMap);
AddResultStats(passportRect, gainedMileage, shownDistance, targetDistance);
AddResultTickets(passportRect, resultMap, rewardMileage);
if(lastResultCleared)
{
AddResultActionButton("면세점으로", ShowDutyFreeShop, new Vector2(-166f, -282f), new Vector2(250f, 48f), true, LoadUiSprite("", DutyFreeIconAssetPath));
AddResultActionButton("다음 여행지 가기", ShowMapPreview, new Vector2(160f, -282f), new Vector2(292f, 48f), false, LoadUiSprite("", AirplaneTravelIconAssetPath));
}
else
{
AddResultActionButton("다시 도전", RetryCurrentMap, new Vector2(-166f, -282f), new Vector2(250f, 48f), true, LoadUiSprite("", CheckpointIconAssetPath));
AddResultActionButton("다음 여행지 가기", ShowMapPreview, new Vector2(160f, -282f), new Vector2(292f, 48f), false, LoadUiSprite("", AirplaneTravelIconAssetPath));
}
}
private void ApplyResultAirportBackground() {
if(overlayBackground != null)
{
overlayBackground.sprite = LoadUiSprite(ResultAirportBackgroundResourcePath, "Assets/Resources/Map_Tutorial_Incheon_Airport.png");
overlayBackground.preserveAspect = false;
overlayBackground.color = overlayBackground.sprite != null
? Color.white
: new Color(0.008f, 0.024f, 0.034f, 0.96f);
}
if(flowCamera != null)
{
flowCamera.backgroundColor = new Color(0.006f, 0.022f, 0.035f, 1f);
}
GameObject scrimObject = CreateUiObject("Result Airport Background Scrim", overlayRoot, typeof(Image));
RectTransform scrimRect = scrimObject.GetComponent<RectTransform>();
scrimRect.anchorMin = Vector2.zero;
scrimRect.anchorMax = Vector2.one;
scrimRect.offsetMin = Vector2.zero;
scrimRect.offsetMax = Vector2.zero;
Image scrimImage = scrimObject.GetComponent<Image>();
scrimImage.color = new Color(0.005f, 0.015f, 0.020f, 0.30f);
scrimImage.raycastTarget = false;
}
private RectTransform AddResultPassportPanel() {
GameObject panelObject = CreateUiObject("Result Passport Page", overlayRoot, typeof(Image));
RectTransform panelRect = panelObject.GetComponent<RectTransform>();
panelRect.anchorMin = new Vector2(0.5f, 0.5f);
panelRect.anchorMax = new Vector2(0.5f, 0.5f);
panelRect.pivot = new Vector2(0.5f, 0.5f);
panelRect.anchoredPosition = new Vector2(0f, 38f);
panelRect.sizeDelta = new Vector2(1092f, 330f);
Image panelImage = panelObject.GetComponent<Image>();
panelImage.sprite = LoadUiSprite(ResultPassportPanelResourcePath, ResultPassportPanelAssetPath);
panelImage.color = panelImage.sprite != null
? Color.white
: new Color(0.95f, 0.91f, 0.80f, 0.98f);
panelImage.preserveAspect = true;
panelImage.raycastTarget = false;
return panelRect;
}
private void AddResultHeader(RectTransform parent, MapDefinition resultMap) {
Sprite rankSprite = LoadUiSprite("", ClearRankIconAssetPath);
AddResultImage(parent, "Result Rank Badge", rankSprite, new Vector2(150f, -140f), new Vector2(48f, 48f), true, Color.white);
string title = lastResultCleared ? "출국 성공" : "일정 실패";
Color titleColor = lastResultCleared
? new Color(0.05f, 0.17f, 0.27f, 1f)
: new Color(0.52f, 0.08f, 0.07f, 1f);
AddResultCenteredText(parent, "Result Title", title, new Vector2(244f, -140f), new Vector2(220f, 50f), 25f, FontStyles.Bold, titleColor, TextAlignmentOptions.Center);
AddResultRouteBox(parent, "From", GetResultOriginAirportCode(resultMap), GetResultOriginCityName(resultMap), new Vector2(440f, -122f));
AddResultRouteBox(parent, "To", GetResultDestinationAirportCode(resultMap), GetResultDestinationCityName(resultMap), new Vector2(660f, -122f));
AddResultBoardingField(parent, "Flight", "항공편", GetResultFlightName(resultMap), new Vector2(400f, -253f));
AddResultBoardingField(parent, "Seat", "좌석", GetResultSeatName(resultMap), new Vector2(497f, -253f));
AddResultBoardingField(parent, "Boarding", "탑승", System.DateTime.Now.ToString("HH:mm"), new Vector2(595f, -253f));
AddResultBoardingField(parent, "Class", "클래스", lastResultCleared ? "일반석" : "대기", new Vector2(695f, -253f));
}
private void AddResultStats(RectTransform parent, int gainedMileage, int shownDistance, int targetDistance) {
AddResultStat(parent, "Mileage", LoadUiSprite("", MileageIconAssetPath), "마일리지", "+" + gainedMileage, new Vector2(812f, -140f));
AddResultStat(parent, "Time", LoadUiSprite("", TimerIconAssetPath), "도착 시간", lastResultTime.ToString("0.0") + "s", new Vector2(903f, -140f));
string distance = targetDistance > 0
? shownDistance + "/" + targetDistance + "m"
: shownDistance + "m";
AddResultStat(parent, "Distance", LoadUiSprite("", CheckpointIconAssetPath), "이동 거리", distance, new Vector2(993f, -140f));
}
private void AddResultTickets(RectTransform parent, MapDefinition resultMap, int rewardMileage) {
AddResultTicket(
parent,
"Destination",
LoadUiSprite("", CheckpointIconAssetPath),
"목적지",
GetResultDestinationCityName(resultMap),
new Vector2(812f, -251f));
AddResultTicket(
parent,
"Souvenir",
lastResultCleared ? GetResultSouvenirSprite(resultMap) : LoadUiSprite("", SouvenirCollectionIconAssetPath),
"보상",
lastResultCleared ? GetResultSouvenirName(resultMap) : "다음 도전",
new Vector2(900f, -251f));
AddResultTicket(
parent,
"Total Mileage",
LoadUiSprite("", MileageIconAssetPath),
"보유",
saveData.totalMileage + " M",
new Vector2(991f, -251f));
}
private void AddResultStat(RectTransform parent, string objectName, Sprite iconSprite, string label, string value, Vector2 centerPosition) {
AddResultImage(parent, "Result " + objectName + " Icon", iconSprite, centerPosition + new Vector2(0f, 5f), new Vector2(26f, 26f), true, Color.white);
AddResultCenteredText(parent, "Result " + objectName + " Value", value, centerPosition + new Vector2(0f, -17f), new Vector2(90f, 22f), 12f, FontStyles.Bold, new Color(0.05f, 0.17f, 0.25f, 1f), TextAlignmentOptions.Center);
AddResultCenteredText(parent, "Result " + objectName + " Label", label, centerPosition + new Vector2(0f, -32f), new Vector2(90f, 16f), 8f, FontStyles.Bold, new Color(0.42f, 0.58f, 0.64f, 0.92f), TextAlignmentOptions.Center);
}
private void AddResultTicket(RectTransform parent, string objectName, Sprite iconSprite, string label, string value, Vector2 centerPosition) {
AddResultImage(parent, "Result " + objectName + " Icon", iconSprite, centerPosition + new Vector2(0f, 27f), new Vector2(34f, 34f), true, Color.white);
AddResultCenteredText(parent, "Result " + objectName + " Label", label, centerPosition + new Vector2(0f, -9f), new Vector2(110f, 18f), 11f, FontStyles.Bold, new Color(0.43f, 0.58f, 0.64f, 0.96f), TextAlignmentOptions.Center);
AddResultCenteredText(parent, "Result " + objectName + " Value", value, centerPosition + new Vector2(0f, -35f), new Vector2(118f, 26f), 11f, FontStyles.Bold, new Color(0.05f, 0.18f, 0.27f, 1f), TextAlignmentOptions.Center);
}
private void AddResultRouteBox(RectTransform parent, string objectName, string code, string cityName, Vector2 centerPosition) {
AddResultCenteredText(parent, "Result " + objectName + " Airport Code", code, centerPosition + new Vector2(0f, 7f), new Vector2(150f, 48f), 34f, FontStyles.Bold, new Color(0.05f, 0.17f, 0.27f, 1f), TextAlignmentOptions.Center);
AddResultCenteredText(parent, "Result " + objectName + " City", cityName, centerPosition + new Vector2(0f, -30f), new Vector2(160f, 22f), 12f, FontStyles.Bold, new Color(0.43f, 0.58f, 0.64f, 0.96f), TextAlignmentOptions.Center);
}
private void AddResultBoardingField(RectTransform parent, string objectName, string label, string value, Vector2 centerPosition) {
AddResultCenteredText(parent, "Result " + objectName + " Label", label, centerPosition + new Vector2(0f, 13f), new Vector2(104f, 17f), 9f, FontStyles.Bold, new Color(0.43f, 0.58f, 0.64f, 0.96f), TextAlignmentOptions.Center);
AddResultCenteredText(parent, "Result " + objectName + " Value", value, centerPosition + new Vector2(0f, -12f), new Vector2(108f, 28f), 14f, FontStyles.Bold, new Color(0.05f, 0.18f, 0.27f, 1f), TextAlignmentOptions.Center);
}
private void AddResultActionButton(string label, UnityEngine.Events.UnityAction action, Vector2 position, Vector2 size, bool primary, Sprite iconSprite) {
GameObject buttonObject = CreateUiObject("Result Button " + label, overlayRoot, typeof(Image), typeof(Button));
RectTransform buttonRect = buttonObject.GetComponent<RectTransform>();
buttonRect.anchorMin = new Vector2(0.5f, 0.5f);
buttonRect.anchorMax = new Vector2(0.5f, 0.5f);
buttonRect.pivot = new Vector2(0.5f, 0.5f);
buttonRect.anchoredPosition = position;
buttonRect.sizeDelta = size;
Image buttonImage = buttonObject.GetComponent<Image>();
buttonImage.sprite = LoadUiSprite(ResultButtonResourcePath, ResultButtonAssetPath);
buttonImage.color = buttonImage.sprite != null
? (primary ? Color.white : new Color(0.86f, 0.94f, 1f, 0.94f))
: primary
? new Color(1f, 0.82f, 0.28f, 0.98f)
: new Color(0.82f, 0.91f, 0.96f, 0.90f);
buttonImage.preserveAspect = false;
buttonImage.raycastTarget = true;
Button button = buttonObject.GetComponent<Button>();
button.onClick.AddListener(action);
if(iconSprite != null)
{
AddResultImage(buttonRect, "Result Button Icon", iconSprite, new Vector2(34f, -(size.y * 0.5f)), new Vector2(24f, 24f), true, Color.white);
}
TextMeshProUGUI buttonText = AddResultText(buttonRect, "Result Button Label", label, new Vector2(iconSprite != null ? 54f : 0f, -1f), new Vector2(iconSprite != null ? size.x - 70f : size.x, size.y), 16f, FontStyles.Bold, new Color(0.94f, 0.99f, 1f, 1f), TextAlignmentOptions.Center);
RectTransform textRect = buttonText.rectTransform;
textRect.anchorMin = new Vector2(0f, 0.5f);
textRect.anchorMax = new Vector2(0f, 0.5f);
textRect.pivot = new Vector2(0f, 0.5f);
buttonText.outlineColor = new Color(0f, 0.04f, 0.07f, 0.98f);
buttonText.outlineWidth = 0.12f;
}
private Image AddResultImage(RectTransform parent, string objectName, Sprite sprite, Vector2 position, Vector2 size, bool preserveAspect, Color color) {
GameObject imageObject = CreateUiObject(objectName, parent, typeof(Image));
RectTransform imageRect = imageObject.GetComponent<RectTransform>();
imageRect.anchorMin = new Vector2(0f, 1f);
imageRect.anchorMax = new Vector2(0f, 1f);
imageRect.pivot = new Vector2(0.5f, 0.5f);
imageRect.anchoredPosition = position;
imageRect.sizeDelta = size;
Image image = imageObject.GetComponent<Image>();
image.sprite = sprite;
image.color = sprite != null ? color : new Color(0.30f, 0.46f, 0.54f, 0.28f);
image.preserveAspect = preserveAspect;
image.raycastTarget = false;
return image;
}
private TextMeshProUGUI AddResultText(RectTransform parent, string objectName, string text, Vector2 position, Vector2 size, float fontSize, FontStyles fontStyle, Color color, TextAlignmentOptions alignment) {
GameObject textObject = CreateUiObject(objectName, parent);
RectTransform textRect = textObject.GetComponent<RectTransform>();
textRect.anchorMin = new Vector2(0f, 1f);
textRect.anchorMax = new Vector2(0f, 1f);
textRect.pivot = new Vector2(0f, 1f);
textRect.anchoredPosition = position;
textRect.sizeDelta = size;
TextMeshProUGUI textComponent = textObject.AddComponent<TextMeshProUGUI>();
textComponent.text = text;
textComponent.font = runtimeFont != null ? runtimeFont : textComponent.font;
textComponent.fontSize = fontSize;
textComponent.fontStyle = fontStyle;
textComponent.alignment = alignment;
textComponent.color = color;
textComponent.raycastTarget = false;
textComponent.textWrappingMode = TextWrappingModes.Normal;
textComponent.overflowMode = TextOverflowModes.Ellipsis;
textComponent.enableAutoSizing = true;
textComponent.fontSizeMin = Mathf.Max(8f, fontSize * 0.66f);
textComponent.fontSizeMax = fontSize;
return textComponent;
}
private TextMeshProUGUI AddResultCenteredText(RectTransform parent, string objectName, string text, Vector2 centerPosition, Vector2 size, float fontSize, FontStyles fontStyle, Color color, TextAlignmentOptions alignment) {
Vector2 topLeftPosition = centerPosition + new Vector2(-size.x * 0.5f, size.y * 0.5f);
return AddResultText(parent, objectName, text, topLeftPosition, size, fontSize, fontStyle, color, alignment);
}
private string GetResultOriginAirportCode(MapDefinition resultMap) {
return GetAirportCode(GetResultOriginMapId(resultMap));
}
private string GetResultDestinationAirportCode(MapDefinition resultMap) {
return GetAirportCode(GetResultDestinationMapId(resultMap));
}
private string GetResultOriginCityName(MapDefinition resultMap) {
return GetAirportCityName(GetResultOriginMapId(resultMap));
}
private string GetResultDestinationCityName(MapDefinition resultMap) {
return GetAirportCityName(GetResultDestinationMapId(resultMap));
}
private MapId GetResultOriginMapId(MapDefinition resultMap) {
if(resultMap == null)
{
return MapId.TutorialIncheon;
}
return resultMap.mapId;
}
private MapId GetResultDestinationMapId(MapDefinition resultMap) {
if(resultMap == null)
{
return MapId.Japan;
}
if(resultMap.hasNextMap)
{
return resultMap.nextMapId;
}
return resultMap.mapId;
}
private string GetAirportCode(MapId mapId) {
switch(mapId)
{
case MapId.TutorialIncheon:
return "ICN";
case MapId.Japan:
return "FUK";
case MapId.China:
return "PVG";
case MapId.America:
return "LAX";
default:
return "TRP";
}
}
private string GetAirportCityName(MapId mapId) {
switch(mapId)
{
case MapId.TutorialIncheon:
return "인천공항";
case MapId.Japan:
return "후쿠오카";
case MapId.China:
return "상하이";
case MapId.America:
return "로스앤젤레스";
default:
return "여행지";
}
}
private string GetResultFlightName(MapDefinition resultMap) {
int mapNumber = resultMap != null ? (int)resultMap.mapId + 1 : 1;
return "UNR-" + mapNumber.ToString("000");
}
private string GetResultSeatName(MapDefinition resultMap) {
int mapNumber = resultMap != null ? (int)resultMap.mapId + 1 : 1;
return (10 + mapNumber).ToString() + "A";
}
private string GetResultSouvenirName(MapDefinition resultMap) {
if(resultMap == null)
{
return "여행 도장";
}
switch(resultMap.mapId)
{
case MapId.TutorialIncheon:
return "공항 마그넷";
case MapId.Japan:
return "일본 마그넷";
case MapId.China:
return "여행 부적";
case MapId.America:
return "스카이라인";
default:
return "여행 도장";
}
}
private Sprite GetResultSouvenirSprite(MapDefinition resultMap) {
if(resultMap == null)
{
return LoadUiSprite("", SouvenirCollectionIconAssetPath);
}
switch(resultMap.mapId)
{
case MapId.TutorialIncheon:
return LoadUiSprite("", AirportSouvenirAssetPath);
case MapId.Japan:
return LoadUiSprite("", JapanSouvenirAssetPath);
case MapId.China:
return LoadUiSprite("", ChinaSouvenirAssetPath);
case MapId.America:
return LoadUiSprite("", AmericaSouvenirAssetPath);
default:
return LoadUiSprite("", SouvenirCollectionIconAssetPath);
}
}
}