ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Turn RPG 만들기 / 스파르타 부트캠프 숙제
    스파르타 게임 개발 2024. 5. 6. 17:36

    Turn RPG를 만들어 보자.

     

    먼저 Monster와 Player의 Class들을 만들어 주자. 이번엔 interface를 활용 해서 만들어 볼 것이다. 왜냐하면 쓰라고 했으니까.

     

    interface를 만들어 주고 property와 Damage를 입게 하는 함수를 만들어 준다. 

    그리고 Player에서 상속을 받고 구현을 하고 Monster라는 Class도 만들어서 구현을 해준다. 

     

     

    internal interface ICharacter
    {
        string Name { get;}
        int Health { get; set; }
        int Attack { get;}
        bool IsDead { get;}
        void TakeDamage(int damage);
    }


    internal class Warrior : ICharacter
    {
        public string Name { get; }
        public int Health { get; set; }

        public bool IsDead => Health <= 0;
        public int Attack { get; set; }

        public Warrior(string name)
        {
            Name = name;
            Health = 100;
            Attack = 30;
        }

        public void TakeDamage(int damage)
        {
            Health -= damage;
            if (IsDead) Console.WriteLine($"{Name}이(가) 죽었습니다.");
            else Console.WriteLine($"{Name}이(가) {damage}의 데미지를 받았습니다. 남은 체력: {Health}");
        }
    }


    public class Monster : ICharacter
    {
        public string Name { get; set; }
        public int Health { get; set; }
        public int Attack { get; set; }
        public bool IsDead => Health <= 0;
        public void TakeDamage(int damage)
        {
            Health -= damage;
            if (IsDead) Console.WriteLine($"{Name}이(가) 죽었습니다.");
            else Console.WriteLine($"{Name}이(가) {damage}의 데미지를 받았습니다. 남은 체력: {Health}");
        }
    }

     

     

    잘 몰르겠어가지고 답안지 보면서 했더니 좀 섞였다. 그리고 Moster Class에서 파생 된 Goblin과 Dragon Class를 만들어 주면 된다. 

     

     public class Goblin : Monster
     {
         public Goblin(string name = "Goblin", int health = 100, int attack = 10)
         {
             Name = name;
             Health = health;
             Attack = attack;
         }
     }


     public class Dragon : Monster
     {
         public Dragon(string name = "Dragon", int health = 200, int attack = 20)
         {
             Name = name;
             Health = health;
             Attack = attack;
         }
     }

     

    난 이렇게 했는데 값을 넣어줄 때 매개변수에 넣을 필요 없이 생성자 안에서 바로 해줄 수 있다. 

     

    public class Dragon : Monster
     {
         public Dragon(string name = "Dragon")
         {
             Name = name;
             Health = 200;
             Attack = 20;
         }
     }

     

    이런 식으로, 굳이 내가 했던 것 처럼 할 필요가 없다. 상황에 따라 다르겠지만,

     

    그리고 이제 Item class를 만들어 준다 이 것도 interface를 활용 해보라고 한다. 

     

    interface 안에는 name 변수와 Use 함수를 만들어 주고 Class에서 구현을 하게 했다.

     

     

    internal class HealthPotion : IItem
    {
        public string Name => "체력 포션";

        public void Use(Warrior warrior)
        {
            warrior.Health += 50;
            Console.WriteLine("체력이 회복 되었습니다!");
        }

    }


    internal class StrengthPotion : IItem
    {
        public string Name { get; set; }

        public void Use(Warrior warrior)
        {
            warrior.Attack += 10;
            Console.WriteLine("공격력이 강화 되었습니다!");
        }

        public StrengthPotion(string name = "강화 포션")
        {
            Name = name;
        }
    }

     

    난 이렇게 했다. 위와 아래가 좀 다른 게 확인이 될텐데 그건 내가 답지 보면서 하다가 좀 섞였다.

     

    그리고 이제 Stage라는 class를 만들어줘서 게임이 실행 되게 해주면 된다.

    이 때 interface를 최대한 활용 해줘서 간단하게 함수들을 작성 할 수 있었다. 

     

    internal class Stage
    {
        ICharacter Player;
        ICharacter Monster;
        List<IItem> Items;

        public Stage(ICharacter player, ICharacter monster, List<IItem> items)
        {
            Player = player;
            Monster = monster;
            Items = items;
        }


        public void start()
        {
            Console.Clear();
            Console.WriteLine("전투 시작!");
            Console.WriteLine($"{Player.Name}의 체  력 : {Player.Health}");
            Console.WriteLine($"{Player.Name}의 공격력 : {Player.Attack}\n");
            Console.WriteLine($"{Monster.Name}의 체 력 : {Monster.Health}");
            Console.WriteLine($"{Monster.Name}의 공격력 : {Monster.Attack}");
            Console.WriteLine("==========================================================");

            while(!Player.IsDead && !Monster.IsDead)
            {
                Console.WriteLine("Player의 공격!");
                Monster.TakeDamage(Player.Attack);
                Console.WriteLine($"{Player.Attack}의 Damage!");
                Thread.Sleep(1000);

                if (Monster.IsDead) break;              //여기에서 if조건문을 사용 한 것은 moster가 죽었는데 공격 하면 안 되기 때문!

                Console.WriteLine($"{Monster.Name}의 공격!");
                Player.TakeDamage(Monster.Attack);
                Console.WriteLine($"{Monster.Attack}의 Damage!");
                Thread.Sleep(1000);
            }

            if(Monster.IsDead)
            {
                Console.WriteLine("Player의 승리!");
                Console.WriteLine("전림품을 획득 할 수 있습니다!");
                Console.WriteLine("사용 할 아이템을 선택 해주세요.");

                for (int i = 0; i < Items.Count; i++)
                {
                    Console.WriteLine($"{i+1}. {Items[i].Name}");
                }

                while (true)
                {
                    if (int.TryParse(Console.ReadLine(), out int num) && num <= Items.Count)
                    {
                        Items[num - 1].Use((Warrior)Player);
                        Console.WriteLine($"현재 Player의 정보");
                        Console.WriteLine($"체력 : {Player.Health}   공격력 : {Player.Attack}\n");
                        break;
                    }
                    else
                    {
                        Console.WriteLine("잘 못 된 입력 입니다.");

                        Console.WriteLine("다시 입력 해주세요.");
                    }
                }
            }
            else if(Player.IsDead)
            {
                Console.WriteLine("Monster에게 패배 하였습니다.");
            }
        }
    }

     

    이렇게 class를 만들어 줬는데 interface로 만들어 두니 함수를 작성 할 때 매우 편리 했다. 원래대로라면 참조 하려면 객체를 생성하거나 매개변수로 받아오게 하거나 등등 번거로웠는데 interface로 작업을 하니 되게 편리 했다. 

    함수 하나만 만들어두고 사용 할 때 값만 class를 넣어주면 되니까 편했다. 

     

    이제 main 함수에서 실행이 되게끔 객체들을 생성 해주고 함수를 실행 하게 하면 된다. 

     

    static void Main(string[] args)
    {
        Warrior player = new Warrior("원강");
        Goblin goblin = new Goblin();
        Dragon dragon = new Dragon();
        List<IItem> items = new List<IItem> { new HealthPotion(), new StrengthPotion() };

        Stage stage1 = new Stage(player, goblin, items);
        stage1.start();
        if (player.IsDead) return;

        Stage stage2 = new Stage(player, dragon, items);
        stage2.start();
        if (player.IsDead) return;

        Console.WriteLine("축하합니다! Game Clear!");
    }

     

    이렇게 하면 끝이다. 

     

    느낀 점 : 이번 숙제를 하면서 interface에 대한 활용법에 대해서 깨달은 느낌이다. 

    원래 interface가 무엇인진 알았고, 어떤 식으로 활용 할 수도 있는지는 알고 있었지만 직접 해보니 더 깨달은 느낌이다. 

     

    interface를 상속 받은 class에 구현한 함수들을 실행 하려면 interface형 객체를 만들고 값에 class를 넣어줘서 함수들을 사용 할 수 있었는데 이것 말고도 다른 class에서 함수들을 만들 때 interface형으로 참조형을 만들어서 함수들을 편리하게 만들어 줄 수 있었다. 이 방법을 사용 안 한다면 다른 class에서 만들 때 객체를 매번 생성 하거나 매개변수로 받아오거나 등등 번거롭게 작업을 해야 했는데 이 방식을 사용하니 매우 편리 했다. 그러면  interface에 최대한 많은 기능들을 넣는 게 좋은 걸까. 어찌 되었든 console game 만들 때는 유용한 것 같으나 Unuty에서도 유용한지는 의문이다. 

     

    class 작성 방법 자체가 많이 다른 느낌이라 Unuty에서 interface는 어떤 방식으로 사용 되는지 궁금하다.

    그리고 살짝 권태기가 온 것일까. 열정이 많이 사그라진 느낌으로 이번 숙제를 한 것 같다. 다시 되찾자 내 열정.

     

Designed by Tistory.