본문 바로가기
다이어리/내일배움 개발일지

게임개발캠프 - 팀과제(B) 4일차

by E.Clone 2024. 1. 12.

과정명 : 내일배움캠프 Unity 게임개발 3기

전체진행도 : 15일차

부분진행도 : Chapter2.2 - 4일차

작성일자 : 2024.01.12(금)

개발일지 목록 : 클릭


1. 진행중인 과정에 대해

팀 과제(콘솔 텍스트 던전 RPG) 진행률이 거의 막바지이다. 오는 월요일에 던전 내 전투 중 장면 구성을 손질하면 게임 내적인 부분은 완료가 되어있을 것 같다. 

UI.cs 클래스를 새로 마련하여 플레이어의 선택지 패널, 아스키아트 프리셋, 텍스트와 콘솔에 관련된 편의기능을 압축한 메서드 등 여러가지를 구현하고, 디자인 개선을 마쳤다. 전후 이미지를 같이 보여주면 좋을 것 같은데 그렇게까지 하기에는 에너지가 모자라다. 기록으로 남기는게 무조건 좋을텐데 라고 생각 중.

매일 그렇지만 요즘 다른 하는 일이 없어서 그런지 팀 과제랑 알고리즘 풀기에 모든 에너지를 쏟고 있다. 수면 시간도 너무 적어져서 그런지 두통이 심해졌다.

 

2. 오늘 학습에 대해

팀 과제

Github Desktop으로 하루 종일 팀 과제를 같이하다보니 깃은 이제 수월하게 다루고 있는 것 같다. 특히 팀원들이 Pull Request를 수행하기 전 Main함수로부터 업데이트를 잘 한 뒤에 PR을 진행했기 때문에 충돌이 거의 없었던 편.

오늘은 UI의 끝을 보자고 생각하여(갑자기 그런 기분이 들어) 구현을 많이 하였는데, 그 내용은 아래와 같다.

1. 타이틀 구현과 전반적인 UI 스타일 구현

타이틀이 필요하다고 개인적으로 종종 생각이 들었었기에, 오늘 UI 구현을 하며 타이틀 장면도 마련 해 두었다.

아스키아트가 화면을 꽉 채우도록 하고, 특정 좌표로 커서를 옮겨 텍스트를 구현하였다. 이 상태에서 아무 키나 누르면

데이터를 불러온다는 안내 메시지를 잠시 보여준 후, 다음 장면으로 넘어간다. 가운데 정렬이 말끔해보여서 좋았다.

캐릭터 생성 장면은 더 화려하게 꾸밀 수 있었지만, 생성 단계는 처음이라는 느낌답게 조촐하게 보여주는 것도 좋지 않을까 생각하게 되어, 필요로 하는 간단한 텍스트만 표시하도록 하였다.

그래도 왼쪽에 여백을 두거나 줄바꿈을 두고, '>>>' 문자를 두는 등 가독성에 신경을 썼다. 뒤따라 나오는 직업 선택이나 확인 장면도 거의 동일

직업까지 선택을 하면 아래와 같은 메인 메뉴를 볼 수 있다.

메인 메뉴이지만 현재 아이디어 고갈로 검소한 디자인을 하고있다.

우측 빈 부분에 아트를 넣거나 하면 좋을듯.

신경쓰이는 점은 상단 아스키아트가 너무 긴데, 내가 작업한 부분이 아니라 건드리기 조심스러운 부분도 있고 마땅한 대체재를 생각해 두지 않았기 때문에 일단은 현상유지이다.

메인메뉴를 제외하면 모두 하단의 유저 입력 전용 패널과 동일한 폭으로 맞춰두었다. 예를 들어 회복아이템 메뉴는 아래와 같이 균형잡힌 배치를 가지고 있다.

유저에게 보여지는 장면의 크기에 맞추어 콘솔창의 크기도 줄여보는 시도를 했었지만, 어째서인지 콘솔 폭을 120자 미만으로 줄이게 되면 콘솔창 하단에 좌우 스크롤바가 생겨버리기 때문에 일단 콘솔창은 넓게 쓰고 있다.

메인 컨텐츠인 던전에 들어가는 입구 장면이다. 간단한 아스키아트를 넣어두었다.

E 키를 통해 내 정보를 열어볼 수 있는데(정보열기는 다른 팀원이 구현)

스테이터스는 밝은 노란색으로 표시되게 하여 가독성을 높였고, 길어진 높이만큼 빈 공간에 아트도 더 넣어두었다.

 

2. UI.cs

오늘 UI.cs 파일을 새로 작성하고, 구현한 메서드가 여럿 있다.

 

(a) 유저 입력 패널

public static string UserInput(string alert="", bool positive=false, string reqMsg= "다음 행동을 입력하세요.")
{
    Console.WriteLine("");
    Console.WriteLine(".──────────────────────────────────────────────────────────────────── .");
    Console.WriteLine($"  {reqMsg}");
    Console.WriteLine("");
    Console.WriteLine(""); Console.ForegroundColor = (positive)?ConsoleColor.Green:ConsoleColor.Red;
    Console.WriteLine($"  {alert}"); Console.ResetColor();
    Console.WriteLine("  >>>"); 
    Console.WriteLine("'──────────────────────────────────────────────────────────────────── '");
    Console.SetCursorPosition(6, Console.CursorTop-2);
    return Console.ReadLine();
}

UserInput()을 사용하여 위와 같은 패널을 그린다.

경고 메시지와, 경고메시지의 성격(true:녹색 / false:빨간색), 그리고 기본 메시지인 "다음 행동을 입력하세요." 도 바꾸어 매개변수로 전달할 수 있다.

 

(b) 아스키아트

게임 내 모든 아스키아트를 모아두었다. 열거형인 AsciiPreset에 각자 정해둔 이름을 사용하여 AsciiArt 메서드를 호출한다.

// 열거형
public enum AsciiPreset
{
    TitleArt,
    CreateCharacter,
    SelectClass,
    MainMenu,
    Battle,
    Status,
	...
}

// 아스키아트 호출
public static void AsciiArt(AsciiPreset preset)
{
    ConsoleColor statusColor = ConsoleColor.Gray;
    int x, y;
    switch (preset)
    {
        ...
        case AsciiPreset.PotionInventory:
            Console.WriteLine("                                                                     ");
            Console.WriteLine("    .-.   p--- .'~`. .-=~=-.   :~:      |~|   .-~~8~~-.  |~|  .-.    ");
            Console.WriteLine("  .'__( .'~`.  `. .'  )___(  .'   `.    | |   |~~---~~|  | |  )__`.  ");
            Console.WriteLine("  | l | | m |  .'n`. (  o  ) |  p  |] .' q `. |   r   | .'s`. | t |  ");
            Console.WriteLine("  |___| |___|  `._.'  `._.'  |_____|  `.___.' `._____.' `._.' |___|  ");
            Console.WriteLine("                                                                     ");
            Console.ForegroundColor = statusColor;
            Console.WriteLine("----------------------------[회복 아이템]----------------------------");
            Console.ResetColor();
            Console.WriteLine("");
            break;
        ...
        case AsciiPreset.DungeonEntrance3:
            x = 41; y = 25;
            DrawOnSpecificPos("" +
                "      |\\      _,,,---,,_\n" +
                "ZZZzz /,`.-'`'    -.  ;-;;,_\n" +
                "     |,4-  ) )-,_. ,\\ (  `'-'\n" +
                "    '---''(_/--'  `-'\\_)\n",
                x, y);
            break;
        ...
    }
}

간단하게 줄여본 코드는 위와 같다. 그냥 적어둔 내용대로 Write를 하고 있기 때문에 복잡한 내용은 없다.

고양이 아트를 예로 든 DrawOnSpecificPos(string, int x, int y) 메서드는 특정 좌표를 지정하여 그릴 수 있도록 마련해둔 메서드이다. 그 내용은 아래와 같다.

 

(c) 특정 좌표에 그림을 그리는 DrawOnSpecificPos 메서드

public static void DrawOnSpecificPos(string s, int xInput, int yInput)
{
    // 커서 위치를 저장해두어, Draw가 끝나면 커서 위치를 원상복귀
    int ySave = Console.CursorTop;
    int xSave = Console.CursorLeft;
    int x = xInput;
    int y = yInput;
    string[] lines = s.Split('\n');
    foreach (string line in lines)
    {
        Console.SetCursorPosition(x, y);
        Console.Write(line);
        y++;
    }
    Console.SetCursorPosition(xSave, ySave);
}

진행중이던 커서 위치는 저장해두고, 특정 위치를 기점으로 아트를 그린 후, 원래의 커서 위치로 되돌아온다. 이렇게 만들어진 것이 아래의 고양이와 캠프장.

 

(d) 텍스트에 색을 입히는 메서드들

public static void ColoredWriteLine(string s, ConsoleColor color)
{
    Console.ForegroundColor = color;
    Console.WriteLine(s);
    Console.ResetColor();
}
public static void ColoredWrite(string s, ConsoleColor color)
{
    Console.ForegroundColor = color;
    Console.Write(s);
    Console.ResetColor();
}
public static void RandomColoredWrite(string s)
{
    Random random = new Random();
    foreach (char c in s)
    {
        Console.ForegroundColor = (ConsoleColor)random.Next(9, 16);
        Console.Write(c);
    }
    Console.ResetColor();
}

메서드 이름만큼 직관적으로, 그리고 한 줄로 사용할 수 있어 나름 편리할 메서드이다.

Console.Write 대신 사용할 수 있고, ConsoleColor.Red 와 같은 매개변수를 함께 넣어 색을 지정해준다.

// 단일 사용
UI.ColoredWriteLine("골드", ConsoleColor.Yellow);

// 연계 사용
Console.WriteLine($"골드를 {UI.ColoredWriteLine("500", ConsoleColor.Yellow);} 만큼 획득!");

그냥 사용해도 편하고, 더 좋은 점은 문자열 도중에 특정 단어만 색을 입히는 것이 편하다. 위 내용을 메서드 없이 깡으로 구현한다면 아래와 같이 매우 길어지게 된다.

// 예시1
Console.ForegroundColor = color;
Console.WriteLine("골드", ConsoleColor.Yellow);
Console.ResetColor();

// 예시2
Console.Write($"골드를 ");
Console.WriteLine("골드", ConsoleColor.Yellow);
Console.Write($"{"500"}");
Console.ResetColor();
Console.WriteLine($" 만큼 획득!");

Write와 WriteLine을 섞어 쓸 수 밖에 없게 되버리는 점도 문제점.

RandomColoredWrite(string s) 메서드는 받은 문자열을 문자 단위로 랜덤한 색을 입히게 하는 신나는 메서드이다.

 

알고리즘 풀이 중 자주 잊어버릴 만한 내용에 대해

캠프에서 소개하는 알고리즘 문제 중 40문제 이상을 풀었지만, 자주 잊어버려 찾아보고 코드 작성을 했던 내용이다.

복습하는 기분으로 문제들을 다시 열어보며 작성하였다.

 

No.3[120805 몫 구하기]

    public int solution(int num1, int num2) {
        int answer = num1 / num2;
        return answer;
    }

 

  • int 형끼리의 나눗셈 계산은 int 형을 반환한다.

 

No.7[120806 두 수의 나눗셈]

    public int solution(int num1, int num2) {
        int answer = 0;
        answer = (int)((float)num1/(float)num2*1000);
        return answer;
    }
  • float로 캐스트 된 수 끼리 나눗셈을 해야 제대로 된 결과가 나온다.
  • 현재 문제에서는 결과값의 소수 부분을 버리고 정수값만 출력.

 

No.10[120817 배열의 평균값]

    public double solution(int[] numbers) {
        double answer = 0;
        for(int i=0; i<numbers.Length; i++){
            answer += numbers[i];
        }
        answer /= numbers.Length;
        return answer;
    }
  • 배열을 전달받을 때에는 int[] numbers 의 형식을 사용.
  • 배열은 .Length 를 사용하여 길이를 반환한다. 리스트의 경우는 .Count 가 길이를 반환한다. 둘 다 뒤에 ()가 없음에 주의.

 

No.11[12937 짝수와 홀수]

  • (영단어)짝수는 'Even', 홀수는 'Odd' 

 

No.12[12944 평균 구하기]

    public double solution(int[] arr) {
        double answer = 0;
        answer /= arr.Length;
        ...
    }
  • 위와 같이 double 형을 int 형으로 나눌 경우에는 오류가 발생하지 않음. 변수 간 포함관계에 따라서 허용되는 것으로 추정.

 

No.13[12931 자릿수 더하기]

    public int solution(int n) {
        int answer = 0;
        string nStr = n.ToString();
        foreach(char c in nStr){
            answer += int.Parse(c.ToString());
        }
        return answer;
    }
  • '문자열' 을 int형으로 바꿀 경우에는 int.Parse() 사용. 문자열이 아닌 문자 는 사용할 수 없기 때문에 .ToString() 메서드를 통해 문자열로 변환 해 주어야 한다.
  • foreach문은 foreach(자료형 이름 in nStr){ 순회 내용 } 과 같이 작성. in 키워드 말고도 다른 방식도 여럿 있을 것으로 생각되어짐.

 

No.16[12954 x만큼 간격이 있는 n개의 숫자]

    public long[] solution(int x, int n) {
        long[] answer = new long[n];
        for(int i=1;i<=n;i++){
            answer[i-1] = (long)i*(long)x;
        }
        return answer;
    }
  • 일부 테스트케이스에서 실패하는 경우, 오버플로가 일어나는지 확인하자.
  • 해당 문제는 int의 범위를 벗어나는 값을 다루기 때문에 long으로 캐스팅하여 해결.

 

No.17[12932 자연수 뒤집어 배열로 만들기]

int[] answer = new int[numStr.Length];
  • 새로운 배열의 선언을 해 줄 때의 형식
answer[index++] = (int)(num%10);
  • 전치 및 후치 연산자를 활용하여 코드 길이 단축

 

3. 과제에 대해

  • 전투 중 UI 디자인 수정
  • README.md 작성하기

 

4. 참고자료

없음

반응형