I’m trying to make voxel-based generation. But I’m stumped on trying to generate grass using perlin noise.
Here’s the code:
local TERRAIN_GENERATION = {}
--// SERVICES
local S_RUN = game:GetService("RunService")
local S_RS = game:GetService("ReplicatedStorage")
--// CONSTANTS
local BLOCK_SIZE = 3
local GRID_SIZE = 48 -- blocks
local MAX_HEIGHT = 25
local MIN_HEIGHT = -25
local FREQUENCY = 10
local SCALE = 200
local AMPLITUDE = 8
local STONE_LEVEL = -10
--[PRIVATE]--
--// Generates blocks on surface level
local function generate_surface(seed)
local blocks = {}
local surface_y = {}
for x = 1, GRID_SIZE, 1 do
blocks[x] = {}
surface_y[x] = {}
for z = 1, GRID_SIZE, 1 do
blocks[x][z] = {}
local y = math.floor(
math.noise((x / SCALE) * FREQUENCY, (z / SCALE) * FREQUENCY, seed) * AMPLITUDE
)
local block = S_RS.ITEMS.BLOCKS["Grass Block"]:Clone()
block.Parent = workspace.MAP
block.Position = Vector3.new(x * BLOCK_SIZE, y * BLOCK_SIZE, z * BLOCK_SIZE)
surface_y[x][z] = y
blocks[x][z][y] = block
end
end
local values_returned = {blocks, surface_y}
return values_returned
end
local function generate_grass(blocks: {}, surface_y: {})
local grass = S_RS.ITEMS.BLOCKS.Grass
local grass_size = grass.PrimaryPart.Size
local width_difference = (BLOCK_SIZE - grass_size.X) / 2 * 100
local y_difference = (BLOCK_SIZE - grass_size.Y)
for x, x_blocks in blocks do
for z, z_blocks in x_blocks do
-- 25% of a surface block having grass
if math.random(100) < 25 then
local grass = grass:Clone()
grass.Parent = workspace.MAP
local y_level = surface_y[x][z] + 1
grass:PivotTo(CFrame.new(
(x * BLOCK_SIZE + math.random(-width_difference, width_difference) / 100 + math.random(0.1, 0.2)),
(y_level * 3 - y_difference / 2),
(z * BLOCK_SIZE + math.random(-width_difference, width_difference) / 100) + math.random(0.1, 0.2))
)
blocks[x][z][y_level] = "Grass"
end
end
end
end
local function generate_below_surface(blocks: {}, surface_y: {})
for x, x_blocks in blocks do
for z, z_blocks in x_blocks do
local surface_level = surface_y[x][z]
for y = MAX_HEIGHT, MIN_HEIGHT, -1 do
if y >= surface_level then continue end
local block = S_RS.ITEMS.BLOCKS["Dirt"]:Clone()
block.Parent = workspace.MAP
block.Position = Vector3.new(x * BLOCK_SIZE, y * BLOCK_SIZE, z * BLOCK_SIZE)
blocks[x][z][y] = block
--if y < math.random(STONE_LEVEL - 2, STONE_LEVEL + 2) then
--local block = S_RS.ITEMS["Stone"]:Clone()
--block.Parent = workspace.MAP
--block.Position = Vector3.new(x * BLOCK_SIZE, y * BLOCK_SIZE, z * BLOCK_SIZE)
--blocks[x][z][y] = block
--end
end
end
end
end
--[PUBLIC]--
function TERRAIN_GENERATION.generate(seed)
local surface_blocks = generate_surface(seed)
local grass = generate_grass(surface_blocks[1], surface_blocks[2])
--local below_surface_blocks = generate_below_surface(surface_blocks[1], surface_blocks[2])
end
return TERRAIN_GENERATION
Any help is greatly appreciated.
