Last active
January 15, 2022 17:21
-
-
Save Kutejnikov/bc89aee11330ae44c27d74c0ba4172fd to your computer and use it in GitHub Desktop.
A simple dungeon creation script for C# (with visualization in Unity)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 1. Create UI -> Image | |
// 2. Add this script to Image | |
// 3. Press Space in Game Mode | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.UI; | |
public class RecursiveDungeon : MonoBehaviour | |
{ | |
[SerializeField] Image image; | |
[SerializeField] int mapSizeHorizontal = 121; | |
[SerializeField] int mapSizeVertical = 81; | |
[SerializeField] int roomMinHorizontal = 11; | |
[SerializeField] int roomMinVertical = 9; | |
[SerializeField] int extraDoorChance = 15; | |
[SerializeField] int minLengthForExtraDoor = 40; | |
[SerializeField] int mapScale = 2; | |
int[,] maze; | |
void Awake() | |
{ | |
image = GetComponent<Image>(); | |
} | |
void Update() | |
{ | |
if (Input.GetKeyDown(KeyCode.Space)) CreateDungeon(); | |
} | |
void CreateDungeon() | |
{ | |
if (mapSizeHorizontal % 2 == 0) mapSizeHorizontal++; // Odd numbers only. | |
if (mapSizeVertical % 2 == 0) mapSizeVertical++; // Odd numbers only. | |
maze = new int[mapSizeHorizontal, mapSizeVertical]; | |
Division(1, mapSizeHorizontal - 2, 1, mapSizeVertical - 2); | |
image.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, mapSizeHorizontal * mapScale); | |
image.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, mapSizeVertical * mapScale); | |
Texture2D texture = new Texture2D(mapSizeHorizontal, mapSizeVertical); | |
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, mapSizeHorizontal, mapSizeVertical), Vector2.zero); | |
sprite.texture.filterMode = FilterMode.Point; | |
image.sprite = sprite; | |
for (int x = 0; x < mapSizeHorizontal; x++) | |
{ | |
for (int y = 0; y < mapSizeVertical; y++) | |
{ | |
if (x == 0 || y == 0 || x == mapSizeHorizontal - 1 || y == mapSizeVertical - 1) maze[x, y] = 1; | |
Color pixelColour = Color.black; | |
if (maze[x, y] == 1) pixelColour = Color.white; // wall | |
else if (maze[x, y] == 2) pixelColour = Color.black; // door | |
texture.SetPixel(x, y, pixelColour); | |
} | |
} | |
texture.Apply(); | |
} | |
void Division(int startX, int endX, int startY, int endY) | |
{ | |
if (endX - startX + 1 < roomMinHorizontal * 2 && endY - startY + 1 < roomMinVertical * 2) return; | |
if (endX - startX > endY - startY) | |
{ | |
if (endX - startX + 1 < roomMinHorizontal * 2) return; | |
CreateRoom(true, startX, endX, startY, endY); | |
} | |
else if (endX - startX < endY - startY) | |
{ | |
if (endY - startY + 1 < roomMinVertical * 2) return; | |
CreateRoom(false, startX, endX, startY, endY); | |
} | |
else | |
{ | |
if (Random.value > 0.5f) | |
{ | |
if (endX - startX + 1 < roomMinHorizontal * 2) return; | |
CreateRoom(true, startX, endX, startY, endY); | |
} | |
else | |
{ | |
if (endY - startY + 1 < roomMinVertical * 2) return; | |
CreateRoom(false, startX, endX, startY, endY); | |
} | |
} | |
} | |
void CreateRoom(bool isHorizontal, int startX, int endX, int startY, int endY) | |
{ | |
if (isHorizontal) | |
{ | |
int verticalWall = Random.Range((startX + roomMinHorizontal), endX + 1 - roomMinHorizontal); | |
if (verticalWall % 2 == 0) // Odd numbers only. | |
{ | |
verticalWall++; | |
if (verticalWall >= (endX + 1 - roomMinHorizontal)) verticalWall -= 2; | |
} | |
for (int i = startY; i <= endY; i++) | |
{ | |
maze[verticalWall, i] = 1; | |
} | |
int doorNumbers = 1; | |
if (extraDoorChance > Random.Range(0, 100) && endY - startY >= minLengthForExtraDoor) doorNumbers++; | |
for (int i = 0; i < doorNumbers; i++) | |
{ | |
int randomDoor = Random.Range(startY, endY + 1); | |
if (randomDoor % 2 != 0) | |
{ | |
randomDoor++; | |
if (randomDoor > endY) randomDoor -= 2; | |
} | |
maze[verticalWall, randomDoor] = 2; | |
} | |
Division(startX, verticalWall - 1, startY, endY); | |
Division(verticalWall + 1, endX, startY, endY); | |
} | |
else | |
{ | |
int horizontalWall = Random.Range(startY + roomMinVertical, endY + 1 - roomMinVertical); | |
if (horizontalWall % 2 == 0) // Odd numbers only. | |
{ | |
horizontalWall++; | |
if (horizontalWall >= endY + 1 - roomMinVertical) horizontalWall -= 2; | |
} | |
for (int i = startX; i <= endX; i++) | |
{ | |
maze[i, horizontalWall] = 1; | |
} | |
int doorNumbers = 1; | |
if (extraDoorChance > Random.Range(0, 100) && endX - startX >= minLengthForExtraDoor) doorNumbers++; | |
for (int i = 0; i < doorNumbers; i++) | |
{ | |
int randomDoor = Random.Range(startX, endX + 1); | |
if (randomDoor % 2 != 0) | |
{ | |
randomDoor++; | |
if (randomDoor > endX) randomDoor -= 2; | |
} | |
maze[randomDoor, horizontalWall] = 2; | |
} | |
Division(startX, endX, startY, horizontalWall - 1); | |
Division(startX, endX, horizontalWall + 1, endY); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment