이전 게시글에 이어서 TextRPG의 전투 시스템에 회피기능을 추가해보았다.
특별히 복잡한 구조가 아니여서 회피기능은 치명타 기능과 유사한 방식으로 구현할 수 있었다.
public interface IDamageCalculator
{
(int damage, bool isCritical, bool isMiss) Calculate(int atk, int def);
}
반환값 튜플에 isMiss(회피여부)를 추가
public class PlayerBasicAttack : IDamageCalculator
{
private Random random = new Random();
private double criticalChance = 0.15;
private double criticalHit = 1.6;
private double evasionChance = 0.5; // 회피 확률
public (int damage, bool isCritical, bool isMiss) Calculate(int atk, int def)
{
bool isMiss = random.NextDouble() < evasionChance; // 회피 여부
if (isMiss) return (0, false, true); // 회피시 반환값
...
}
}
회피 시에는 공격이 무효되도록 처리
public interface IAttack
{
(int damage, bool isCritical, bool isMiss) Attack(Monster monster);
}
public class PlayerAttack : IAttack
{
private readonly IDamageCalculator calculator;
public PlayerAttack(IDamageCalculator calculator)
{
this.calculator = calculator;
}
public (int damage, bool isCritical, bool isMiss) Attack(Monster monster)
{
var (damage, isCritical, isMiss) = calculator.Calculate(GameManager.Instance.player.TotalAttack, monster.def);
monster.health -= damage;
return (damage, isCritical, isMiss);
}
}
PlayerAttack에서 회피여부를 추가로 받아서 반환값에 추가
public void AttackResult(Monster monster)
{
int beforeHp = monster.health;
IDamageCalculator calculator = new PlayerBasicAttack();
IAttack atk = new PlayerAttack(calculator);
var (damage, isCritical, isMiss) = atk.Attack(monster);
Console.Clear();
Console.WriteLine("Battle!!\n");
Console.WriteLine($"{GameManager.Instance.player.Name}의 공격!");
if (isMiss)
{
Console.WriteLine($"Lv.{monster.name}이(가) 공격을 회피했습니다.\n");
}
else
{
Console.WriteLine($"Lv.{monster.level} {monster.name}을(를) 공격했습니다. [데미지 : {damage}] {(isCritical ? "- 치명타 공격!!" : "")}\n");
}
Console.WriteLine($"Lv.{monster.level} {monster.name}");
Console.WriteLine($"HP {beforeHp} -> {(monster.health <= 0 ? "Dead" : monster.health)}\n");
Console.WriteLine("0. 다음\n");
Console.WriteLine(">>");
while (true)
{
bool isSelectedMenu = int.TryParse(Console.ReadLine(), out int index);
if (isSelectedMenu && index == 0) break;
Console.WriteLine("잘못된 입력입니다.");
}
}
isMiss 값을 이용해서 회피했을시 회피멘트가 뜨게함
이번 회피 기능은 치명타 기능과 구조가 거의 동일해서 구현 난이도도 낮았고, 빠르게 추가할 수 있었다.