How would i start making some sort of generation based of some "Cells"

wanted to create a random dungeon generation type system, but the rooms are like actually random layouts and stuff, couldn’t find much on it besides this one post

Video for lazy people

He actually made some cool looking generation thing,
i “somewhat” made the grid system
(most of it is taked / made off of his stuff, but with some extras added in to help)

and now im wondering how i would generate based on the area next to an area?
an idea i had was figuring out what each face to each cell has (wall, floor, door, escape door, ect) and generating based on that but not sure how to achieve said thing

Code

Module Script for grid

-- Variables
local NumberOfGeneratedGrids = 0
local NumberOfCellsGenerated = 0
local CellGen = require(script.CellGeneration)
local PartDebug = {}
local Debris = game:GetService("Debris")

-- Functions
local function TempDebugPart(P1, P2, P3, P4, P5)
	if #PartDebug > 0 then
		for i, v  in ipairs(PartDebug) do
			v:Destroy()
		end
	end

	local T_ = {P1, P2, P3, P4, P5}

	for i = 1, #T_ do
		local Part = Instance.new("Part")
		Part.Anchored = true
		Part.Size = Vector3.new(1,1,1)
		Part.Position = T_[i]

		local Highlight = Instance.new("Highlight", Part)
		Part.Parent = workspace
		table.insert(PartDebug, Part)
	end
end

local function TempDebugPart2(P1, P2, P3, P4, P5)
	local T_ = {P1, P2, P3, P4, P5}

	for i = 1, #T_ do
		local Part = Instance.new("Part")
		Part.Anchored = true
		Part.Size = Vector3.new(1,1,1)
		Part.Position = T_[i]

		local Highlight = Instance.new("Highlight", Part)
		Part.Parent = workspace
		Debris:AddItem(Part, 10)
	end
end

local function RangeCheck(Position, Corner1, Corner2)
	--TempDebugPart(Position, Corner1, Corner2) 
	local Check1
	local Check2

	local PosX, PosY, PosZ = Position.X, Position.Y, Position.Z
	local Corner1X, Corner1Y, Corner1Z = Corner1.X, Corner1.Y, Corner1.Z
	local Corner2X, Corner2Y, Corner2Z = Corner2.X, Corner2.Y, Corner2.Z

	if PosX < Corner2X and PosY < Corner2Y and PosZ < Corner2Z then
		Check1 = true
	end

	if PosX > Corner1X and PosY > Corner1Y and PosZ > Corner1Z then
		Check2 = true
	end

	if Check1 and Check2 then
		return true
	end
end

-- Cells are ordered as XZY
local Grid = {}
function Grid.New(X, Y, Z, cframe, CellSize, SendDelay)
	local self = setmetatable({}, Grid)
	NumberOfGeneratedGrids += 1

	self.CFrame = cframe
	self.TotalCells = X * Z * Y
	self.NumX = X
	self.NumZ = Z
	self.NumY = Y
	self.CellSize = CellSize
	self.Cells = {}

	for x = 1, X do
		self.Cells[x] = {}
		for z = 1, Z do
			self.Cells[x][z] = {}
			for y = 1, Y do
				local WorldCFrame = cframe + (Vector3.new(x,y,z) * CellSize)
				local Cell = CellGen.New(x, y, z, WorldCFrame, CellSize)
				Cell:Display()

				NumberOfCellsGenerated += 1
				self.Cells[x][z][y] = Cell
				if SendDelay then task.wait(SendDelay) end
			end	
		end
	end

	return self, true
end

function Grid:CellFromPosition(Position)
	for x = 1, self.NumX do
		for z = 1, self.NumZ do
			for y = 1, self.NumY do
				local cell = self.Cells[x][z][y]
				local CC1 = (cell["Size"]/2 + cell.Position)
				local CC2 = (-cell["Size"]/2 + cell.Position)

				local InRange = RangeCheck(Position, CC2, CC1)

				if InRange then
					return cell
				end
			end
		end
	end

	return false
end

function Grid:GetCellsInBetween(CellA, CellB)
	local cells = {}
	local cellsTable = self.Cells
	
	local X1 = math.abs(CellA.X - CellB.X)
	local Y1 = math.abs(CellA.Y - CellB.Y)
	local Z1 = math.abs(CellA.Z - CellB.Z)
	
	local X2 = math.min(CellA.X, CellB.X)
	local Y2 = math.min(CellA.Y, CellB.Y)
	local Z2 = math.min(CellA.Z, CellB.Z)
	
	Y1 += 1
	
	for x = 1, X1 do
		for z = 1, Z1 do
			for y = 1, Y1 do
				local Cell = cellsTable[X2+x-1][Z2+z-1][Y2+y-1]
				table.insert(cells, Cell)
			end
		end
	end
	
	return cells
end

function Grid:GetCellRegionCFrame(cf, Size)
	local halfCellSize = (self.CellSize/2)

	local CornerCFA = cf * CFrame.new(-halfCellSize.X, -halfCellSize.Y, -halfCellSize.Z)
	local CornerCFB = cf * CFrame.new(halfCellSize.X, halfCellSize.Y, halfCellSize.Z)
	
	PartDebug(cf.Position, CornerCFA.Position, CornerCFB.Position)
	
	local CellA, CellB = self:CellFromPosition(CornerCFA.Position), self:CellFromPosition(CornerCFB.Position)
	
	return self:GetCellsInBetween(CellA, CellB)
end

function Grid:GetCellRegionCells(CellA, CellB)
	return self:GetCellsInBetween(CellA, CellB)
end

function Grid.Info()
	print("Number of grids: " .. NumberOfGeneratedGrids)
	print("Number of cells: " .. NumberOfCellsGenerated)
end

function Grid.CellTablePartDebug(Table)
	for i, v in ipairs(Table) do
		TempDebugPart2(v["Position"])
	end
end

Grid.__index = Grid
return Grid

Module script for cells

local AllCells = {}
local CellPartDisplay = script.CellPartDisplay

local Cell = {}

function Cell.New(X, Y, Z, WorldCFrame, Size)
	local self = setmetatable({}, Cell)
	
	self.X = X
	self.Y = Y
	self.Z = Z
	self.Occuiped = false
	self.Size = Size
	
	self.WCF = WorldCFrame
	self.Position = WorldCFrame.Position
	
	table.insert(AllCells, self)
	return self
end

function Cell:Display()
	if not workspace.Terrain:FindFirstChild("DisplayParts") then
		local DisplayParts = Instance.new("Folder")
		DisplayParts.Name = "DisplayParts"
		DisplayParts.Parent = workspace.Terrain
	end
	
	local Folder = workspace.Terrain:FindFirstChild("DisplayParts")
	
	local DisplayPart = CellPartDisplay:Clone()
	DisplayPart.Size = self.Size
	DisplayPart.Parent = Folder
	DisplayPart.CFrame = self.WCF
	DisplayPart.T.TextLabel.Text = self.X .. ", " .. self.Y .. ", " .. self.Z
	DisplayPart.Name = "DisplayPart: " .. self.X .. ", " .. self.Y .. ", " .. self.Z 
end

local color = Color3.new(1,0,0)
Cell.__index = Cell
return Cell

Server Script
not really needed but this is what ive been testing

local GridGeneration = require(game.ReplicatedStorage.GridGeneration)

local CellSize = Vector3.new(20,10,20)
local CellCFrame = CFrame.new(1,1,1)

local XAmount = 20
local YAmount = 2
local ZAmount = 20

local Grid = GridGeneration.New(XAmount, YAmount, ZAmount, CellCFrame, CellSize)

local Cell1 = Grid:CellFromPosition(Vector3.new(26, 21.5, 80))
local Cell2 = Grid:CellFromPosition(Vector3.new(256, 17, 241))
local CellsInBetween = Grid:GetCellsInBetween(Cell1, Cell2)

print(CellsInBetween)

GridGeneration.CellTablePartDebug(CellsInBetween)

heres a little video of it working


(Edit)
Added something else in that i forgot to add before, also forgot to dash out some of the code

1 Like