728x90
전에 절차적 지향 맵 생성을 제작해 보았는데 이번에는 다른 알고리즘으로 동굴느낌의 맵을 생성하려고한다.
Unity2D 절차 지향적 맵 생성
2D 타일맵을 검색해 보면 BSP 알고리즘을 이용한 생성과 간단한 절차 지향적 알고리즘을 이용한 생성을 많이 소개합니다그중 절차 지향적으로 랜덤맵을 생성하는 방법을 시도해 보았습니다 결
rimugiri.tistory.com
셀룰러 오토마타라는 알고리즘을 약간 변형하여 사용한 것인데 유전자 알고리즘과 비슷하게 현재 세대가 다음세대에 영향을 미치고 변형하는 원리의 알고리즘이다.
i번째 세대에 어떤 셀이 빈공간이고 그 주변의 8칸중 5칸 이상이면 벽으로 3칸 이하면 빈공간 4칸이면 그대로 둔다 이렇게 되면 세대를 거듭 할때마다 최종적으로 특정 모양으로 이뤄진 공간이 남고 이 공간이 이어져 있으면 거대한 동굴이 형성되는 것이다
1. 생성 코드
- 전체적인 흐름만 이해하면 된다 초기에 가장자리를 벽으로 채워주고 랜덤으로 공간을 채워준다
- 다음으로는 step이 진행할때마다 위에 설명한 알고리즘으로 공간을 변형시켜간다
using System;
using UnityEngine;
namespace PKW_Tilemap
{
enum CaveTileType
{
EMPTY = 0,
WALL = 1,
}
public class RandomCaveGenerator : DungenGeneratorBase
{
[SerializeField] private RandomSquareSO _randomSquareSO;
[Range(0, 100)]
[SerializeField] private int _randomFillPercent;
public int wallLimit = 4;
public bool temp = false;
int[,] maps = null;
protected override void RunGenerator()
{
if (temp)
{
ResetMap();
temp = false;
}
if (maps == null)
{
Init();
}
else
{
SmoothMap();
}
}
private void SmoothMap()
{
for (int x = 0; x < _randomSquareSO.maxWidth; x++)
{
for (int y = 0; y < _randomSquareSO.maxHeight; y++)
{
int wallCount = GetSurroundingWallCount(x, y);
if (wallCount > wallLimit)
{
maps[x, y] = (int)CaveTileType.WALL;
}
else if (wallCount < wallLimit)
{
maps[x, y] = (int)CaveTileType.EMPTY;
}
PaintTile(x, y, maps[x, y]);
}
}
Debug.Log("Smooth Complete");
}
private int GetSurroundingWallCount(int x, int y)
{
int wallCount = 0;
for (int neighborX = x - 1; neighborX <= x + 1; neighborX++)
{
for (int neighborY = y - 1; neighborY <= y + 1; neighborY++)
{
// 범위 이상과 자기 자신은 제외한다
if (x == neighborX && y == neighborY) { continue; }
if (neighborX < 0 || neighborX >= _randomSquareSO.maxWidth || neighborY < 0 || neighborY >= _randomSquareSO.maxHeight)
{
wallCount++;
continue;
}
wallCount += maps[neighborX, neighborY];
}
}
return wallCount;
}
public void ResetMap()
{
maps = null;
}
private void Init()
{
int randomSeed = Time.time.GetHashCode();
System.Random randomNumber = new System.Random(randomSeed);
maps = new int[_randomSquareSO.maxWidth, _randomSquareSO.maxHeight];
for (int x = 0; x < _randomSquareSO.maxWidth; x++)
{
for (int y = 0; y < _randomSquareSO.maxHeight; y++)
{
// 가장자리는 벽으로 채워준다
if (x == 0 || x == _randomSquareSO.maxWidth - 1 || y == 0 || y == _randomSquareSO.maxHeight - 1)
{
maps[x, y] = (int)CaveTileType.WALL;
}
// 나머지는 설정한 랜덤 값으로 설정해 준다
else
{
maps[x, y] = (randomNumber.Next(0, 100) < _randomFillPercent) ? (int)CaveTileType.WALL :
(int)CaveTileType.EMPTY;
}
PaintTile(x, y, maps[x, y]);
}
}
Debug.Log("Init Complete");
}
void PaintTile(int x, int y, int tileType)
{
switch (tileType)
{
case (int)CaveTileType.EMPTY:
tilemapVisualizer.PaintEmptyTile(new Vector2Int(x, y));
break;
case (int)CaveTileType.WALL:
tilemapVisualizer.PaintCaveTile(new Vector2Int(x, y));
break;
}
}
}
}
2. 결과
728x90
'unity > 기술개발일지' 카테고리의 다른 글
2) TMPro 글자 모자이크처리 매우 간단한 방법 - 2D 게임 (0) | 2025.01.27 |
---|---|
2D 스토리게임 개발 1) PPU, TMPro (0) | 2025.01.27 |
2인용 간단한 pingpong 만들기 - Photon, firebase (0) | 2024.10.19 |
sprite sorting 설정 - 2D horror 게임 (0) | 2024.08.03 |
2D게임 제작후기 및 정리 - <투두두두> (0) | 2024.01.30 |