-
내일배움캠프 14일차 TIL - 퀘스트 구현TIL/C# 2024. 5. 2. 20:48
[학습목표]
팀 프로젝트 추가 요구사항 중 퀘스트 기능을 구현한다.
[학습내용]
오늘은 어제 구현을 끝내지 못한 퀘스트 기능을 구현 완료하였다. 마침 팀원분이 아이템과 인벤토리 기능을 구현하셔서 아이템 클래스를 가져다가 퀘스트 보상으로 사용할 수 있었다.
퀘스트 클래스는 다음과 같다.
using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; namespace OceanStory { internal class Quest { public string QuestName { get; set; } // 퀘스트 제목 public string Description { get; set; } // 퀘스트 설명 public string QuestObjective { get; set; } // 퀘스트 수행조건 public int QuestObjectiveCount { get; set; } // 퀘스트 목표 진행도 public int QuestProgressCount { get; set; } // 퀘스트 현재 진행도 public List<Item>? QuestRewardItem { get; set; } // 퀘스트 완료시 보상 아이템 리스트 public int QuestRewardGold { get; set; } // 퀘스트 완료시 보상 골드 public bool IsAccepted { get; set; } // 퀘스트 진행 중 여부 public bool IsCleared { get; set; } // 퀘스트 완료 여부 public Quest(string questName, string description, string questObjective, int questObejctiveCount, int questProgressCount, List<Item> questRewardItem, int questRewardGold) { QuestName = questName; Description = description; QuestObjective = questObjective; QuestObjectiveCount = questObejctiveCount; QuestProgressCount = questProgressCount; QuestRewardItem = questRewardItem; QuestRewardGold = questRewardGold; IsAccepted = false; IsCleared = false; } } }
퀘스트를 완료했을 때 지급할 아이템을 리스트로 만들어서 저장하였다.
아래는 퀘스트 매니저 클래스다. 게임 시작 시에 스태틱으로 하나 생성된다.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace OceanStory { internal class QuestManager { public int QuestIndex = 0; // 외부에서 퀘스트 리스트 접근을 위한 인덱스 public List<Quest> QuestList = new List<Quest>(); // 퀘스트 리스트 public List<Item>[] QuestRewardItemList = new List<Item>[3]; // 퀘스트 보상 아이템 리스트 public QuestManager() { for (int i = 0; i < 3; i++) { QuestRewardItemList[i] = new List<Item>(); } QuestRewardItemList[0].Add(new Item("낡은 검", "마을 주민이 미니언을 잡아준 대가로 선물한 검이다.", 10, null, ItemType.WEAPON)); QuestRewardItemList[1].Add(new Item("튼튼해보이는 옷", "못 입고 다니는 게 안타까웠던 주민이 선물한 옷이다.", null, 10, ItemType.ARMOR)); QuestList.Add(new Quest("마을을 위협하는 미니언 처치", "이봐! 마을 근처에 미니언들이 너무 많아졌다고 생각하지 않나?\n" + "마을 주민의 안전을 위해서라도 저것들 수를 좀 줄여야 한다고!\n" + "모험가인 자네가 좀 처치해주게!", "미니언 5마리 처치", 5, 0, QuestRewardItemList[0], 100)); QuestList.Add(new Quest("장비를 장착해보자", "떼잉, 쯔쯧... 그렇게 약해빠진 장비를 가지고서 미니언이나 잡겠나?\n" + "좀 더 반듯한 장비를 마련해서 오라고!", "새로운 장비 아무거나 1개 장착", 1, 0, QuestRewardItemList[1], 100)); QuestList.Add(new Quest("더욱 더 강해지기!", "무언갈 지키기 위해선 강해져야 하는 법이지.\n" + "몬스터를 사냥하고 지금보다 레벨을 올려서 오게나.", "현재보다 레벨 2 증가", 2, 0, QuestRewardItemList[2], 500)); } // 퀘스트 진행도 증가 public void ProgressQuest(int QuestIndex) { if (QuestList[QuestIndex].IsAccepted) // 퀘스트가 진행 중 상태이면 { QuestList[QuestIndex].QuestProgressCount++; // 퀘스트 진행도 1 증가 if (QuestList[QuestIndex].QuestProgressCount >= QuestList[QuestIndex].QuestObjectiveCount) // 목표 진행도에 도달하면 퀘스트 완료 { ClearQuest(QuestIndex); } } } // 퀘스트 완료 public void ClearQuest(int QuestIndex) { foreach (Item questRewardItem in QuestList[QuestIndex].QuestRewardItem) // 보상 아이템 지급 { Program.Inventory.itemList.Add(questRewardItem); } Program.Character.Gold += QuestList[QuestIndex].QuestRewardGold; // 보상 골드 지급 QuestList[QuestIndex].IsAccepted = false; // 퀘스트 진행중 -> 완료 표시 QuestList[QuestIndex].IsCleared = true; } } }
가운데에 보면 퀘스트 내용을 직접 집어넣어줬는데, 코드가 많이 더러워진 느낌이 든다. 퀘스트 정보에 대한 것들을 따로 파일이라던지로 저장해놓았다가 불러올 수 있는 방법을 생각해봐야겠다.
그리고 퀘스트 진행도를 나타내기 위해서 IsAccepted(진행중)와 IsCleared(완료)를 boolean값으로 체크하게 했는데, 다시 생각해보니 둘은 공존할 수 없기 때문에 차라리 정수형 변수로 해서 여러가지 상태를 표현할 수 있게 하면 어땠을까 생각이 들었다.
아래 두 코드는 퀘스트 관련 씬이다.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace OceanStory.Scenes { // 퀘스트 화면 internal class QuestScene : Scene { public override void RunScene() { List<Quest> questList = Program.QuestManager.QuestList; while (true) { Console.Clear(); Console.WriteLine("Quest!!\n"); // 퀘스트 리스트 표시 if (questList != null) { for (int i = 0; i < questList.Count(); i++) { Console.WriteLine("{1}. {0}{2}", questList[i].IsCleared?"[완]":"", i + 1, questList[i].QuestName); } } Console.WriteLine("\n0. 돌아가기"); // 퀘스트 선택 입력 받기 int input = Program.SceneManager.GetUserInput(questList.Count(), "원하시는 퀘스트를 선택해주세요", 0); Program.QuestManager.QuestIndex = input - 1; if (input == 0 || input == -1) return; // 입력받은 퀘스트 정보 화면으로 이동 else Program.SceneManager.ChangeScene("QuestDetailScene"); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Transactions; namespace OceanStory.Scenes { // 퀘스트 정보 화면 internal class QuestDetailScene : Scene { public override void RunScene() { // 전역 변수 반복 접근을 줄이기 위한 변수 List<Quest> questList = Program.QuestManager.QuestList; int questIndex = Program.QuestManager.QuestIndex; while (true) { Console.Clear(); Console.WriteLine("Quest!!\n"); Console.WriteLine(questList[questIndex].QuestName + "\n"); Console.WriteLine(questList[questIndex].Description + "\n"); Console.WriteLine("- {0} ({1}/{2})\n", questList[questIndex].QuestObjective, questList[questIndex].QuestProgressCount, questList[questIndex].QuestObjectiveCount); Console.WriteLine("- 보상"); // 보상 아이템 리스트 표시 foreach(Item reward in questList[questIndex].QuestRewardItem) { Console.WriteLine(reward.Name); } Console.WriteLine("{0} G", questList[questIndex].QuestRewardGold); // 퀘스트가 완료 상태라면 if (questList[questIndex].IsCleared) { Console.WriteLine("\n완료된 퀘스트입니다."); Console.WriteLine("\n0. 뒤로 가기"); int input = Program.SceneManager.GetUserInput(0); if (input == 0) break; } else { // 퀘스트가 진행 중이 아니라면 if (!questList[questIndex].IsAccepted) { Console.WriteLine("\n1. 수락\n2. 거절"); int input = Program.SceneManager.GetUserInput(2); if (input == 1) questList[questIndex].IsAccepted = true; break; } // 퀘스트가 진행 중이라면 else { Console.WriteLine("\n현재 진행중인 퀘스트입니다."); Console.WriteLine("\n0. 뒤로 가기"); int input = Program.SceneManager.GetUserInput(0); if (input == 0) break; } } } } } }
씬은 있는 것을 출력하기만 하면 됐기 때문에 구현에 어려운 점은 없었다.
퀘스트 진행도를 출력해주는 기능이 있기 때문에, 퀘스트 조건을 한 번 수행할 때마다 카운트가 오르도록 구현했다. 특이한 조건을 가지는 퀘스트를 구현해야하는 상황이 오면 진행도를 어떻게 해야 할지 다시 생각해봐야 할 것 같다.
[결과물]
https://github.com/Gambling7l7l7JackPot/OceanStory
[회고]
TIL을 작성하면서 느끼는 건데, 새로운 걸 배운다기보다는 기존의 알던 것을 어떻게 활용하는지를 배우는 느낌이 큰 거 같다. 주말을 제외하면 내일이 팀 프로젝트를 실질적으로 진행할 수 있는 마지막 날이기 때문에 내일은 마무리작업에 들어가야할 거 같다.
'TIL > C#' 카테고리의 다른 글
내일배움캠프 16일차 TIL - 프로젝트 발표 (0) 2024.05.07 내일배움캠프 15일차 TIL - 팀 프로젝트 마무리 (1) 2024.05.03 내일배움캠프 13일차 TIL - 전투 구현 마무리 (1) 2024.05.01 내일배움캠프 12일차 TIL - 팀 프로젝트 전투 기능 관련 (0) 2024.04.30 내일배움캠프 11일차 TIL - 텍스트 기반 RPG 제작 팀 프로젝트 기초 (1) 2024.04.29