I made scripts that generate parts based on what you need. It is tested.
My script requires another script in server script service, to make kill blocks. This is that other script.
local CollectionService = game:GetService("CollectionService")
for _, part in CollectionService:GetTagged("KillBlock") do
part.Touched:Connect(function(hit)
if hit and hit.Parent and hit.Parent:FindFirstChild("Humanoid") then
hit.Parent.Humanoid.Health = 0
end
end)
end
This script works as a server script in workspace.
local function createBeastGrid(gridWidth: IntValue, gridHeight: IntValue)
local grid = {}
local goDowns = 0
local x = math.random(2,gridWidth-1)
local y = 1
local needle
local done = false
local blockCornerConnections = 1 -- 0 is false, 1 is true
-- Fill the table with empty values
for i = 1, gridWidth do
grid[i] = {}
for j = 1, gridHeight do
grid[i][j] = 0
end
end
-- generate a path foreward, but keep your distance from your own path
-- also, always go in one direction (mostly)
-- 0 is right, 90 is up, 180 is left, 270 is down.
while done == false do
local goodDirections = {0,90,180,270}
-- set the current tile
grid[x][y]=1
if y == gridHeight then
return grid;
end
-- dont leave the grid
if x == 1 then
needle = table.find(goodDirections,180)
if needle ~= nil then
table.remove(goodDirections,needle)
end
end
if x == gridWidth then
needle = table.find(goodDirections,0)
if needle ~= nil then
table.remove(goodDirections,needle)
end
end
if y == 1 then
needle = table.find(goodDirections,270)
if needle ~= nil then
table.remove(goodDirections,needle)
end
end
-- check right edge
if grid[math.clamp(x+1,1,gridWidth)][y] + grid[math.clamp(x+1,1,gridWidth)][math.clamp(y+1,1,gridHeight)] + grid[math.clamp(x+1,1,gridWidth)][math.clamp(y-1,1,gridHeight)] + (grid[math.clamp(x+2,1,gridWidth)][math.clamp(y-1,1,gridHeight)] * blockCornerConnections)>0 then
needle = table.find(goodDirections,0)
if needle ~= nil then
table.remove(goodDirections,needle)
end
end
-- check left edge
if grid[math.clamp(x-1,1,gridWidth)][y] + grid[math.clamp(x-1,1,gridWidth)][math.clamp(y+1,1,gridHeight)] + grid[math.clamp(x-1,1,gridWidth)][math.clamp(y-1,1,gridHeight)] + (grid[math.clamp(x-2,1,gridWidth)][math.clamp(y-1,1,gridHeight)] * blockCornerConnections)>0 then
needle = table.find(goodDirections,180)
if needle ~= nil then
table.remove(goodDirections,needle)
end
end
-- check upper edge
if grid[x][math.clamp(y+1,1,gridHeight)] + grid[math.clamp(x-1,1,gridWidth)][math.clamp(y+1,1,gridHeight)] + grid[math.clamp(x+1,1,gridWidth)][math.clamp(y+1,1,gridHeight)]>0 then
needle = table.find(goodDirections,90)
if needle ~= nil then
table.remove(goodDirections,needle)
end
end
-- check lower edge
if grid[x][math.clamp(y-1,1,gridHeight)] + grid[math.clamp(x-1,1,gridWidth)][math.clamp(y-1,1,gridHeight)] + grid[math.clamp(x+1,1,gridWidth)][math.clamp(y-1,1,gridHeight)] + grid[x][math.clamp(y-2,1,gridHeight)] + ((grid[math.clamp(x-1,1,gridWidth)][math.clamp(y-2,1,gridHeight)] + grid[math.clamp(x+1,1,gridWidth)][math.clamp(y-2,1,gridHeight)]) * blockCornerConnections)>0 then
needle = table.find(goodDirections,270)
if needle ~= nil then
table.remove(goodDirections,needle)
end
end
-- limit going down to happen only once
if goDowns>0 then
needle = table.find(goodDirections,270)
if needle ~= nil then
table.remove(goodDirections,needle)
end
end
-- never go down on the edge of the table
if x <= 2 or x >= gridWidth-1 then
needle = table.find(goodDirections,270)
if needle ~= nil then
table.remove(goodDirections,needle)
end
end
local chosenDirection
if #goodDirections > 0 then
chosenDirection = goodDirections[ math.random(1, #goodDirections ) ]
-- make left and right more common than up and down
if math.random(1,2) == 1 and (chosenDirection == 90 or chosenDirection == 270) then
chosenDirection = goodDirections[ math.random(1, #goodDirections ) ]
end
else
done = true
end
if chosenDirection == 270 then
goDowns += 1
end
if chosenDirection == 90 then
goDowns = math.max(goDowns-1,0)
end
-- go toward the chosen direction
if chosenDirection == 0 then
x += 1
end
if chosenDirection == 180 then
x -= 1
end
if chosenDirection == 90 then
y += 1
end
if chosenDirection == 270 then
y -= 1
end
end
return nil
end
local beastGridWidth = 10
local beastGridHeight = 20
local generationFailed = true
while generationFailed == true do
local beastGrid = createBeastGrid(beastGridWidth, beastGridHeight)
-- generate the physical grid do
if beastGrid ~= nil then
generationFailed = false
for x = 1, beastGridWidth do
for y = 1, beastGridHeight do
--print('see me')-- seen
local beastTile = Instance.new("Part")
beastTile.Size = Vector3.new(9,0.5,9)
beastTile.Position = Vector3.new(x*10,0.25,y*10)
beastTile.Color = Color3.new(1, 0.333333, 0)
if beastGrid[x][y] == 0 then
beastTile:AddTag("KillBlock")
else
beastTile.Color = Color3.new(0.333333, 1, 0.498039)
end
beastTile.Anchored = true
beastTile.Parent = workspace
end
end
end
end
Edit: Grammar fix. Scripts not changed.
Edit 2: Added an extra check to âcheck lower edgeâ. (avoids path connects.)
Edit 3: Added a switch to control corner connections.
Edit 4: Somehow, generation can still fail sometimes⌠The scriot now re-generates the grid if it fails to generate. Iâll keep working on it. I couldnât get the function to fail. Maybe itâs a roblox bug or something. I do know that the re-generation always works, so I guess itâs done.
Edit 5: goDowns was intended to go down as you go up. It does now. My mistake.
Edit 6: ânever go down on the edge of the tableâ now has a thicker boundary. this will reduce failed generations.