유니티

로그라이크 - BoardManager.cs

hololol 2019. 6. 24. 11:08
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System; //자동완성으로 SerializeField를 쓰려면 이 namespace 써야함
using Random = UnityEngine.Random; //랜덤으로 위치를 정해야함

public class BoardManager : MonoBehaviour
{
    [SerializeField]
    public class Count
    {
        //필드(변수), 생성자(초기값), 메소드
        public int minCount; //최대값
        public int maxCount; //최소값

        public Count(int min, int max) //생성자, min max를 초기값으로
        {
            minCount = min;
            maxCount = max;
        }

    }


    public int columns = 8; //열의 개수, 보드판의 열
    public int rows = 8; //보드판의 행
    //배열은 0번부터 시작하니 보드판의 위치는 0~7 까지임
    //      (7,7)
    //(0,0)


    public Count wallCount = new Count(5, 9);//Count의 클래스를 가지고 값을 선언한다, 생성자로 값 초기화
    public Count foodCount = new Count(1, 5); //food는 1개부터 5개까지



    public GameObject exit;
    public GameObject[] floorTiles; //바닥의 종류를 랜덤으로 결정
    public GameObject[] wallTiles; //벽(장애물)의 종류를 랜덤으로 결정
    public GameObject[] foodTiles;  //food
    public GameObject[] outerwallTiles; //바깥쪽 벽, 절대로 넘어갈 수 없는 outwall
    public GameObject[] enemyTiles;

    //List의 장점. 삽입 삭제가 용이함. 배열과 똑같은 존재
    List<Vector3> gridPositions = new List<Vector3>();//위치 정보를 담음, 생성자를 이용해 만듦, 위치가 비어있지 않은가
    Transform boardHolder;//보드를 정리해주는 역할


    //게임이 시작될 때 마다 호출
    void InitializeList() //위치정보를 넣고 초기화하겠다
    {
        gridPositions.Clear(); //리스트를 지움


        for (int x = 1; x < columns - 1; x++)//1~6까지, x값
        {
            for (int y = 1; y < rows - 1; y++)//1~6까지, y값
            {
                gridPositions.Add(new Vector3(x, y, 0)); //List는 Add. 2D니까 z는0, 위치정보를 grid에 넣음
            }
        }
    }

    //보드판 만들기. 외벽과 안쪽 바닥을 특정한 위치에 생성한다
    void BoardSetup()
    {

        boardHolder = new GameObject("boardHolder").transform; //대신 스크립트로

        //외벽은 (-1,-1) 부터
        for (int x = -1; x < columns + 1; x++)
        {
            for (int y = -1; y < rows + 1; y++)
            {
                //floor중에 랜덤으로 오브젝트 생성
                GameObject obj = floorTiles[Random.Range(0, floorTiles.Length)];

                //x가 -1이거나 colums가 가장 바깥쪽이거나 y가 -1이거나, y가 rows랑 같다면
                if (x == -1 || x == columns || y == -1 || y == rows)
                    //obj에 바깥쪽 벽이 생성되도록 해야함
                    obj = outerwallTiles[Random.Range(0, outerwallTiles.Length)];

                //obj를 생성한다
                GameObject _object = Instantiate(obj, new Vector3(x, y, 0), Quaternion.identity);//임시변수, 타일 까는거니 회전필요x
                _object.transform.SetParent(boardHolder);//boardHolder가 부모가 되도록 선언
            }
        }

    }

    //Vector3의 반환형을 가지는 함수
    Vector3 RandomPosition()
    {   
        //(1,1)~(6,6) 36개의 위치정보를 담는다
        int randomIndex = Random.RandomRange(0, gridPositions.Count);//랜덤위치
        Vector3 pos = gridPositions[randomIndex]; //List의 gridPosition을 pos에 저장. 
        gridPositions.RemoveAt(randomIndex); //삭제 
        return pos; //gridPosition의 pos 리턴
    }


    //배치
    void LayoutObjectAtRandom(GameObject[] tileArray, Count count)
    {
        //Count가 가지는 최대, 최소 중에 랜덤으로 수를 결정 
        int objectCount = Random.Range(count.minCount, count.maxCount + 1);
        //+1을 안쓰면 만약 5,9면 5~8밖에 안생김 그래서 +1을 써야함

        for (int i = 0; i < objectCount; i++) //objectCount만큼 반복해서 생성
        {
            //메소드를 호출해서 위치하나를 가져온다
            Vector3 pos = RandomPosition(); //새 위치 랜덤으로 받고
            GameObject tileChoose = tileArray[Random.Range(0, tileArray.Length)];
            //tileArray의 길이보다 작은만큼 random으로 타일을 고른다

            Instantiate(tileChoose, pos, Quaternion.identity);
                
        }

    }

    //1단계 2단계 3단계 레벨을 매개변수로 받는다
    public void SetupScene(int level)
    {
        int num = (int)Mathf.Log(level, 2); //로그2의레벨. 1~3까지는 한마리, 4~8은 두마리.
        Count enemyCount = new Count(num, num);
        BoardSetup();
        InitializeList();
        LayoutObjectAtRandom(wallTiles, wallCount);
        LayoutObjectAtRandom(foodTiles, foodCount); //foodTiles의 최대 최소 중 랜덤으로 만들어라
        


        LayoutObjectAtRandom(enemyTiles, enemyCount);
        Instantiate(exit, new Vector3(columns - 1, rows - 1), Quaternion.identity); //exit 생성
    }


}