I'm trying to make a procedural dungeon generator where the rooms have random sizes and random positions in the x, y, and z axis. The problem is that I want that each room are connected with corridors and stairs. I tried using delaunay triangulation algorithm but that was too complex and I get an error every time.
for anyone that want to know the code, here is it:
local Dungeon = {}
--SETTINGS ------------------------------------------------------------------------------------------------------
local chest = false
model = Instance.new("Model",workspace)
local numchest = 0
local enemys = false
local numenemy = 0
local numdoors = math.random(1,10)
local Delaunay = require(game.ReplicatedStorage.delaunator)
local function createPart(sizex,sizey,sizez,px,py,pz)
local part = Instance.new("Part",model)
part.TopSurface = Enum.SurfaceType.Universal
part.BottomSurface = Enum.SurfaceType.Universal
part.RightSurface = Enum.SurfaceType.Universal
part.LeftSurface = Enum.SurfaceType.Universal
part.BackSurface = Enum.SurfaceType.Universal
part.FrontSurface = Enum.SurfaceType.Universal
part.Anchored = true
part.Size = Vector3.new(sizex,sizey,sizez)
part.Position = Vector3.new(px,py,pz)
if math.random(1,100) == 1 then
part.BrickColor = BrickColor.Random()
elseif math.random(1,10000) == 1 then
local text = part
local add = 10
wait(1)
local k = 1
while k <= 255 do
text.Color = Color3.new(k/255,0/255,0/255)
k = k + add
wait()
end
while true do
k = 1
while k <= 255 do
text.Color = Color3.new(255/255,k/255,0/255)
k = k + add
wait()
end
k = 1
while k <= 255 do
text.Color = Color3.new(255/255 - k/255,255/255,0/255)
k = k + add
wait()
end
k = 1
while k <= 255 do
text.Color = Color3.new(0/255,255/255,k/255)
k = k + add
wait()
end
k = 1
while k <= 255 do
text.Color = Color3.new(0/255,255/255 - k/255,255/255)
k = k + add
wait()
end
k = 1
while k <= 255 do
text.Color = Color3.new(k/255,0/255,255/255)
k = k + add
wait()
end
k = 1
while k <= 255 do
text.Color = Color3.new(255/255,0/255,255/255 - k/255)
k = k + add
wait()
end
while k <= 255 do
text.Color = Color3.new(255/255 - k/255,0/255,0/255)
k = k + add
wait()
end
end
end
return part
end
function Dungeon.createRoom()
roomsizex = math.random(5, 100)
roomsizey = math.random(6, 100)
roomsizez = math.random(5, 100)
local posX = math.random(-500, 500)
local posY = math.random(-500, 500)
local posZ = math.random(-500, 500)
local roomReg = createPart(roomsizex, roomsizey, roomsizez, math.random(-500, 500), math.random(-10, 10), math.random(-500, 500))
-- Create walls relative to the roomReg position
local wallL = createPart(1, roomsizey, roomsizez, roomReg.Position.X - roomsizex / 2 - 0.5, roomReg.Position.Y, roomReg.Position.Z)
wallL.Name = "LeftWall"
local wallR = createPart(1, roomsizey, roomsizez, roomReg.Position.X + roomsizex / 2 + 0.5, roomReg.Position.Y, roomReg.Position.Z)
wallR.Name = "RightWall"
local wallT = createPart(roomsizex + 1, 1, roomsizez, roomReg.Position.X, roomReg.Position.Y + roomsizey / 2 + 0.5, roomReg.Position.Z)
wallT.Name = "TopWall"
local wallB = createPart(roomsizex + 1, 1, roomsizez, roomReg.Position.X, roomReg.Position.Y - roomsizey / 2 - 0.5, roomReg.Position.Z)
wallB.Name = "BottomWall"
local wallF = createPart(roomsizex, roomsizey + 1, 1, roomReg.Position.X, roomReg.Position.Y + roomsizey / 1000, roomReg.Position.Z + roomsizez / 2)
wallF.Name = "FrontWall"
local wallBack = createPart(roomsizex, roomsizey + 1, 1, roomReg.Position.X, roomReg.Position.Y + roomsizey / 1000, roomReg.Position.Z - roomsizez / 2)
wallBack.Name = "BackWall"
-- DOORS ----------------------------------------------------------------------------
local numDoors = math.random(1, 6) -- Change the range as needed
local doorPositions = {
CFrame.new(roomReg.Position.X - roomsizex / 2 + 1.5, roomReg.Position.Y - roomsizey/ 2 , roomReg.Position.Z),
CFrame.new(roomReg.Position.X + roomsizex / 2 - 1.5, roomReg.Position.Y - roomsizey/ 2, roomReg.Position.Z),
CFrame.new(roomReg.Position.X, roomReg.Position.Y - roomsizey/ 2 , roomReg.Position.Z - roomsizex / 2 + 0.5),
CFrame.new(roomReg.Position.X, roomReg.Position.Y - roomsizey/ 2 , roomReg.Position.Z + roomsizex / 2 - 0.5),
CFrame.new(roomReg.Position.X / 2.5, roomReg.Position.Y - roomsizey/ 2 , roomReg.Position.Z + roomsizez / 2 - 0.5),
CFrame.new(roomReg.Position.X / 2.5, roomReg.Position.Y - roomsizey / 2, roomReg.Position.Z - roomsizez / 2 + 0.5)
}
-- Randomly select unique door positions
local selectedDoorPositions = {}
for i = 1, math.min(numDoors, #doorPositions) do
local randomIndex = math.random(1, #doorPositions)
table.insert(selectedDoorPositions, doorPositions[randomIndex])
table.remove(doorPositions, randomIndex)
end
for _, doorPos in ipairs(selectedDoorPositions) do
local door = createPart(5, 5, 5, doorPos.X, doorPos.Y, doorPos.Z)
door.Name = "Door"
door.BrickColor = BrickColor.new("Bright red")
local code = script.Script:Clone()
code.Parent = door
code.Enabled = true
door.Touched:Connect(function(otherPart)
local character = otherPart.Parent
if character:IsA("Model") and character:FindFirstChild("Humanoid") then
door:Destroy()
Dungeon.createRoom()
wait(1)
model:Destroy()
wallBack:Destroy()
end
end)
end
if math.random(1,10) == 1 then
enemys = true
wait(1)
enemys = false
end
if enemys == true then
for i = 1,numenemy do
local part = Instance.new("Part",workspace)
part.Name = "saadadadddasd"
part.Position = wallB.Position
end
end
end
return Dungeon
Here is the code that generates the room :
for i = 1,math.random(4,30) do
require(game.ReplicatedStorage.Dungeon).createRoom()
wait(1)
end
here is what I tried: since the roomreg (room region) is the center of the room, I tried to connect the room to every room and used the MST (Minimum Spanning Tree) to like make it not overlap with other rooms and it was too complicated and I want some help.
Things that I expect: I'm expecting doors that leads to corridors that connects to each rooms and stairs for the room that are above.