들어가기 앞서
이전에 던전을 완성하고 플레이 테스트를 하면서 발견한 버그수정과 추가되는 기능들을 진행하고자 한다
아이템 추가 : 체력회복물약
<회복기능 기능>
● 플레이어의 체력 +
● 회복중 maxHP에 도달할 경우 maxHP를 넘지 않고 최대치까지만 회복
● 상점에서 구매할경우 물약은 구매갯수 제한이 없음
public void AddHPStats(Item item) //체력함수 추가
{
int bonusHp = CurrentHp += item.StatusBonus;
if (item.Type == Item.ItemType.Potion)
{
if (bonusHp > MaxHp)
{
CurrentHp = MaxHp; // 포션 사용 시 최대 체력을 넘지 않도록 보장
}
else
{
CurrentHp = bonusHp; // 포션 사용 시 현재 체력에 보너스 체력을 추가
}
}
}
전투선택지-도망치기 추가 기능
<구현 사항>
● 플레이어 소지금에서 일정수치(%)만큼 감소
● 도망치기시 확률로 발동됨
void PlayerRun()
{
if (currentMonsters.Count > 1)
{
if (new Random().NextDouble() < 0.1f) // 10% 확률로 도망 성공
{
if (new Random().NextDouble() < 0.3f) // 30% 확률로 돈 흘림
LoseGold();
GameManager.Instance.currentState = DungeonState.Adventure;
Info("도망쳤습니다");
Thread.Sleep(500);
return;
}
else
{
Info("도망치지 못했습니다.");
GameManager.Instance.currentState = DungeonState.EnemyTurn;
MonstersDeadCheck();
return;
}
}
else
{
if (new Random().NextDouble() < 0.3f)
LoseGold();
Info("도망쳤습니다.");
GameManager.Instance.currentState = DungeonState.Adventure;
Thread.Sleep(200);
}
// 입력 버퍼 비우기
while (Console.KeyAvailable) Console.ReadKey(true);
Thread.Sleep(500);
// 또 한 번 비워주기 (남아있을 수도 있으니까)
while (Console.KeyAvailable) Console.ReadKey(true);
}
void LoseGold()
{
Info("도망치다가 소지금을 흘렸습니다");
myPlayer.Gold -= (int)(myPlayer.Gold * 0.05f); // 소지금 5% 감소
}
던전 난이도 설정 구현 단계
<구현 사항>
● 난이도별 클리어조건 수치와 몬스터 출현수 변경
● 새로운 화면을 위해 열거변수 추가
public enum DungeonState
{
SelectStart,
SelectLevel,
Adventure,
PlayerTrun,
PlayerAttack,
EnemyTurn,
EndBattle,
}
// 던전 난이도 열거형
public enum DungeonLevel
{
Easy,
Normal,
Hard,
}
● 난이도 선택 화면 구성
// ============================[던전선택]============================
void SelectLevelRender()
{
Print("◎던전-난이도 선택◎", ConsoleColor.DarkYellow);
Print("던전의 난이도를 선택해주세요.\n");
Print(1, "쉬움 난이도 | 몬스터 최대 2마리 까지만 출현", ConsoleColor.DarkCyan);
Print(2, "보통 난이도 | 몬스터 최대 3마리 까지만 출현", ConsoleColor.DarkCyan);
Print(3, "어려움난이도 | 몬스터 최대 4마리 까지만 출현", ConsoleColor.DarkCyan);
Print(0, "마을로 돌아가기", ConsoleColor.DarkCyan);
Print("\n원하시는 행동을 입력해주세요");
Console.Write(">>");
}
void SelectLevelMove(int index)
{
switch (index)
{
case 1:
Info("쉬움난이도로 진행합니다.");
Info("전투보다 스토리를 더 중요시 여기는 분들에게 알맞는 난이도 입니다.");
dungeonClearCount = 10;
GameManager.Instance.currentLevel = DungeonLevel.Easy;
GameManager.Instance.currentState = DungeonState.Adventure;
Thread.Sleep(200);
break;
case 2:
Info("보통 난이도로 진행합니다.");
dungeonClearCount = 15;
GameManager.Instance.currentLevel = DungeonLevel.Normal;
GameManager.Instance.currentState = DungeonState.Adventure;
Thread.Sleep(100);
break;
case 3:
Info("어려움 난이도로 진행합니다.");
dungeonClearCount = 20;
GameManager.Instance.currentLevel = DungeonLevel.Hard;
GameManager.Instance.currentState = DungeonState.Adventure;
Thread.Sleep(100);
break;
case 0:
Info("마을로 돌아갑니다");
GameManager.Instance.SwitchScene(GameState.TownScene); // 마을로 돌아가기
Thread.Sleep(100);
break;
default:
Console.WriteLine("\ninfo : 잘못 입력 하셨습니다.");
Thread.Sleep(200);
break;
}
}
● 난이도별 몬스터 출현수 조정 로직 추가
void SwapnMonster()
{
// 난이도별 몬스터수 조정
int max = 0;
int min = 1;
switch (GameManager.Instance.currentLevel)
{
case DungeonLevel.Easy:
max = 3;
break;
case DungeonLevel.Normal:
max = 4;
break;
case DungeonLevel.Hard:
min = 2; // 최소 2마리
max = 5;
break;
}
currentMonsters.Clear(); // 몬스터 목록 초기화
var rnd = new Random();
var types = GameManager.Instance.monsType.Keys.ToList(); // 몬스터 타입 목록 가져오기
int MonsterCount = new Random().Next(min, max); // 최소 1, 최대 3 마리 까지 생성하도록 설정
for (int i = 0; i < MonsterCount; i++)
{
var mType = types[rnd.Next(types.Count)];
switch (mType)
{
case MonsterType.Minion:
currentMonsters.Add(new Minion());
break;
case MonsterType.SigeMinion:
currentMonsters.Add(new SiegeMinion());
break;
case MonsterType.Voidgrub:
currentMonsters.Add(new Voidgrub());
break;
}
}
}
던전 진행하기, 새로하기 화면&기능 구현
<구현 사항>
● 던전 진행도 저장 및 화면에 출력
● 새로하기 누르면 모든 던전 수치 초기화
● 화면출력
void SelectStartRender()
{
Print("◎던전◎", ConsoleColor.DarkYellow);
Print("던전 진행을 선택해주세요\n");
if (isAtive)
{
int num = (walkCount *100) / dungeonClearCount;
Print(1, $"계속하기 | 진행도({num}%)", ConsoleColor.DarkCyan);
Print(2, "새로하기", ConsoleColor.DarkCyan);
}
else
Print(1, "새로하기", ConsoleColor.DarkCyan);
Print(0, "마을로 돌아가기", ConsoleColor.DarkCyan);
Print("\n원하시는 행동을 입력해주세요");
Console.Write(">>");
}
● 던전 탐험 중간에 마을로 귀환하는 로직
case 0:
Info("마을로 돌아갑니다");
GameManager.Instance.currentState = DungeonState.SelectStart;
GameManager.Instance.SwitchScene(GameState.TownScene); // 마을로 돌아가기
isAtive = true;
Thread.Sleep(100);
break;
버그 수정
● 다수의 몬스터가 나올때 한마리만 잡고 행동을 이어가면 모든 몬스터가 전멸함 |
MonstersDeadCheck 함수의 deadCount++; 해당부분의 변수가 입력요청될때마다 +되어 살아있는 몬스터가 있어도 죽은 몬스터가 중첩으로 카운팅되어 if (deadCount == currentMonsters.Count) 조건문에 해당되어 전투가 강제로 종료됨 그래서 체크하기전 deadCount를 초기화 해주는 로직을 추가하여 해결함 |
void MonstersDeadCheck()
{
deadCount = 0;
// 다음 몬스터턴 행동에 사용될 살아있는 몬스터들 큐에 추가
monsterQueue.Clear();
foreach (var monster in currentMonsters)
{
if (!monster.Stat.IsDead) // 살아있는 몬스터 필터링
{
monsterQueue.Enqueue(monster);
}
}
// 몬스터들 전부 죽었는지 확인
foreach (var monster in currentMonsters)
{
if (monster.Stat.IsDead)
deadCount++;
if (deadCount == currentMonsters.Count)
{
isWin = true; // 모든 몬스터를 처치했을 때 승리 상태로 변경
GameManager.Instance.currentState = DungeonState.EndBattle;
Info("모든 몬스터를 처치했습니다.");
}
else
{
GameManager.Instance.currentState = DungeonState.EnemyTurn;
}
}
● 몬스터와 플레이어 전투중 데미지 표기가 오기가 되는 현상 |
몬스터와 플레이어간 공유하는 데미지 연산 함수의 로직은 문제가 없었지만 출력하는 과정의 출력함수는 다른 데미지를 출력하고 있음을 발견하여 수정함 기존 void 였던 데미지 연산 함수를 int반환형으로 바꾸어 출력함수에서 연산함수의 반환값을 출력하는 형태로 수정함 |
● 데미지 연산함수 : 몬스터와 플레이어 공격시 연산이 다르므로 둘로 나눔
public int ApplyDamage(int damage)
{
int ten = (int)(damage * 0.1f);
int min = damage- ten;
int max = damage+ ten;
int rand= new Random().Next(min, max+1);
int finalDamage = rand - TotalDefense;
if (finalDamage < 1) finalDamage = 1; // 최소 1의 데미지는 받도록 보장
CurrentHp -= finalDamage;
if (CurrentHp < 0) CurrentHp = 0;
return finalDamage; // 최종 데미지를 반환
}
public int MosApplyDamage(int damage)
{
int finalDamage = damage - TotalDefense;
if (finalDamage < 1) finalDamage = 1; // 최소 1의 데미지는 받도록 보장
CurrentHp -= finalDamage;
if (CurrentHp < 0) CurrentHp = 0;
return finalDamage; // 최종 데미지를 반환
}
● 데미지 출력함수 : 연산되는 값이 다르므로 둘로 나눔
// target이 damage를 받는 행동
public virtual void TakeDamage(int damage)
{
// 실제 데미지 계산 및 적용은 Stat 전문가에게 위임
int finalDamage = Stat.ApplyDamage(damage);
// 데미지를 받은 후의 결과(메시지 출력, 사망 확인 등)는 Character가 직접 처리
Console.WriteLine($"{this.Name}은(는) {finalDamage}의 데미지를 받았습니다. (남은 체력: {Stat.CurrentHp})");
if (Stat.IsDead)
{
Console.WriteLine($"{this.Name}이(가) 쓰러졌습니다.");
}
}
// 몬스터가 Player에게 damage를 주는 행동
public virtual void MosTakeDamage(int damage)
{
// 실제 데미지 계산 및 적용은 Stat 전문가에게 위임
int finalDamage = Stat.MosApplyDamage(damage);
// 데미지를 받은 후의 결과(메시지 출력, 사망 확인 등)는 Character가 직접 처리
Console.WriteLine($"{this.Name}은(는) {finalDamage}의 데미지를 받았습니다. (남은 체력: {Stat.CurrentHp})");
if (Stat.IsDead)
{
Console.WriteLine($"{this.Name}이(가) 쓰러졌습니다.");
}
}
'유니티개발 TIL' 카테고리의 다른 글
4주차 1일 TIL_C#심화(알고리즘) (2) | 2025.07.21 |
---|---|
3주차 5일 TIL_TextRPG심화(+추가 : 회피기능) (6) | 2025.07.18 |
3주차 3일 TIL_TextRPG심화(상태패턴) (0) | 2025.07.16 |
3주차 2일 TIL_TextRPG심화(전투시스템&몬스터) (1) | 2025.07.15 |
3주차 1일 TIL_TextRPG심화(던전메이커) (0) | 2025.07.14 |