So basically, I think you are trying to make something like this
Roblox DungeonCreator Video.wmv (3.4 MB)
So I will just write the script that you will need
local roomsModel = game.Workspace.Rooms
local roomModel = game.ReplicatedStorage.Room
local function makeRooms(room, startRoomPos, roomsInX, roomsInZ)
local startRoom
local finishRoom
local xShift = 0
local zShift = 0
local xFloorSize = room.Floor.Size.X
local zFloorSize = room.Floor.Size.Z
for i = 1, roomsInZ do
xShift = 0
local roomForLaterPurpose
for i = 1, roomsInX do
local newRoom = room:Clone()
local newRoomCFrame = CFrame.new(startRoomPos + Vector3.new(-xShift, 0, -zShift))
newRoom:SetPrimaryPartCFrame(newRoomCFrame)
newRoom.Parent = roomsModel
roomForLaterPurpose = newRoom
if xShift == 0 and zShift == 0 then
startRoom = newRoom
end
xShift = xShift + xFloorSize
end
zShift = zShift + zFloorSize
if xShift >= roomsInX * xFloorSize and zShift >= roomsInZ * zFloorSize then
finishRoom = roomForLaterPurpose
end
end
return startRoom, finishRoom
end
local function openDoors(room1, room2)
local direction = room2.Center.Position - room1.Center.Position
local floorXSize = room1.Floor.Size.X
local floorZSize = room1.Floor.Size.Z
local doorToOpen1
local doorToOpen2
if direction == Vector3.new(0, 0, floorZSize) then
doorToOpen1 = room1.Doors:WaitForChild("Z")
doorToOpen2 = room2.Doors:WaitForChild("-Z")
elseif direction == Vector3.new(0, 0, -floorZSize) then
doorToOpen1 = room1.Doors:WaitForChild("-Z")
doorToOpen2 = room2.Doors:WaitForChild("Z")
elseif direction == Vector3.new(floorXSize, 0, 0) then
doorToOpen1 = room1.Doors:WaitForChild("X")
doorToOpen2 = room2.Doors:WaitForChild("-X")
elseif direction == Vector3.new(-floorXSize, 0, 0) then
doorToOpen1 = room1.Doors:WaitForChild("-X")
doorToOpen2 = room2.Doors:WaitForChild("X")
else
warn("Error in opening doors")
return
end
doorToOpen1.Transparency = 1
doorToOpen2.Transparency = 1
doorToOpen1.CanCollide = false
doorToOpen2.CanCollide = false
end
local function checkCenterPartAndOpen(position)
local roomReturn
local roomEligible = false
local size = Vector3.new(2, 2, 2)
local regionPoint1 = position - (size/2)
local regionPoint2 = position + (size/2)
local region = Region3.new(regionPoint1, regionPoint2)
local partsInRegion = workspace:FindPartsInRegion3(region)
if partsInRegion then
-- found room
for i, partInRegion in pairs(partsInRegion) do
if partInRegion:IsA("BasePart") and partInRegion.Name:find("Center") then
local room = partInRegion.Parent
if room.Closed.Value == false then
roomEligible = true
roomReturn = room
end
end
end
else
-- edge of maze
end
return roomEligible, roomReturn
end
local function findClosedRandomRoom()
local closedRooms = {}
local eligibleRooms = {}
-- find all closed rooms first
for i, room in pairs(roomsModel:GetChildren()) do
if room.Closed.Value == true then
table.insert(closedRooms, room)
end
end
-- check each side and make sure that there is atleast 1 open area
for i, room in pairs(closedRooms) do
local roomChoosable = false
local roomXSize = room.Floor.Size.X
local roomZSize = room.Floor.Size.Z
local checkPoint1 = room.Center.Position + Vector3.new(0, 0, roomZSize)
local checkPoint2 = room.Center.Position + Vector3.new(0, 0, -roomZSize)
local checkPoint3 = room.Center.Position + Vector3.new(roomXSize, 0, 0)
local checkPoint4 = room.Center.Position + Vector3.new(-roomXSize)
local room1Eligible = checkCenterPartAndOpen(checkPoint1)
local room2Eligible = checkCenterPartAndOpen(checkPoint2)
local room3Eligible = checkCenterPartAndOpen(checkPoint3)
local room4Eligible = checkCenterPartAndOpen(checkPoint4)
if room1Eligible == true or room2Eligible == true or room3Eligible == true or room4Eligible == true then
table.insert(eligibleRooms, room)
end
end
if #eligibleRooms == 0 then
print("No closed room found which has an open neighbour room")
return
end
-- now choose a random room to return
local randomNumber = math.random(1, #eligibleRooms)
local randomClosedRoom = eligibleRooms[randomNumber]
return randomClosedRoom
end
local function findRandomOpenNeighbourRoom(room)
local eligibleRooms = {}
local roomXSize = room.Floor.Size.X
local roomZSize = room.Floor.Size.Z
local checkPoint1 = room.Center.Position + Vector3.new(0, 0, roomZSize)
local checkPoint2 = room.Center.Position + Vector3.new(0, 0, -roomZSize)
local checkPoint3 = room.Center.Position + Vector3.new(roomXSize, 0, 0)
local checkPoint4 = room.Center.Position + Vector3.new(-roomXSize)
local room1Eligible, room1 = checkCenterPartAndOpen(checkPoint1)
local room2Eligible, room2 = checkCenterPartAndOpen(checkPoint2)
local room3Eligible, room3 = checkCenterPartAndOpen(checkPoint3)
local room4Eligible, room4 = checkCenterPartAndOpen(checkPoint4)
if room1Eligible == true then
table.insert(eligibleRooms, room1)
end
if room2Eligible == true then
table.insert(eligibleRooms, room2)
end
if room3Eligible == true then
table.insert(eligibleRooms, room3)
end
if room4Eligible == true then
table.insert(eligibleRooms, room4)
end
if #eligibleRooms == 0 then
print("No open neighbour rooms found")
return
end
local randomNumber = math.random(1, #eligibleRooms)
local randomOpenNeighbourRoom = eligibleRooms[randomNumber]
return randomOpenNeighbourRoom
end
local function reset()
for i, room in pairs(roomsModel:GetChildren()) do
room:Destroy()
end
end
local function makeDungeon(room, startRoomPos, roomsInX, roomsInZ)
reset()
local startRoom, finishRoom = makeRooms(room, startRoomPos, roomsInX, roomsInZ)
startRoom.Closed.Value = true
repeat
local closedRoom = findClosedRandomRoom()
if closedRoom then
local openNeighbourRoom = findRandomOpenNeighbourRoom(closedRoom)
openDoors(closedRoom, openNeighbourRoom)
openNeighbourRoom.Closed.Value = true
wait()
end
until closedRoom == nil
-- open all outside of finish
for i, door in pairs(finishRoom.Doors:GetChildren()) do
door.Transparency = 1
door.CanCollide = false
end
end
local roomsModel = game.Workspace.Rooms
local roomModel = game.ReplicatedStorage.Room
local roomsInX = 5
local roomsInZ = 5
wait(15)
makeDungeon(roomModel, roomModel.Center.Position, roomsInX, roomsInZ)
Now that is a really long script. So I will explain it slowly.
First of all, I’ll just tell that I used Prim’s algorithm for this.
So you will need to know prim’s algorithm first.
Prim’s algorithm is just an algorithm for making mazes and stuff like that. So how does it work?
Well, you will first have a few nodes connected randomly for example:
Now here’s what you have to do:
First, close the start node.
(I’m representing closed nodes as green and open nodes as red)
Now the next step is the most important it goes like this
repeat
find a random closed node which has an open neighbour
(for example in the above example, A is the closed node. And B and D are its neighbours.
So you just check whether any one of its neighbours(B or D) is open or not. if it’s not open then
choose another closed node)
Then you just choose any one of its open neighbours and close it
After closing its neighbour, open the doors between A and B
(I’m representing opening the door with a green line.)
until no more open nodes are nodes found
Example:
In the above A was the only closed node. So I chose that.
Then I chose the neighbour D and closed it. Then I opened the doors of A and D
And then I had to choose a node that had an open neighbour.
I chose A as it had an open neighbour
Then I chose the open neighbour B and closed it and opened the doors
And I will continue on like that
Then I chose the closed node D and chose the open neighbour G and closed G and made doors.
Then I chose closed node D and chose E as the open neighbour.
Then I chose the closed node E and chose open neighbour F
Then I chose the closed node F and open neighbour C
Then I chose the closed node F and open neighbour I
then I chose closed node I and open node H.
Now here’s the final result
Now that was just the explanation of the prim’s algorithm
Now I will briefly explain the script.
First, there are 6 functions -
- makeRooms(room, startRoomPos, roomsInX, roomsInZ)
Parameters -
room = You just have to give it an example of the room you want to duplicate
startRoomPos = It is just the starting room Position. (Note that the start room is always in the top left)
roomsInX = Just how many rooms you want in x Direction
roomsInZ = Just how many rooms you want in z Direction
Returns - startRoom and finishRoom
-
openDoors(room1, room2)
Parameters -
You just have to give it the two adjacent rooms and it will open the doors for both the rooms
-
checkCenterPartAndOpen(position)
Parameters -
position
This is a function that you just need for some calculation. Basically, it just checks if there is a room in the position and it also checks if the room is open
-
findClosedRandomRoom()
Parameters - none
So this function just finds a closed room which has an open room near it
Returns - the found node
-
findRandomOpenNeighbourRoom(room)
Parameters = room
So this function just selects a random open neighbour room of the parameter
Returns - the found node
-
reset()
Just resets some value to make another dungeon and delete the existing one
And then using all these functions, you combine them to make the main algorithm
local function makeDungeon(room, startRoomPos, roomsInX, roomsInZ)
reset()
local startRoom, finishRoom = makeRooms(room, startRoomPos, roomsInX, roomsInZ)
startRoom.Closed.Value = true
repeat
local closedRoom = findClosedRandomRoom()
if closedRoom then
local openNeighbourRoom = findRandomOpenNeighbourRoom(closedRoom)
openDoors(closedRoom, openNeighbourRoom)
openNeighbourRoom.Closed.Value = true
wait()
end
until closedRoom == nil
-- open all outside of finish
for i, door in pairs(finishRoom.Doors:GetChildren()) do
door.Transparency = 1
door.CanCollide = false
end
end
Well, if you don’t understand how the main function works, just look at this pseudo code
-- this is pseudo-code so do attempt to use this in scripts
local function makeDungeon(room, startRoomPos, roomsInX, roomsInZ)
reset()
makeRooms(roomModel, roomModel.Center.Position, roomsInX, roomsInZ)
repeat
local closedNode = findClosedRandomRoom()
if closedRoom then
local openNeighbourRoom = findRandomOpenNeighbourRoom(closedRoom)
open the doors of the closed room and open neighbour room
close the new neighbour node
wait()
end
until no more closed rooms are there that have an open neighbour
open all doors of the finishNode
end
And that’s the algorithm
If you want to know how to the other functions work, then you could try to understand them yourself or ask me
Setup of Dungeon
So now there are a few things to do before executing the code.
So first make the room you want to copy and put it in replicatedStorage
Then, it MUST HAVE the following as a CHILD and NOT ANY DESCENDANT
-
A boolean value set to false
-
A rectangular/square part Named (“Floor”) (the floor of the room)
-
A PrimaryPart named (“Center”) and it should be in the center of the rooms
-
It should also have a model named (“Doors”) with the same exact format of names
And also make sure that you have the doors placed exactly as given in the picture
Then, make sure that there is an empty model named (“Rooms”) in the workspace
So basically that’s it.
Sorry for making this post so long and if you have any questions, please do ask