Add duty free systems and travel stage updates

This commit is contained in:
jongjae0305
2026-07-09 02:50:48 +09:00
parent 445d74d462
commit 750e9ce0a6
340 changed files with 21825 additions and 1197 deletions
File diff suppressed because it is too large Load Diff
+21 -4
View File
@@ -1,15 +1,27 @@
using System;
public enum DutyFreeItemType {
None = 0,
Lunchbox = 1,
MileageCard = 4,
Supplement = 5
}
[Serializable]
public class GameSaveData {
public int currentMapIndex;
public int unlockedMapIndex;
public int totalMileage;
public int bagSlots;
public int shieldStock;
public int lunchboxStock;
public int speedShoesStock;
public int mileageCardStock;
public int supplementPurchases;
public int dutyFreeLimitStageIndex;
public bool purchasedMileageCardThisStage;
public bool purchasedSupplementThisStage;
public DutyFreeItemType equippedSlot1;
public DutyFreeItemType equippedSlot2;
public DutyFreeItemType equippedSlot3;
public int bestScore;
public static GameSaveData CreateDefault() {
@@ -18,10 +30,15 @@ public class GameSaveData {
unlockedMapIndex = 0,
totalMileage = 0,
bagSlots = 1,
shieldStock = 0,
lunchboxStock = 0,
speedShoesStock = 0,
mileageCardStock = 0,
supplementPurchases = 0,
dutyFreeLimitStageIndex = -1,
purchasedMileageCardThisStage = false,
purchasedSupplementThisStage = false,
equippedSlot1 = DutyFreeItemType.None,
equippedSlot2 = DutyFreeItemType.None,
equippedSlot3 = DutyFreeItemType.None,
bestScore = 0
};
}
+140 -2
View File
@@ -66,10 +66,148 @@ public static class GameSaveManager {
saveData.currentMapIndex = Mathf.Min(saveData.currentMapIndex, saveData.unlockedMapIndex);
saveData.totalMileage = Mathf.Max(0, saveData.totalMileage);
saveData.bagSlots = Mathf.Clamp(saveData.bagSlots, 1, 3);
saveData.shieldStock = Mathf.Max(0, saveData.shieldStock);
saveData.lunchboxStock = Mathf.Max(0, saveData.lunchboxStock);
saveData.speedShoesStock = Mathf.Max(0, saveData.speedShoesStock);
saveData.mileageCardStock = Mathf.Max(0, saveData.mileageCardStock);
saveData.supplementPurchases = Mathf.Clamp(saveData.supplementPurchases, 0, 4);
saveData.dutyFreeLimitStageIndex = saveData.dutyFreeLimitStageIndex < 0
? -1
: Mathf.Clamp(saveData.dutyFreeLimitStageIndex, 0, MapDatabase.LastMapIndex);
NormalizeEquippedItems(saveData);
NormalizeDutyFreeStockCapacity(saveData);
NormalizeEquippedItems(saveData);
saveData.bestScore = Mathf.Max(0, saveData.bestScore);
}
private static void NormalizeDutyFreeStockCapacity(GameSaveData saveData) {
int bagSlots = Mathf.Clamp(saveData.bagSlots, 1, 3);
int equippedLunchboxes = CountEquippedItem(saveData, DutyFreeItemType.Lunchbox, bagSlots);
int equippedMileageCards = CountEquippedItem(saveData, DutyFreeItemType.MileageCard, bagSlots);
saveData.lunchboxStock = Mathf.Max(equippedLunchboxes, Mathf.Min(saveData.lunchboxStock, bagSlots));
saveData.mileageCardStock = Mathf.Max(equippedMileageCards, Mathf.Min(saveData.mileageCardStock, bagSlots));
while(saveData.lunchboxStock + saveData.mileageCardStock > bagSlots)
{
if(saveData.mileageCardStock > equippedMileageCards)
{
saveData.mileageCardStock--;
}
else if(saveData.lunchboxStock > equippedLunchboxes)
{
saveData.lunchboxStock--;
}
else
{
break;
}
}
}
private static int CountEquippedItem(GameSaveData saveData, DutyFreeItemType itemType, int bagSlots) {
int count = 0;
for(int i = 0; i < bagSlots; i++)
{
if(GetEquippedSlot(saveData, i) == itemType)
{
count++;
}
}
return count;
}
private static void NormalizeEquippedItems(GameSaveData saveData) {
int bagSlots = Mathf.Clamp(saveData.bagSlots, 1, 3);
if(bagSlots < 3)
{
saveData.equippedSlot3 = DutyFreeItemType.None;
}
if(bagSlots < 2)
{
saveData.equippedSlot2 = DutyFreeItemType.None;
}
saveData.equippedSlot1 = NormalizeItemType(saveData.equippedSlot1);
saveData.equippedSlot2 = NormalizeItemType(saveData.equippedSlot2);
saveData.equippedSlot3 = NormalizeItemType(saveData.equippedSlot3);
int lunchboxCount = 0;
int mileageCardCount = 0;
ClampEquippedSlot(saveData, 0, ref lunchboxCount, ref mileageCardCount);
ClampEquippedSlot(saveData, 1, ref lunchboxCount, ref mileageCardCount);
ClampEquippedSlot(saveData, 2, ref lunchboxCount, ref mileageCardCount);
}
private static DutyFreeItemType NormalizeItemType(DutyFreeItemType itemType) {
switch(itemType)
{
case DutyFreeItemType.Lunchbox:
case DutyFreeItemType.MileageCard:
return itemType;
default:
return DutyFreeItemType.None;
}
}
private static void ClampEquippedSlot(
GameSaveData saveData,
int slotIndex,
ref int lunchboxCount,
ref int mileageCardCount) {
DutyFreeItemType itemType = GetEquippedSlot(saveData, slotIndex);
if(itemType == DutyFreeItemType.None)
{
return;
}
bool overStock = false;
switch(itemType)
{
case DutyFreeItemType.Lunchbox:
overStock = lunchboxCount >= saveData.lunchboxStock;
lunchboxCount++;
break;
case DutyFreeItemType.MileageCard:
overStock = mileageCardCount >= saveData.mileageCardStock;
mileageCardCount++;
break;
}
if(overStock)
{
SetEquippedSlot(saveData, slotIndex, DutyFreeItemType.None);
}
}
private static DutyFreeItemType GetEquippedSlot(GameSaveData saveData, int slotIndex) {
switch(slotIndex)
{
case 0:
return saveData.equippedSlot1;
case 1:
return saveData.equippedSlot2;
case 2:
return saveData.equippedSlot3;
default:
return DutyFreeItemType.None;
}
}
private static void SetEquippedSlot(GameSaveData saveData, int slotIndex, DutyFreeItemType itemType) {
switch(slotIndex)
{
case 0:
saveData.equippedSlot1 = itemType;
break;
case 1:
saveData.equippedSlot2 = itemType;
break;
case 2:
saveData.equippedSlot3 = itemType;
break;
}
}
}
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 55433eabfe544a199c2b2899e3256b3b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,178 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public partial class GameFlowManager {
#if UNITY_EDITOR || DEVELOPMENT_BUILD
private void ShowDebugMenu() {
EnsureDebugPreviewData();
gameplayActive = false;
pendingStartGameplay = false;
currentScreen = FlowScreen.DebugMenu;
EnsureOverlay();
ClearOverlay();
SetOverlayVisible(true);
SetDefaultOverlayBackground();
AddTitle("디버그 메뉴");
AddBody("기본 화면과 실전맵을 바로 확인합니다.\n단축키: 1~0, F1/F2");
AddDebugButton("1. 인트로", ShowDebugIntroPreview, new Vector2(-235f, -32f));
AddDebugButton("2. 현재 맵 시작", ShowDebugGameStartPreview, new Vector2(-235f, -74f));
AddDebugButton("3. 현재 출국 실패", delegate { ShowDebugResultPreview(false); }, new Vector2(-235f, -116f));
AddDebugButton("4. 현재 출국 성공", delegate { ShowDebugResultPreview(true); }, new Vector2(-235f, -158f));
AddDebugButton("5. 면세점", ShowDebugDutyFreeShopPreview, new Vector2(-235f, -200f));
AddDebugButton("6. 지도", ShowDebugMapPreview, new Vector2(-235f, -242f));
AddDebugButton("7. 일본 게임시작", delegate { ShowDebugMapGameStartPreview(MapId.Japan); }, new Vector2(235f, -32f));
AddDebugButton("8. 일본 출국성공", delegate { ShowDebugMapResultPreview(MapId.Japan, true); }, new Vector2(235f, -74f));
AddDebugButton("9. 중국 게임시작", delegate { ShowDebugMapGameStartPreview(MapId.China); }, new Vector2(235f, -116f));
AddDebugButton("0. 중국 출국성공", delegate { ShowDebugMapResultPreview(MapId.China, true); }, new Vector2(235f, -158f));
AddDebugButton("F1. 미국 게임시작", delegate { ShowDebugMapGameStartPreview(MapId.America); }, new Vector2(235f, -200f));
AddDebugButton("F2. 미국 출국성공", delegate { ShowDebugMapResultPreview(MapId.America, true); }, new Vector2(235f, -242f));
}
private void AddDebugButton(string label, UnityEngine.Events.UnityAction action, Vector2 position) {
GameObject buttonObject = CreateUiObject("Debug 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 = new Vector2(310f, 34f);
Image buttonImage = buttonObject.GetComponent<Image>();
buttonImage.color = new Color(0.92f, 0.96f, 1f, 0.94f);
buttonImage.raycastTarget = true;
Button button = buttonObject.GetComponent<Button>();
button.targetGraphic = buttonImage;
button.navigation = new Navigation {
mode = Navigation.Mode.None
};
button.onClick.AddListener(action);
TextMeshProUGUI buttonText = AddTextTo(buttonObject.transform, "Label", label, 14f, FontStyles.Bold);
RectTransform textRect = buttonText.rectTransform;
textRect.anchorMin = Vector2.zero;
textRect.anchorMax = Vector2.one;
textRect.offsetMin = Vector2.zero;
textRect.offsetMax = Vector2.zero;
buttonText.color = new Color(0.04f, 0.07f, 0.09f, 1f);
}
private void ShowDebugIntroPreview() {
ShowIntro();
}
private void ShowDebugGameStartPreview() {
EnsureDebugPreviewData();
LoadGameSceneForCurrentMap();
}
private void ShowDebugMapGameStartPreview(MapId mapId) {
SetDebugCurrentMap(mapId);
LoadGameSceneForCurrentMap();
}
private void ShowDebugResultPreview(bool cleared) {
EnsureDebugPreviewData();
gameplayActive = false;
pendingStartGameplay = false;
currentScreen = FlowScreen.Result;
completedMap = currentMap;
lastResultCleared = cleared;
lastResultScore = cleared ? 12800 : 7200;
lastResultMileage = cleared ? 263 : 84;
lastResultTime = cleared ? 23.9f : 38.4f;
lastResultDistance = completedMap != null
? (cleared ? completedMap.targetDistance : completedMap.targetDistance * 0.62f)
: 380f;
if(saveData != null)
{
saveData.totalMileage = Mathf.Max(saveData.totalMileage, 4120);
}
ShowResult();
}
private void ShowDebugMapResultPreview(MapId mapId, bool cleared) {
SetDebugCurrentMap(mapId);
gameplayActive = false;
pendingStartGameplay = false;
currentScreen = FlowScreen.Result;
completedMap = currentMap;
lastResultCleared = cleared;
int mapIndex = MapDatabase.GetIndex(mapId);
lastResultScore = cleared ? 12800 + (mapIndex * 2200) : 7200 + (mapIndex * 900);
lastResultMileage = cleared ? 190 + (mapIndex * 70) : 84;
lastResultTime = currentMap != null
? Mathf.Max(10f, currentMap.timeLimit * (cleared ? 0.78f : 1.08f))
: cleared ? 23.9f : 38.4f;
lastResultDistance = currentMap != null
? (cleared ? currentMap.targetDistance : currentMap.targetDistance * 0.62f)
: 380f;
if(saveData != null)
{
saveData.totalMileage = Mathf.Max(saveData.totalMileage, 4120);
}
ShowResult();
}
private void ShowDebugDutyFreeShopPreview() {
EnsureDebugPreviewData();
if(saveData != null)
{
saveData.totalMileage = Mathf.Max(saveData.totalMileage, 4120);
}
ShowDutyFreeShop();
}
private void ShowDebugMapPreview() {
EnsureDebugPreviewData();
ShowMapPreview();
}
private void SetDebugCurrentMap(MapId mapId) {
EnsureDebugPreviewData();
currentMap = MapDatabase.GetMap(mapId);
if(saveData == null)
{
return;
}
int mapIndex = MapDatabase.GetIndex(mapId);
saveData.currentMapIndex = mapIndex;
saveData.unlockedMapIndex = Mathf.Max(saveData.unlockedMapIndex, mapIndex);
GameSaveManager.Save(saveData);
}
private void EnsureDebugPreviewData() {
if(saveData == null)
{
saveData = GameSaveManager.Load();
}
if(currentMap == null)
{
currentMap = MapDatabase.GetMapByIndex(saveData != null ? saveData.currentMapIndex : 0);
}
if(currentMap == null)
{
currentMap = MapDatabase.GetMapByIndex(0);
}
}
#endif
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dc38b07e718f43dda9e26895c85dbf3f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,390 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public partial class GameFlowManager {
private void ShowDutyFreeShop() {
currentScreen = FlowScreen.DutyFreeShop;
gameplayActive = false;
pendingStartGameplay = false;
if(TryLoadFlowScene(DutyFreeShopSceneName))
{
return;
}
EnsureOverlay();
ClearOverlay();
SetOverlayVisible(true);
BuildDutyFreeShopScreen();
}
private void BuildDutyFreeShopScreen() {
EnsureDutyFreeStagePurchaseLimits();
ApplyDutyFreeShopBackground();
RectTransform boardRect = AddDutyFreeBoard();
AddDutyFreeHeader(boardRect);
AddDutyFreeItemCard(
boardRect,
"도시락",
DutyFreeItemType.Lunchbox,
LunchboxCost,
saveData.lunchboxStock,
LoadUiSprite("", DutyFreeLunchboxAssetPath),
BuyLunchbox,
new Vector2(75f, -135f));
AddDutyFreeSupplementCard(
boardRect,
"영양제",
SupplementCost,
saveData.supplementPurchases,
LoadUiSprite("", DutyFreeSupplementAssetPath),
BuySupplement,
new Vector2(303f, -135f));
AddDutyFreeItemCard(
boardRect,
"마일리지 카드",
DutyFreeItemType.MileageCard,
MileageCardCost,
saveData.mileageCardStock,
LoadUiSprite("", DutyFreeMileageCardAssetPath),
BuyMileageCard,
new Vector2(760f, -135f));
AddDutyFreeNextTravelButton();
}
private void ApplyDutyFreeShopBackground() {
if(overlayBackground != null)
{
overlayBackground.sprite = null;
overlayBackground.preserveAspect = false;
overlayBackground.color = new Color(0.018f, 0.041f, 0.052f, 0.98f);
}
if(flowCamera != null)
{
flowCamera.backgroundColor = new Color(0.018f, 0.041f, 0.052f, 1f);
}
AddDutyFreeBackdropImage(
"Duty Free Shop Interior",
LoadUiSprite(DutyFreeBackgroundResourcePath, DutyFreeBackgroundAssetPath),
Vector2.zero,
new Vector2(1378f, 724f),
true,
Color.white);
GameObject scrimObject = CreateUiObject("Duty Free 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.01f, 0.012f, 0.014f, 0.22f);
scrimImage.raycastTarget = false;
}
private Image AddDutyFreeBackdropImage(string objectName, Sprite sprite, Vector2 position, Vector2 size, bool preserveAspect, Color color) {
GameObject imageObject = CreateUiObject(objectName, overlayRoot, typeof(Image));
RectTransform imageRect = imageObject.GetComponent<RectTransform>();
imageRect.anchorMin = new Vector2(0.5f, 0.5f);
imageRect.anchorMax = new Vector2(0.5f, 0.5f);
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 RectTransform AddDutyFreeBoard() {
GameObject boardObject = CreateUiObject("Duty Free Product Board", overlayRoot, typeof(Image));
RectTransform boardRect = boardObject.GetComponent<RectTransform>();
boardRect.anchorMin = new Vector2(0.5f, 0.5f);
boardRect.anchorMax = new Vector2(0.5f, 0.5f);
boardRect.pivot = new Vector2(0.5f, 0.5f);
boardRect.anchoredPosition = new Vector2(0f, 20f);
boardRect.sizeDelta = new Vector2(1038f, 552f);
Image boardImage = boardObject.GetComponent<Image>();
boardImage.sprite = LoadUiSprite(DutyFreeWindowPanelResourcePath, DutyFreeWindowPanelAssetPath);
boardImage.color = boardImage.sprite != null
? Color.white
: new Color(0.92f, 0.98f, 1f, 0.78f);
boardImage.preserveAspect = false;
boardImage.raycastTarget = false;
return boardRect;
}
private void AddDutyFreeHeader(RectTransform parent) {
AddResultImage(parent, "Duty Free Equip Slots Panel", LoadUiSprite(DutyFreeEquipSlotPanelResourcePath, "Assets/Resources/UI_DutyFreeBagSlotPanel.png"), new Vector2(50f, -570f), new Vector2(276f, 124f), true, Color.white);
for(int i = 0; i < 3; i++)
{
AddDutyFreeEquipSlot(parent, i, new Vector2(-65f + (i * 82f), -540f));
}
AddDutyFreeBagUpgradeButton(parent, new Vector2(190f, -560f));
AddResultImage(parent, "Duty Free Mileage Price Tag", LoadDutyFreeResourceSprite(DutyFreePriceTagResourcePath), new Vector2(1000f, -48f), new Vector2(230f, 100f), false, Color.white);
AddResultText(parent, "Duty Free Mileage Label", "보유 마일리지", new Vector2(990f, -26f), new Vector2(118f, 20f), 14f, FontStyles.Bold, new Color(0.94f, 0.99f, 1f, 0.96f), TextAlignmentOptions.MidlineLeft);
AddResultText(parent, "Duty Free Mileage Value", saveData.totalMileage + " M", new Vector2(1000f, -45f), new Vector2(122f, 28f), 21f, FontStyles.Bold, new Color(1f, 0.90f, 0.38f, 1f), TextAlignmentOptions.MidlineLeft);
}
private void AddDutyFreeEquipSlot(RectTransform parent, int slotIndex, Vector2 topLeftPosition) {
bool unlocked = slotIndex < saveData.bagSlots;
DutyFreeItemType itemType = unlocked ? GetEquippedDutyFreeItem(slotIndex) : DutyFreeItemType.None;
bool hasItem = itemType != DutyFreeItemType.None;
GameObject slotObject = CreateUiObject("Duty Free Equip Slot " + (slotIndex + 1), parent, typeof(Image), typeof(Button));
RectTransform slotRect = slotObject.GetComponent<RectTransform>();
slotRect.anchorMin = new Vector2(0f, 1f);
slotRect.anchorMax = new Vector2(0f, 1f);
slotRect.pivot = new Vector2(0f, 1f);
slotRect.anchoredPosition = topLeftPosition;
slotRect.sizeDelta = new Vector2(64f, 64f);
Image slotImage = slotObject.GetComponent<Image>();
if(hasItem)
{
slotImage.sprite = LoadDutyFreeResourceSprite(DutyFreeOccupiedSlotResourcePath);
slotImage.color = slotImage.sprite != null ? Color.white : new Color(0.05f, 0.16f, 0.20f, 0.88f);
}
else if(unlocked)
{
slotImage.sprite = LoadDutyFreeResourceSprite(DutyFreeActiveSlotResourcePath);
slotImage.color = slotImage.sprite != null ? Color.white : new Color(0.58f, 0.36f, 0.18f, 0.88f);
}
else
{
slotImage.sprite = LoadDutyFreeResourceSprite(DutyFreeInactiveSlotResourcePath);
slotImage.color = slotImage.sprite != null ? Color.white : new Color(0.35f, 0.35f, 0.35f, 0.78f);
}
slotImage.preserveAspect = true;
slotImage.raycastTarget = hasItem;
Button slotButton = slotObject.GetComponent<Button>();
slotButton.targetGraphic = slotImage;
slotButton.interactable = hasItem;
slotButton.navigation = new Navigation {
mode = Navigation.Mode.None
};
if(hasItem)
{
int capturedSlotIndex = slotIndex;
slotButton.onClick.AddListener(delegate { UnequipDutyFreeSlot(capturedSlotIndex); });
}
AddResultText(slotRect, "Duty Free Slot Number", (slotIndex + 1).ToString(), new Vector2(3f, -3f), new Vector2(18f, 18f), 10f, FontStyles.Bold, new Color(0.78f, 0.92f, 0.97f, 0.94f), TextAlignmentOptions.Center);
if(hasItem)
{
AddResultImage(slotRect, "Duty Free Slot Icon", GetDutyFreeItemSprite(itemType), new Vector2(32f, -31f), new Vector2(36f, 36f), true, Color.white);
AddResultText(slotRect, "Duty Free Slot Name", GetDutyFreeItemShortName(itemType), new Vector2(5f, -50f), new Vector2(54f, 12f), 8f, FontStyles.Bold, new Color(0.94f, 0.99f, 1f, 0.96f), TextAlignmentOptions.Center);
}
}
private void AddDutyFreeBagUpgradeButton(RectTransform parent, Vector2 topLeftPosition) {
bool isMax = saveData.bagSlots >= 3;
bool canBuy = !isMax && saveData.totalMileage >= BagSlotUpgradeCost;
GameObject buttonObject = CreateUiObject("Duty Free Bag Upgrade", parent, typeof(Image), typeof(Button));
RectTransform buttonRect = buttonObject.GetComponent<RectTransform>();
buttonRect.anchorMin = new Vector2(0f, 1f);
buttonRect.anchorMax = new Vector2(0f, 1f);
buttonRect.pivot = new Vector2(0f, 1f);
buttonRect.anchoredPosition = topLeftPosition;
buttonRect.sizeDelta = new Vector2(160f, 64f);
Image buttonImage = buttonObject.GetComponent<Image>();
buttonImage.sprite = LoadUiSprite(
canBuy ? DutyFreeButtonPrimaryResourcePath : DutyFreeButtonDisabledResourcePath,
canBuy ? "Assets/Resources/UI_DutyFreeButton_PrimaryYellow.png" : "Assets/Resources/UI_DutyFreeButton_DisabledGray.png");
buttonImage.color = canBuy
? Color.white
: (buttonImage.sprite != null ? Color.white : new Color(0.36f, 0.43f, 0.47f, 0.76f));
buttonImage.preserveAspect = false;
buttonImage.raycastTarget = canBuy;
Button button = buttonObject.GetComponent<Button>();
button.targetGraphic = buttonImage;
button.interactable = canBuy;
button.navigation = new Navigation {
mode = Navigation.Mode.None
};
button.onClick.AddListener(BuyBagSlotUpgrade);
AddResultImage(buttonRect, "Duty Free Bag Upgrade Icon", LoadUiSprite("", DutyFreeBackpackAssetPath), new Vector2(45f, -32f), new Vector2(42f, 42f), true, canBuy ? Color.white : new Color(1f, 1f, 1f, 0.48f));
AddResultText(buttonRect, "Duty Free Bag Upgrade Label", isMax ? "가방 MAX" : "가방 +1", new Vector2(75f, -11f), new Vector2(66f, 24f), 16f, FontStyles.Bold, canBuy ? new Color(0.06f, 0.16f, 0.22f, 1f) : new Color(0.72f, 0.80f, 0.84f, 0.92f), TextAlignmentOptions.MidlineLeft);
AddResultText(buttonRect, "Duty Free Bag Upgrade Cost", isMax ? "" : BagSlotUpgradeCost + " M", new Vector2(85f, -36f), new Vector2(66f, 18f), 14f, FontStyles.Bold, canBuy ? new Color(0.87f, 0.55f, 0.08f, 1f) : new Color(0.62f, 0.68f, 0.70f, 0.92f), TextAlignmentOptions.MidlineLeft);
}
private void AddDutyFreeItemCard(RectTransform parent, string itemName, DutyFreeItemType itemType, int cost, int stock, Sprite itemSprite, UnityEngine.Events.UnityAction buyAction, Vector2 topLeftPosition) {
bool canBuy = CanBuyDutyFreeItem(itemType, cost);
bool hasFreeSlot = HasFreeDutyFreeSlot();
int equippedCount = GetEquippedDutyFreeItemCount(itemType);
bool canEquip = stock > equippedCount && hasFreeSlot;
bool canInteract = canEquip || canBuy;
GameObject cardObject = CreateUiObject("Duty Free Item " + itemName, parent, typeof(Image));
RectTransform cardRect = cardObject.GetComponent<RectTransform>();
cardRect.anchorMin = new Vector2(0f, 1f);
cardRect.anchorMax = new Vector2(0f, 1f);
cardRect.pivot = new Vector2(0f, 1f);
cardRect.anchoredPosition = topLeftPosition;
cardRect.sizeDelta = new Vector2(206f, 288f);
Image cardImage = cardObject.GetComponent<Image>();
cardImage.sprite = GetDutyFreeProductCardSprite(itemType);
cardImage.color = cardImage.sprite != null
? (canInteract ? Color.white : new Color(0.68f, 0.70f, 0.72f, 0.92f))
: canInteract
? new Color(0.97f, 0.91f, 0.78f, 0.96f)
: new Color(0.40f, 0.45f, 0.48f, 0.88f);
cardImage.preserveAspect = false;
cardImage.raycastTarget = false;
Color textColor = canInteract
? new Color(0.06f, 0.16f, 0.22f, 1f)
: new Color(0.78f, 0.84f, 0.86f, 1f);
AddResultImage(cardRect, "Duty Free " + itemName + " Image", itemSprite, new Vector2(103f, -107f), new Vector2(92f, 96f), true, canInteract ? Color.white : new Color(1f, 1f, 1f, 0.54f));
Image priceTagImage = AddResultImage(cardRect, "Duty Free " + itemName + " Price Tag", LoadDutyFreeResourceSprite(DutyFreeProductPriceTagResourcePath), new Vector2(151f, -150f), new Vector2(52f, 78f), true, canInteract ? Color.white : new Color(1f, 1f, 1f, 0.62f));
priceTagImage.rectTransform.localEulerAngles = new Vector3(0f, 0f, 110f);
TextMeshProUGUI priceText = AddResultCenteredText(cardRect, "Duty Free " + itemName + " Price", cost + "M", new Vector2(153f, -150f), new Vector2(40f, 18f), 11f, FontStyles.Bold, canInteract ? new Color(0.03f, 0.03f, 0.028f, 1f) : new Color(0.36f, 0.36f, 0.34f, 0.92f), TextAlignmentOptions.Center);
priceText.rectTransform.pivot = new Vector2(0.5f, 0.5f);
priceText.rectTransform.anchoredPosition = new Vector2(155f, -150f);
priceText.rectTransform.localEulerAngles = new Vector3(0f, 0f, 20f);
TextMeshProUGUI nameText = AddResultCenteredText(cardRect, "Duty Free " + itemName + " Name", itemName + "\n" + GetDutyFreeItemEffectText(itemType), new Vector2(103f, -199f), new Vector2(126f, 34f), 13f, FontStyles.Bold, textColor, TextAlignmentOptions.Center);
nameText.lineSpacing = -8f;
GameObject buyObject = CreateUiObject("Duty Free " + itemName + " Buy Area", cardRect, typeof(Image), typeof(Button));
RectTransform buyRect = buyObject.GetComponent<RectTransform>();
buyRect.anchorMin = new Vector2(0f, 1f);
buyRect.anchorMax = new Vector2(0f, 1f);
buyRect.pivot = new Vector2(0f, 1f);
buyRect.anchoredPosition = new Vector2(39f, -232f);
buyRect.sizeDelta = new Vector2(128f, 22f);
Image buyImage = buyObject.GetComponent<Image>();
buyImage.color = Color.clear;
buyImage.raycastTarget = canInteract;
Button buyButton = buyObject.GetComponent<Button>();
buyButton.targetGraphic = buyImage;
buyButton.interactable = canInteract;
buyButton.transition = Selectable.Transition.None;
buyButton.navigation = new Navigation {
mode = Navigation.Mode.None
};
buyButton.onClick.AddListener(buyAction);
TextMeshProUGUI buyText = AddResultText(buyRect, "Duty Free " + itemName + " Buy Label", GetDutyFreePurchaseLabel(itemType, canEquip, canBuy, hasFreeSlot, stock, equippedCount), Vector2.zero, new Vector2(128f, 22f), 11f, FontStyles.Bold, new Color(0.94f, 0.99f, 1f, 1f), TextAlignmentOptions.Center);
buyText.outlineColor = new Color(0f, 0.04f, 0.07f, 0.98f);
buyText.outlineWidth = 0.12f;
}
private void AddDutyFreeSupplementCard(RectTransform parent, string itemName, int cost, int purchaseCount, Sprite itemSprite, UnityEngine.Events.UnityAction buyAction, Vector2 topLeftPosition) {
bool isMax = purchaseCount >= MaxSupplementPurchases;
bool alreadyPurchasedThisStage = HasPurchasedSupplementInDutyFreeStage();
bool canBuy = CanBuySupplement();
GameObject cardObject = CreateUiObject("Duty Free Item " + itemName, parent, typeof(Image));
RectTransform cardRect = cardObject.GetComponent<RectTransform>();
cardRect.anchorMin = new Vector2(0f, 1f);
cardRect.anchorMax = new Vector2(0f, 1f);
cardRect.pivot = new Vector2(0f, 1f);
cardRect.anchoredPosition = topLeftPosition;
cardRect.sizeDelta = new Vector2(206f, 288f);
Image cardImage = cardObject.GetComponent<Image>();
cardImage.sprite = GetDutyFreeProductCardSprite(DutyFreeItemType.Supplement);
cardImage.color = cardImage.sprite != null
? (canBuy || isMax ? Color.white : new Color(0.68f, 0.70f, 0.72f, 0.92f))
: canBuy
? new Color(0.97f, 0.91f, 0.78f, 0.96f)
: new Color(0.40f, 0.45f, 0.48f, 0.88f);
cardImage.preserveAspect = false;
cardImage.raycastTarget = false;
Color textColor = canBuy || isMax
? new Color(0.06f, 0.16f, 0.22f, 1f)
: new Color(0.78f, 0.84f, 0.86f, 1f);
AddResultImage(cardRect, "Duty Free " + itemName + " Image", itemSprite, new Vector2(103f, -107f), new Vector2(92f, 96f), true, canBuy || isMax ? Color.white : new Color(1f, 1f, 1f, 0.54f));
Image priceTagImage = AddResultImage(cardRect, "Duty Free " + itemName + " Price Tag", LoadDutyFreeResourceSprite(DutyFreeProductPriceTagResourcePath), new Vector2(151f, -150f), new Vector2(52f, 78f), true, canBuy || isMax ? Color.white : new Color(1f, 1f, 1f, 0.62f));
priceTagImage.rectTransform.localEulerAngles = new Vector3(0f, 0f, 110f);
TextMeshProUGUI priceText = AddResultCenteredText(cardRect, "Duty Free " + itemName + " Price", isMax ? "MAX" : cost + "M", new Vector2(153f, -150f), new Vector2(40f, 18f), 11f, FontStyles.Bold, canBuy || isMax ? new Color(0.03f, 0.03f, 0.028f, 1f) : new Color(0.36f, 0.36f, 0.34f, 0.92f), TextAlignmentOptions.Center);
priceText.rectTransform.pivot = new Vector2(0.5f, 0.5f);
priceText.rectTransform.anchoredPosition = new Vector2(155f, -150f);
priceText.rectTransform.localEulerAngles = new Vector3(0f, 0f, 20f);
TextMeshProUGUI nameText = AddResultCenteredText(cardRect, "Duty Free " + itemName + " Name", itemName + "\n" + GetDutyFreeSupplementEffectText(purchaseCount), new Vector2(103f, -199f), new Vector2(126f, 34f), 13f, FontStyles.Bold, textColor, TextAlignmentOptions.Center);
nameText.lineSpacing = -8f;
GameObject buyObject = CreateUiObject("Duty Free " + itemName + " Buy Area", cardRect, typeof(Image), typeof(Button));
RectTransform buyRect = buyObject.GetComponent<RectTransform>();
buyRect.anchorMin = new Vector2(0f, 1f);
buyRect.anchorMax = new Vector2(0f, 1f);
buyRect.pivot = new Vector2(0f, 1f);
buyRect.anchoredPosition = new Vector2(39f, -232f);
buyRect.sizeDelta = new Vector2(128f, 22f);
Image buyImage = buyObject.GetComponent<Image>();
buyImage.color = Color.clear;
buyImage.raycastTarget = canBuy;
Button buyButton = buyObject.GetComponent<Button>();
buyButton.targetGraphic = buyImage;
buyButton.interactable = canBuy;
buyButton.transition = Selectable.Transition.None;
buyButton.navigation = new Navigation {
mode = Navigation.Mode.None
};
buyButton.onClick.AddListener(buyAction);
TextMeshProUGUI buyText = AddResultText(buyRect, "Duty Free " + itemName + " Buy Label", GetDutyFreeSupplementPurchaseLabel(canBuy, isMax, alreadyPurchasedThisStage), Vector2.zero, new Vector2(128f, 22f), 11f, FontStyles.Bold, new Color(0.94f, 0.99f, 1f, 1f), TextAlignmentOptions.Center);
buyText.outlineColor = new Color(0f, 0.04f, 0.07f, 0.98f);
buyText.outlineWidth = 0.12f;
}
private void AddDutyFreeNextTravelButton() {
GameObject buttonObject = CreateUiObject("Duty Free Next Travel Sign", 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 = new Vector2(548f, -247f);
buttonRect.sizeDelta = new Vector2(200f, 160f);
Image buttonImage = buttonObject.GetComponent<Image>();
buttonImage.sprite = LoadDutyFreeResourceSprite(DutyFreeDirectionSignResourcePath);
buttonImage.color = buttonImage.sprite != null ? Color.white : new Color(0.82f, 0.91f, 0.96f, 0.90f);
buttonImage.preserveAspect = true;
buttonImage.raycastTarget = true;
Button button = buttonObject.GetComponent<Button>();
button.targetGraphic = buttonImage;
button.onClick.AddListener(ShowMapPreview);
button.navigation = new Navigation {
mode = Navigation.Mode.None
};
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8edc62b4b60248ce8001165fb0588bf8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,377 @@
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);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8bf10c40d6cc4b319e90f0bf9279966b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: