80. Unity 최종 프로젝트 7주차(4)

이규성·2024년 2월 22일
0

TIL

목록 보기
88/106

02/22

📌알고리즘 코드 카타 (Algorithm Code Kata)

2016년

2016년 1월 1일은 금요일입니다. 2016년 a월 b일은 무슨 요일일까요? 두 수 a ,b를 입력받아 2016년 a월 b일이 무슨 요일인지 리턴하는 함수, solution을 완성하세요. 요일의 이름은 일요일부터 토요일까지 각각 SUN,MON,TUE,WED,THU,FRI,SAT

입니다. 예를 들어 a=5, b=24라면 5월 24일은 화요일이므로 문자열 "TUE"를 반환하세요.

제한사항

2016년은 윤년입니다.
2016년 a월 b일은 실제로 있는 날입니다. (13월 26일이나 2월 45일같은 날짜는 주어지지 않습니다)

입출력 예

abresult
524"TUE"
public class Solution
{
    public string solution(int a, int b)
    {
        int deltaDay = 0;

        int[] month = new int[] { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
        string[] day = new string[] { "FRI", "SAT", "SUN", "MON", "TUE", "WED", "THU" };

        for (int i = 0; i < a - 1; i++)
        {
            deltaDay += month[i];
        }

        deltaDay += b - 1;
        deltaDay %= 7;

        return day[deltaDay];
    }
}

📌팀 프로젝트 진행

목표

Android build 최적화
Ios 빌드 알아보기

금일 구현 설계

Armor system refactoring 4트

금일 구현한 사항

Armor system refactoring 1차 완료

public class UIArmorSlotContainer : MonoBehaviour
{
    private List<UIArmorSlot> _armorSlots = new List<UIArmorSlot>();

    private void Awake()
    {
        GameManager.Instance.Player.ArmorSystem.OnEquipArmor += EquipArmor;
        GameManager.Instance.Player.ArmorSystem.OnUnEquipArmor += UnEquipArmor;
    }
    
	//아머 슬롯을 생성한다.
    public void CreatArmorSlots<T>(GameObject slotPrefab, int count) where T : UIArmorSlot
    {
        for (int i = 0; i < count; i++)
        {
            var armorSlotPrefab = Instantiate(slotPrefab, this.transform);
            var armorSlotUI = armorSlotPrefab.GetComponent<T>();
            SetParts(armorSlotUI, i);
            _armorSlots.Add(armorSlotUI);
        }
    }
	
    //아머슬롯의 아이콘을 설정한다.
    public void Init<T>(QuickSlot[] quickSlot) where T : UIArmorSlot
    {
        foreach (var armor in quickSlot)
        {
            EquipArmor(armor);
        }
    }

	//아머슬롯이 생성될 때 enum ItemParts 값을 설정한다.
    private void SetParts(UIArmorSlot armorSlotUI, int index)
    {
        armorSlotUI.part = (ItemParts)index;
    }

	//인벤토리에서 아이템 데이터를 받아서 방어구 슬롯에 장착시킨다.
    public void EquipArmor(QuickSlot quickSlot)
    {
        if (quickSlot.itemSlot.itemData == null) return;

        int parts = GetPart(quickSlot);
        _armorSlots[parts].Set(quickSlot.itemSlot);
    }

	//방어구를 해제한다.
    public void UnEquipArmor(QuickSlot quickSlot)
    {
        int parts = GetPart(quickSlot);
        _armorSlots[parts].Clear();
    }
	
    private int GetPart(QuickSlot slot)
    {
        var itemData = slot.itemSlot.itemData as EquipItemData;
        if (itemData == null) return -1;
        return (int)itemData.part;
    }
}
public class UIArmorSlot : UIItemSlot
{
	//UI class는 데이터 처리를 하지 않고 디스플레이에 표현만 한다.
    enum Images
    {
        Icon,
    }

    public ItemParts part;

    public override void Initialize()
    {
        Bind<Image>(typeof(Images));
        Get<Image>((int)Images.Icon).gameObject.SetActive(false);
        Get<Image>((int)Images.Icon).raycastTarget = false;
    }

    private void Awake()
    {
        Initialize();
    }

    public override void Set(ItemSlot itemSlot)
    {
        if (itemSlot.itemData == null) return;
        Get<Image>((int)Images.Icon).sprite = itemSlot.itemData.iconSprite;
        Get<Image>((int)Images.Icon).gameObject.SetActive(true);
    }

    public override void Clear()
    {
        Get<Image>((int)Images.Icon).gameObject.SetActive(false);
    }
}
public class ArmorSystem : MonoBehaviour
{
    private Player _player;
    //방어력과 같은 중요한 변수는 private로
    [SerializeField] private int _defense;

    [SerializeField] private QuickSlot[] _equippedArmors;

    public event Action<QuickSlot> OnEquipArmor;
    public event Action<QuickSlot> OnUnEquipArmor;

    private void Awake()
    {
        _player = GetComponentInParent<Player>();

        _equippedArmors = new QuickSlot[2];
        for (int i = 0; i < _equippedArmors.Length; i++)
        {
            _equippedArmors[i] = new QuickSlot();
        }

        GameManager.Instance.Player.OnHit += OnUpdateDurabilityOfArmor;

        Load();

        GameManager.Instance.OnSaveCallback += Save;
    }

    private void Start()
    {
        _player.Inventory.OnUpdated += OnInventoryUpdated;
    }

	//방어구를 장착시키고 인벤토리의 UI를 장착된 상태로 업데이트한다.
    public void Equip(int index, ItemSlot itemSlot)
    {
        var part = GetPart(itemSlot);

        UnEquip(part);

        itemSlot.SetEquip(true);
        _equippedArmors[(int)part].Set(index, itemSlot);

        AddDefenseOfArmor(_equippedArmors[(int)part]);

        OnEquipArmor?.Invoke(_equippedArmors[(int)part]);
    }

    public void UnEquip(ItemParts part)
    {
        if (_equippedArmors[(int)part].itemSlot.itemData == null) return;

        SubtractDefenseOfArmor(_equippedArmors[(int)part]);

        _equippedArmors[(int)part].itemSlot.SetEquip(false);
        OnUnEquipArmor?.Invoke(_equippedArmors[(int)part]);

        _equippedArmors[(int)part].Clear();
    }

	//방어구 SO의 방어력 값을 가져와서 더해준다.
    private void AddDefenseOfArmor(QuickSlot quickSlot)
    {
        EquipItemData toolItemData = GetArmorItemData(quickSlot);
        _defense += toolItemData.defense;
    }

    private void SubtractDefenseOfArmor(QuickSlot quickSlot)
    {
        EquipItemData toolItemData = GetArmorItemData(quickSlot);
        _defense -= toolItemData.defense;
    }

	//몬스터에게 맞았을 때 방어구의 내구도를 감소시킨다.
    public void OnUpdateDurabilityOfArmor()
    {
        for (int i = 0; i < _equippedArmors.Length; i++)
        {
            if (_equippedArmors[i] != null && _equippedArmors[i].targetIndex != -1)
            {
                _player.Inventory.TrySubtractDurability(_equippedArmors[i].targetIndex, 1);
            }
        }
    }

	//방어구 아이템 데이터의 enum ItemParts 값을 가져오기 위한 형변환 함수이다.
    private EquipItemData GetArmorItemData(QuickSlot quickSlot)
    {
        EquipItemData toolItemDate = quickSlot.itemSlot.itemData as EquipItemData;
        return toolItemDate;
    }

    private ItemParts GetPart(ItemSlot slot)
    {
        var itemData = slot.itemData as EquipItemData;
        return itemData.part;
    }

	//방어력을 플레이어에게 넘겨주는 함수이다.
    public int GetDefense()
    {
        return _defense;
    }

	//방어구 슬롯을 UIInventory에 넘겨주기 위한 함수이다.
    public QuickSlot[] GetEquippedArmorsArray()
    {
        return _equippedArmors;
    }

	//방어구의 내구도가 다 닳아서 파괴되었을 때 인벤토리를 업데이트 시키는 함수이다.
    public void OnInventoryUpdated(int inventoryIndex, ItemSlot itemSlot)
    {
        if (itemSlot.itemData != null) return;
        for (int i = 0; i < _equippedArmors.Length; i++)
        {
            if (_equippedArmors[i] != null)
            {
                if (_equippedArmors[i].targetIndex == inventoryIndex && itemSlot.itemData == null)
                {
                    SubtractDefenseOfArmor(_equippedArmors[i]);
                    OnUnEquipArmor?.Invoke(_equippedArmors[i]);
                    _equippedArmors[i].Clear();
                }
            }
        }
    }

    private void Load()
    {
        if (SaveGame.TryLoadJsonToObject(this, SaveGame.SaveType.Runtime, "ArmorSystem"))
        {
            for (int i = 0; i < _equippedArmors.Length; ++i)
            {
                _equippedArmors[i].itemSlot.LoadData();
            }
        }
    }

    private void Save()
    {
        var json = JsonUtility.ToJson(this);
        SaveGame.CreateJsonFile("ArmorSystem", json, SaveGame.SaveType.Runtime);
    }
}

금일 이슈

금일 커밋한 사항

Refactored the armor system 2
방어구 시스템 리팩토링을 1차 완료하였습니다.

🤸🏻‍♀️Feedback

시간이 많이 소요되었지만 그래도 1차 완료는 해서 다행이라는 생각이 든다 . . .

0개의 댓글