[TIL] 팀프로젝트 (TextRPG) 3/4

백성은·2025년 4월 24일

TIL

목록 보기
20/34

✅ 들어가기 앞서

이전 게시글에 이어서 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 값을 이용해서 회피했을시 회피멘트가 뜨게함

✅ 후기

이번 회피 기능은 치명타 기능과 구조가 거의 동일해서 구현 난이도도 낮았고, 빠르게 추가할 수 있었다.

profile
게임 개발일지

0개의 댓글