본문 바로가기
스파르타 내배캠

스파르타 내배캠 Unity 3기 14일차

by LemongO 2024. 1. 11.

(대충 코드 충돌 티콘)

 

 

 

 

어제는 Monster 클래스와 IDamagable 클래스를 만들어보았다.

오늘은 Stage 추가를 위해 DungeonInfo 라는 클래스를 만들어 보도록 하자.

 


스테이지 추가

 

  • 스테이지 추가 시 가지고 있을 기능
    • 최고 도달층 및 현재 진행 층
    • 최고 도달층 클리어 시, 스테이지 갱신
    • 입장 층에 따라 난이도 상이

 

스테이지 진행

  • 던전입구 ->  최고층 진행 / 다른 층 진행 (분기점) -> 선택 층 입장
    -> 해당 층 클리어 시, (최고층 == 현재층) 이라면 최고층 갱신

난이도 설정

  • 5층 단위로 스폰 개체 수 1 ~ 5마리 랜덤
  • 5층 단위로 레벨, 타입(종류) 증가

 

스테이지 기능을 총괄할 클래스는

DungeonInfo 라는 이름으로 생성해주자.

단, 해당 클래스는 기록을 관리하며 부가 기능 모두 객체를 생성할 필요가 없으므로 static 클래스로 생성한다.

 

internal static class DungeonInfo
{
    public static int HighestFloor { get; private set; } = 1;
    public static int CurrentFloor { get; private set; }

    public static void UpdateInfo()
    {
        // 현재 선택한 층이 최고도달 층일 때, 최고층 갱신

        if (HighestFloor == CurrentFloor)
            HighestFloor++;            
    }
}

 

클래스가 static 이다 보니 모든 변수 및 함수가 static으로 선언돼야 한다.

최고층은 1층으로 초기화 해주며 UpdateInfo 메서드를 통해 (현재층 == 최고층) 일 때, 최고층을 갱신한다.

 

난이도 설정은 몬스터를 스폰과 밀접하게 관련있다. 다음 코드를 살펴보자.

public static Monster[] MonsterSpawn(int floor)
{            
    CurrentFloor = floor;

    // 몬스터 생성

    int spawnCount = SpawnCount();
    Monster[] monsters = new Monster[spawnCount];

    for (int i = 0; i < monsters.Length; i++)
        monsters[i] = new Monster(MonsterInfo().Item1, MonsterInfo().Item2);

    return monsters;
}

 

몬스터들을 스폰하여 그 배열을 반환하는 MonsterSpawn 메서드에선 매개변수로 int floor를 받아 현재 진행중인 층인 CurrentFloor 에 할당한다.

 

그 후 실제 몬스터를 생성하는 부분을 작성해 스폰에 필요한 (스폰 수, 레벨, 타입)을

CurrentFloor에 맞춰 레벨링을 하도록 한다.

 

private static int SpawnCount()
{         
    // 5층 단위로 최대 스폰 1 ~ 5마리 
    // 최소 스폰 1마리, 최대 스폰이 3마리 이상일 땐 2마리

    int maxCount = CurrentFloor % 5 == 0 ? 5 : CurrentFloor % 5;
    int minCount = maxCount > 3 ? 2 : 1 ;
    Random rnd = new Random();            
    return rnd.Next(minCount, maxCount + 1);
}

private static (int, MonsterType) MonsterInfo()
{
    Random rnd = new Random();

    // 최소 레벨 : 1 * [x]층
    // 최대 레벨 : 3 * [x]층 - [x]층
    // 예) 1층 : 최소/최대 = 1 / 2
    // 예) 4층 : 최소/최대 = 4 / 8

    int minLv = 1 * CurrentFloor;
    int maxLv = 3 * CurrentFloor - CurrentFloor;            
    int randLv = rnd.Next(minLv, maxLv + 1);

    // 최소 타입 : 스켈레톤 워리어
    // 최고 타입 : 5층 마다 3가지 타입 추가 / 초과 시 현재 존재하는 마지막 타입
    // 예) 3층 : 최소/최대 = 0(스켈레톤 워리어) / 3 - 1(스켈레톤 마법사)
    // 예) 6층 : 최소/최대 = 0(스켈레톤 워리어) / 6 - 1(고블린 마법사)
    // 예) 12층 : 초소/최대 = 0(스켈레톤 워리어) / 12 - 1(목록에 없음) >> (고블린 마법사)

    int minType = 0;
    int maxType = 3 + CurrentFloor / 5 * 3;            
    int randType = rnd.Next(minType, Math.Min(maxType, Enum.GetValues(typeof(MonsterType)).Length));

    return (randLv, (MonsterType)randType);
}

 

SpawnCount 메서드에서 최소 스폰수 / 최대 스폰수를 설정후 그 사이의 랜덤한 값으로 나오도록 Random().Next() 를 활용하여 반환 하도록하자.

 

MonsterInfo 메서드는 튜플로 int 와 MonsterType을 반환하도록 하고 이에 각각 (레벨)과 몬스터의 (종류)가 들어갈 것이다.

 

밸런싱 및 레벨링 하는 부분은 언제든지 바뀔 수 있는 부분이니 자세한 설명은 하지 않았다.

 


이제 실제로 스테이지를 고를 수 있도록 씬 부분을 구현하도록 하자.

 

먼저 던전 입구 씬에서 bool 타입 지역변수를 선언하자.

bool choiceFloorPanel = false;

이 bool 값은 [다른 층 선택] 을 선택 시 보여질 패널의 조건을 담당한다.

 

if (!choiceFloorPanel)
{
    Console.WriteLine("" +
    $"(1) 전투 시작 (현재 진행 : {DungeonInfo.HighestFloor}층)\n" +
    $"(2) 다른 층 선택\n" +
    "(B) 마을로 돌아가기\n");
}
else
{                    
    for (int i = 1; i <= DungeonInfo.HighestFloor; i++)
        Console.WriteLine($"({i}) {i}층 진입");
    Console.WriteLine("(0) 취소\n");
}

 

choiceFloorPanel == false 라면 

최고 층을 도전할 것인지, 다른 층을 선택할 것인지 선택지가 나온다.

 

choiceFloorPanel == true 라면

이제껏 클리어한 층들의 목록과 최고 층 선택이 가능한 패널이 보이게 된다.

 

 

최고층 / 다른층 선택이 가능하다

 

1) 최고 층 부터 입장한다. 현재 5층을 도전할 수 있다.

2) 이때까지 클리어한 모든 층들을 다시 도전할 수 있다.

 

다른 층 선택 - 3층을 간다고 가정

 

3층을 다시 간다고 가정하자.

 

3층에 왔다. 최고층은 5층이다

 

정상적으로 3층에 왔다.

 

 

현재 1층 최고 1층 일 때

현재 층과 최고 층이 같다고 가정할 때

 

최고 층 클리어

최고 층이 갱신되어 2층으로 보여진다.