Skip to content

MapManager

김광수 edited this page Oct 11, 2023 · 5 revisions

< Readme

MapManager

Map을 생성하고 관리하는 Manager입니다.

Code Summary

Field

  • maxXIndex

    • Map 리스트의 2차원 크기입니다.
    • 지도의 최대 x축
  • maxYIndex

    • Map 리스트의 1차원 크기입니다.
    • 지도의 최대 y축
  • minX

    • 한 층에서 만들어질 location의 최소 개수 입니다.
  • maxX

    • 한 층에서 만들어질 locaction의 최대 개수 입니다.
  • Map

    • 지도의 정보를 리스트배열로 표현 합니다.
    • 갈 수 없는 지역은 null로 처리하고 갈 수 있는 지역에는 LocationInfo로 해당 지역의 정보를 가지고 있습니다.
  • moveable

    • 한 층을 이동할 때 이동가능한 x축의 범위 입니다.

Method

public

  • GenerateMapStructure

    • 외부에서 MapManager를 통해 맵을 생성하고자 할때 호출됩니다.
    • 만약 이미 생성된 Map이 존재한다면 동작하지 않지 않습니다.
  • ClearMap

    • 외부에서 더 이상 필요없어진 Map의 정보를 지우기위해 호출됩니다.
    • ClearMap으로 Map이 null이 되면 GenerateMapStructure 메서드를 통해 새로운 Map을 생성할 수 있습니다

private

  • CheckDubugMap

    • 맵이 제대로 생성되는지 테스트하기위한 코드입니다.
    • 맵 List를 StringBuilder를 통해 문자열로 만들어 Debug.Log로 출력합니다
  • Init

    • 맵 생성시 가장 처음 호출되는 메서드 입니다.
    • 생성할 맵의 층 수 정보를 받아서 Map 리스트배열을 생성한 후 0층에 대한 정보를 생성합니다
  • RouteCountThisFloor

    • 이번층에 대한 정보를 바탕으로 다음층에 이동가능한 영역을 표시해서 int[]로 리턴합니다.
    • 이동 가능한 지역은 moveable 배열을 순회하며 판단합니다.
    • int[]에는 갈수 없는 지역은 0, 갈수있는 지역은 중첩에 따라 1, 2, 3으로 표시됩니다.
  • SelectRoute

    • RouteCountThisFloor에서 리턴해준 이동가능 배열의 정보를 바탕으로 각 location에서 이동할 지역을 선택해줍니다.
    • 이번층에서 활성화된 location들을 순회하여 각각의 location에서 연결할 다음층의 location을 생성합니다.
    • 다음층의 location이 Map에 어디에 저장되어 있는지 인덱스를 이번층의 LocationInfo.RouteIndexs에 저장하여 아래층에서 위층으로 접근할 수 있도록 해줍니다.
    • EventType을 결정해서 LocationInfo에 저장합니다.
  • CheckPos

    • 2차원의 인덱스 범위를 벗어나지 않기 위한 메서드입니다.
    • 인덱스 범위를 벗어나면 false를 리턴합니다.
  • AddSelectList

    • SelectRoute에서 사용하는 메서드로 이동가능배열의 중첩도에 따라서 selectList를 채워줍니다.
    • 우선도가 높을수록 selectList에 해당 인덱스가 여러번들어가서 선택될 확률이 높아집니다.

Code

using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class LocationInfo
{
    public LocationInfo(int x, int y, EventType type)
    {
        Init(x, y, type);
    }

    public void Init(int x, int y, EventType type)
    {
        Index = x;
        Floor = y;
        RouteIndexs = new List<int>();
        EventType = type;
    }
    public int Index { get; private set; }
    public int Floor { get; private set; }
    public List<int> RouteIndexs { get; private set; }
    public RectTransform rectTransform { get; set; }

    public EventType EventType { get; private set; }

    public EventInfoSO EventInfoSO { get; private set; }
}
public class MapManager : Singleton<MapManager>
{
    int maxXIndex = 10;
    int maxYIndex;

    int minX = 3;
    int maxX = 5;

    public List<LocationInfo>[] Map { get; private set; }

    public int[] moveable = { -1, 0, 1 };
    public void GenerateMapStructure(int floorNumber)
    {
        if (Map != null) return;

        Init(floorNumber);

        for( int i =1; i< maxYIndex; i++)
        {
            Map[i] = new List<LocationInfo>();

            int[] Possibility = RouteCountThisFloor(Map[i-1]);

            foreach (LocationInfo location in Map[i-1])
            {
                SelectRoute(location, Possibility);
                // 다음지역 중 하나를 선택한다.
            }
        }

    }

    public void ClearMap()
    {
        Map = null;
    }

    private void CheckDebugMap()
    {
        StringBuilder sb = new StringBuilder();

        foreach (List<LocationInfo> floor in Map)
        {
            int start = 0;
            foreach (LocationInfo location in floor)
            {
                for (int i = start; i < location.Index; i++)
                {
                    sb.Append(-1);
                }
                sb.Append(location.Index);
                start = location.Index + 1;
            }

            for (int i = start; i < maxXIndex; i++)
            {
                sb.Append(-1);
            }

            sb.AppendLine();
        }

        Debug.Log(sb.ToString());
    }
    private  void Init(int floorNumber)
    {
        maxYIndex = floorNumber;
        Map = new List<LocationInfo>[maxYIndex];
        Map[0] = new List<LocationInfo>();

        int choice = UnityEngine.Random.Range(minX, maxX+1);

        foreach(int index in Util.SelectNumber(0, maxXIndex, choice))
        {
            EventType type = (EventType)Random.Range(0, (int)EventType.EndPoint);
            Map[0].Add(new LocationInfo(index, 0, type));
        }
    }

    private int[] RouteCountThisFloor(List<LocationInfo> floor)
    {
        // 이전층의 List를 floor로 받아왔음 지금
        int[] possibleRoute = new int[maxXIndex];

        foreach(LocationInfo location in floor)
        {
            int index = location.Index;

            foreach (int move in moveable)
            {
                int nextX = index + move;
                if (CheckXPos(nextX))
                {
                    possibleRoute[nextX]++;
                }
            }
        }
        return possibleRoute;
    }

    private  void SelectRoute(LocationInfo location, int[] possibility)
    {
        int index = location.Index;
        int floor = location.Floor;
        List<int> selectList = new List<int>();

        foreach (int move in moveable)
        {
            int nextX = index + move;
            if (CheckXPos(nextX))
            {
                AddSelectList(selectList, possibility, nextX);
            }
        }

        int nextIndex = Util.SelectItemFromList(selectList);
        EventType type = (EventType)Random.Range(0, (int)EventType.EndPoint);
        Map[floor+1].Add(new LocationInfo(nextIndex, floor + 1,type));
        // 이때 시작점에도 추가해준다.
        location.RouteIndexs.Add(Map[floor+1].Count-1);
    }

    private bool CheckXPos(int x)
    {
        if (x < 0 || x >= maxXIndex)
        {
            return false;
        }
        return true;
    }

    private void AddSelectList(List<int> selectList, int[] possiblity, int x )
    {
        switch (possiblity[x])
        {
            case 1:
                for(int i =0; i< 3; i++)
                {
                    selectList.Add(x);
                }
                break;
            case 2:
                selectList.Add(x);
                break;
            default:
                break;
        }
    }

   
}

Clone this wiki locally