내일배움캠프 36일차 TIL - 절차적 생성

권태하·2024년 6월 5일
post-thumbnail
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MakeForest1 : MonoBehaviour
{
    [SerializeField] private int width;   // 47, 47
    [SerializeField] private int height;

    [SerializeField] private string seed;
    [SerializeField] private bool useRandomSeed;

    [Range(0, 100)]
    [SerializeField] private int randomeFillPercent;
    [SerializeField] private int smoothNum;
    [SerializeField] private int interval;
    [SerializeField] private int treeRand;
    [SerializeField] private int startArea;

    private int[,] map;
    private const int Road = 0;
    private const int Wall = 1;

    public GameObject treeOj;



    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.P))
        {
            GenerateMap();
        }
    }

    private void GenerateMap()
    {
        map = new int[width, height];
        MapRandomFill();

        for (int i = 0; i < smoothNum; i++)
        {
            SmoothMap();
        }

        SetTree();
    }

    private void SetTree()
    {
        for (int x = 0; x < width; x += interval)
        {
            for (int y = 0; y < height; y += interval)
            {
                if (map[x, y] == Wall)
                {
                    int randX = UnityEngine.Random.Range(-treeRand, treeRand + 1);
                    int randY = UnityEngine.Random.Range(-treeRand, treeRand + 1);
                    Instantiate(treeOj, new Vector3(x - (width * 0.5f) + (interval * 0.5f) + randX, 0, y - (height * 0.5f) + (interval * 0.5f) + randY), Quaternion.identity);
                }
            }
        }
    }

    private void MapRandomFill()
    {
        if (useRandomSeed)     // 랜덤 시드 사용
        {
            seed = Time.time.ToString();
        }

        System.Random rand = new System.Random(seed.GetHashCode()); //  시드값을 해시코드로 변환

        for (int x = 0; x < width; x += interval)
        {
            for (int y = 0; y < height; y += interval)
            {
                //if (x == 0 || x == width - interval || y == 0 || y == height - interval)
                //{
                //    map[x, y] = Wall;  // 맵의 가장자리는 벽으로 채움
                //}
                //else
                //{
                    map[x, y] = rand.Next(0, 100) < randomeFillPercent ? Wall : Road; // 랜덤으로 벽을 생성
            //}
             }
        }
    }
    private void SmoothMap()
    {
        for (int x = 0; x < width; x += interval)
        {
            for (int y = 0; y < height; y += interval)
            {
                int neighbourWallTiles = GetSurroundingWallCount(x, y);
                if (neighbourWallTiles > 4)
                {
                    map[x, y] = Wall;  // 벽이 5개 이상이면 벽으로 채움
                }
                else if (neighbourWallTiles < 4)
                {
                    map[x, y] = Road;  // 벽이 3개 이하면 길로 채움
                }

                if (x < (width * 0.5 + startArea - interval) && x > (width * 0.5 - startArea) && y < (height * 0.5 + startArea - interval) && y > (height * 0.5 - startArea))
                {
                    map[x, y] = Road;  // 시작지점은 길로 채움
                }
            }
        }
    }

    private int GetSurroundingWallCount(int gridX, int gridY)
    {
        int wallCount = 0;

        for (int neighbourX = gridX - interval; neighbourX <= gridX + interval; neighbourX += interval)
        {
            for (int neighbourY = gridY - interval; neighbourY <= gridY + interval; neighbourY += interval)     // 현재 좌표를 기준으로 주변 8칸 검사
            {
                if ((neighbourX >= 0) && (neighbourX < width) && (neighbourY >= 0) && neighbourY < height) // 맵을 초과하지 않는 조건문으로 검사
                {
                    if (neighbourX != gridX || neighbourY != gridY)
                    {
                        wallCount += map[neighbourX, neighbourY]; // 현재 좌표가 아니면 벽의 갯수를 증가
                    }
                }
                else wallCount++; // 맵을 초과하면 벽의 갯수를 증가
            }
        }
        return wallCount;
    }
}
profile
스터디 로그

0개의 댓글