오늘은 카드 족보를 강화하는 카드 행성카드에 대한 구현과 행성카드 사용 기반 포커 족보 강화에 대한 구현 내용을 정리해보겠습니다.
행성 카드는 다음과 같이 기획하였습니다.
1. 행성카드의 구조는 조커카드와 유사한 구조로 생성, 상점 표시, 구매가 가능하도록 처리한다.
2. 행성 카드 구매시 소모품 슬롯에 배치한다.
3. 배치된 행성 카드를 클릭하여 사용시 카드와 연결된 족보가 표시된다.
4. 족보 표시 이후, Chip 과 Mult를 족보별 강화 수치에 맞게 적용한다
5. 행성 카드 사용시 삭제처리한다.
6. 삭제된 행성 카드는 다음 라운드부터 다시 상점에 노출 되어야 한다.
행성 카드는 PlanetCard에서 카드 생성 및 족보 강화를 진행, ConsumableSlot, ShopUI, ShopManager에서 상점에 표시 및 구매, 슬롯 배치가 가능하도록 처리하였습니다.
PlanetCard.cs
<style>
public class PlanetCard : BaseCard,IPointerEnterHandler, IPointerExitHandler
{
[Header("PlanetCard Information")]
public float addMult;
public int addChip;
public int sellPrice;
public HandRanking enforceTarget;
public static void SetupBaseRankLevel()
{
targetRankLevels.Clear();
for(int i = 1; i <= 9; i++)
{
HandRanking rank = (HandRanking)i;
targetRankLevels.Add(rank, 0);
}
}
public void SetupCard(string id, int sellPrice, int targetRankIndex)
{
Initalize(id, sellPrice, targetRankIndex);
gameObject.SetActive(false);
}
public void Initalize(string id, int sellPrice, int targetRankIndex)
{
if (targetRankIndex == 0) return;
string name = (targetRankIndex < planetName.Length) ? planetName[targetRankIndex] : "";
string description = (targetRankIndex < enforceDescriptions.Length) ? enforceDescriptions[targetRankIndex] : "";
base.Initalize(id, name, description);
this.sellPrice = sellPrice;
this.enforceTarget = (HandRanking)targetRankIndex;
if (planetNameText != null)
{
planetNameText.text = (targetRankIndex < planetName.Length) ? planetName[targetRankIndex] : "";
}
SetRankStat(this.enforceTarget, out this.addChip, out this.addMult);
}
public void UsePlanetCard()
{
int enforceChip;
float enforceMult;
//Debug.Log("UsePlanetCard 진입");
if (targetRankLevels.ContainsKey(enforceTarget))
{
targetRankLevels[enforceTarget]++;
SetRankStat(enforceTarget, out enforceChip, out enforceMult);
PlayLevelUp(enforceTarget, enforceChip, enforceMult);
//Debug.Log($"UsePlanetCard targetRankLevels: {targetRankLevels[enforceTarget]}");
ConsumableSlot.Instance.RemovePlanetCard(this);
ShopManager shopManager = Object.FindFirstObjectByType<ShopManager>();
if (shopManager != null)
{
if (!shopManager.remainPlanetList.Contains(this))
{
shopManager.remainPlanetList.Add(this);
}
transform.SetParent(shopManager.planetParent);
}
gameObject.SetActive(false);
}
}
public static void ApplyEnforceHandRanking(HandRanking ranking, CardCalculator cardCalculator)
{
if (targetRankLevels.Count == 0) SetupBaseRankLevel();
int enforceCount = targetRankLevels[ranking];
if (enforceCount <= 0) return; // 아직 행성카드 미사용상태일 경우
SetRankStat(ranking, out int chip, out float mult);
cardCalculator.chip += chip * enforceCount;
cardCalculator.mult += mult * (float)enforceCount;
}
private static void SetRankStat(HandRanking ranking, out int chip, out float mult)
{
chip = 0;
mult = 0;
switch (ranking)
{
case HandRanking.HighCard: chip = 5; mult = 1; break;
case HandRanking.OnePair: chip = 5; mult = 1; break;
case HandRanking.TwoPair: chip = 10; mult = 1; break;
case HandRanking.Triple: chip = 15; mult = 2; break;
case HandRanking.Straight: chip = 25; mult = 2; break;
case HandRanking.Flush: chip = 25; mult = 2; break;
case HandRanking.FullHouse: chip = 45; mult = 2; break;
case HandRanking.FourCard: chip = 65; mult = 3; break;
case HandRanking.StraightFlush: chip = 85; mult = 3; break;
}
int level = targetRankLevels[ranking];
chip *= level;
mult *= level;
}
}
</style>
오늘은 행성카드와 행성카드 기반 족보 강화 시스템을 구현하였습니다.
기존 조커카드와 동일한 방식으로 진행되는 부분들이 많아서 구현에 어려움이 있지는 않았지만, 구현 과정에서 2가지 개선 필요한 사항이 파악되었습니다.
현재 조커 카드와 더불어 행성카드를 배치하는 Slot을 싱글톤으로 구현하였습니다.
싱글톤으로 구현했던 의도는 씬 전환에 있어서도 슬롯의 배치나 배치된 카드가 유지되어야 한다는 생각에 싱글톤으로 유지하였습니다.
싱글톤으로 전환하는 기준이 데이터 유지 및 프로젝트 내에 유일해야한다는 관점에도 부합한다고 생각하였습니다.
하지만 너무 많은 싱글톤 방식의 구현은 오히려 싱글톤에만 의지하는 구현 습관이 생길것 같다는 생각과 게임의 정보를 유지한다는 관점이 부합되지만 일반적인 이전에 구현한 RoundManager와 같은 것들에서만 싱글톤을 유지하고 게임 오브젝트성 데이터들은 싱글톤 없이 데이터 전달을 진행하는 것이 옳은 방식이라고 판단하여 추후에 싱글톤 전환을 제거할 예정입니다. 이 또한 리팩토링을 진행할 때, 수정해볼 계획입니다.