how to make procedural dungeon generation (roblox)

225 Views Asked by At

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.

0

There are 0 best solutions below