local Part = Instance.new("Part") --For cloning
Part.Anchored = true
Part.FormFactor = "Custom"
Part.Size = Vector3.new(4,4,4)
Part.TopSurface = "Smooth"
local seed = math.random(1, 10e6)
local frequency = 3
local power = 20
local resolution = 256
for x = 1, resolution do
for z = 1, resolution do
local y1 = math.noise(
(x*frequency)/resolution,
(z*frequency)/resolution,
seed
)
local y2 = math.noise(
(x*frequency*.125)/resolution,
(z*frequency*.125)/resolution,
seed
)
local y3 = math.noise(
(x*frequency*4)/resolution,
(z*frequency*4)/resolution,
seed
)
local y = (y1*y2*power*power)+y3
local Part = Part:Clone()
Part.Parent = game.Workspace.Map
Part.CFrame = CFrame.new(x,y,z)
--[[if math.abs(y2) < .1 then
Part.BrickColor = BrickColor.Green()
elseif math.abs(y2) > .25 then
Part.BrickColor = BrickColor.Red()
else
Part.BrickColor = BrickColor.Blue()
end]]
end
end
This code generates a random map using Perlin Noise and Parts. I want to add trees, water, and biomes to this how can I do that?
For trees, assuming you only want trees to spawn where land is, you can user a second perlin noise and layer it on top. For example, after
local Part = Part:Clone()
Part.Parent = game.Workspace.Map
Part.CFrame = CFrame.new(x,y,z)
you can do:
local c = 0.4 -- c is some constant you use to customise how the noise feels
local threshold = 0.1 -- the TreeChance needs to be greater than this to spawn a tree
local TreeChance = math.noise(x * frequency * c / resolution, z * frequency * c / resolution, seed)
if TreeChance > threshold then
-- Add a tree on top this part
end
Play around with the threshold value and c to get the results you like. Remember math.noise returns a value between -0.5 and 0.5, so don’t let the threshold be 0.5 or greater, otherwise no trees will ever spawn.
If you wanted the water to appear you would check if the block below it spawns below the water level.
local Part = Instance.new("Part") --For cloning
Part.Anchored = true
Part.FormFactor = "Custom"
Part.Size = Vector3.new(4,4,4)
Part.TopSurface = "Smooth"
local seed = math.random(1, 10e6)
local frequency = 3
local power = 20
local resolution = 256
local WaterLevel = 0 --We store the level the water spawns below
for x = 1, resolution do
for z = 1, resolution do
local y1 = math.noise(
(x*frequency)/resolution,
(z*frequency)/resolution,
seed
)
local y2 = math.noise(
(x*frequency*.125)/resolution,
(z*frequency*.125)/resolution,
seed
)
local y3 = math.noise(
(x*frequency*4)/resolution,
(z*frequency*4)/resolution,
seed
)
local y = (y1*y2*power*power)+y3
local Part = Part:Clone()
Part.Parent = game.Workspace.Map
Part.CFrame = CFrame.new(x,y,z)
if z%resolution/2==resolution/4 then
wait(0)
end
--[[if math.abs(y2) < .1 then
Part.BrickColor = BrickColor.Green()
elseif math.abs(y2) > .25 then
Part.BrickColor = BrickColor.Red()
else
Part.BrickColor = BrickColor.Blue()
end]]
if y+(Part.Size.Y/2)<WaterLevel then -- We check if water is able to spawn.
print(WaterLevel-y+(Part.Size.Y/2))
local WaterPart=Part:Clone()
WaterPart.CanCollide=false -- We set some values to the water.
WaterPart.Transparency=0.5
WaterPart.Reflectance=0.1
WaterPart.Size=Vector3.new(4,WaterLevel-y+(Part.Size.Y/2),1)
WaterPart.BrickColor=BrickColor.new("Cyan")
WaterPart.CFrame=CFrame.new(x,y+(WaterLevel-y+(Part.Size.Y/2))/2,z)
WaterPart.Parent=workspace.Map
end
end
end
thanks for the code is this what I am supposed to do?
local c = 0.4 -- c is some constant you use to customise how the noise feels
local threshold = 0.1 -- the TreeChance needs to be greater than this to spawn a tree
local TreeChance = math.noise(x * frequency * c / resolution, z * frequency * c / resolution, seed)
if TreeChance > threshold then
local Tree = game.Workspace.Tree:Clone()
Tree.Parent = workspace.Map
Tree.CFrame = CFrame.new(x,y,z)
end
Yes, pretty much, but you would want to set the CFrame of the tree to slightly higher than the block otherwise it will spawn in the same place as the block. Perhpas try this:
Tree.CFrame = CFrame.new(x, y + 5, z) -- using 5 as a constant so all trees will be 5 studs above the block
Or you could calculate the height of the tree and use that:
local TreeHeight = Tree.Size.Y
local PartHeight = Part.Size.Y
-- I split it up here to make it more clear what is happening:
local TreeY = y + PartHeight / 2 + TreeHeight / 2
-- You take the Y value of the part and add half the height of the part and half the height of the tree.
Tree.CFrame = CFrame.new(x, TreeY, z)
In the code you don’t have to have TreeHeight, PartHeight and TreeY as variables, but it helps organise the code and makes it more intuitive to understand.
I believe there is a problem with your calculation of x and z. When you use perlin noise, you would usually multiply the x and z values by the width and depth of the blocks respectively. Otherwise the blocks would all overlap, and so would the trees. For example, you would do this:
Part.CFrame = CFrame.new(x * Part.Size.X, y, z * Part.Size.Z)
-- ...
Tree.CFrame = CFrame.new(x * Part.Size.X, TreeY, z * Part.Size.Z)
Ideally you would have a constant outside of the for loop with the scale of the blocks,
-- Before for loop
local Scale = Part.Size
-- For loop
for x = 1, resolution do
for z = 1, resoluation do
-- ...
Part.CFrame = CFrame.new(x * Scale.X, y, z * Scale.Z)
-- ...
Tree.CFrame = CFrame.new(x * Scale.X, TreeY, z * Scale.Z)
end
end
(Trees are the brown cylinders and the Parts are the green blocks)
Here is my script (I changed a few things, but I commented on what I chenged):
local Part = Instance.new("Part") --For cloning
Part.Anchored = true
Part.FormFactor = "Custom"
Part.Size = Vector3.new(4,4,4)
Part.TopSurface = "Smooth"
-- Added this to make the part more visible
Part.BrickColor = BrickColor.new("Forest green")
local seed = math.random(1, 10e6)
local frequency = 3
local power = 20
-- Changed to 64 from 256 because my computer cannot handle so many parts
local resolution = 64
local Scale = Part.Size
-- Changed from "for x = 1, resolution" to "for x = -resolution / 2, resolution / 2" in order to make map centered.
for x = -resolution / 2, resolution / 2 do
-- Did the same here for z
for z = -resolution / 2, resolution / 2 do
local y1 = math.noise(
(x * frequency) / resolution,
(z * frequency) / resolution,
seed
)
local y2 = math.noise(
(x * frequency * .125) / resolution,
(z * frequency * .125) / resolution,
seed
)
local y3 = math.noise(
(x * frequency * 4) / resolution,
(z * frequency * 4) / resolution,
seed
)
local y = (y1 * y2 * power * power) + y3
local Part = Part:Clone()
Part.Parent = game.Workspace.Map
Part.CFrame = CFrame.new(x * Scale.X, y, z * Scale.Z)
local c = 0.4 -- c is some constant you use to customise how the noise feels
local threshold = 0.1 -- the TreeChance needs to be greater than this to spawn a tree
local TreeChance = math.noise(x * frequency * c / resolution, z * frequency * c / resolution, seed)
if TreeChance > threshold then
local Tree = game.Workspace.Tree:Clone()
Tree.Parent = workspace.Map
local TreeHeight = Tree.Size.Y
local PartHeight = Part.Size.Y
local TreeY = y + PartHeight / 2 + TreeHeight / 2
-- I changed it to Tree.Position instead of Tree.CFrame because the tree is a cylinder, so would spawn flat if I updated the CFrame instead of the position.
Tree.Position = Vector3.new(x * Scale.X, TreeY, z * Scale.Z)
end
end
end
btw there’s no need to do math.random(1, 10e6). Firstly, the lower limit for math.random() is 1 by default, so it’s fine if you just do math.random(10e6). Secondly, you don’t even need an upper limit if you want something completely random. Just doing math.random() and not passing any arguments will generate something random. After you’re done generating, though, you should do math.randomseed(tick() or math.randomseed(os.time()) to reset it.
If it looks a bit unnatural, you can always make it so that no trees can spawn below a certain level (using the y result from the original math.noise) and then set limits to a certain level using the new math.noise.
I found the problem. It was because of the water code. It works without the water code thank you. The water code and the tree code don’t work together.
I got trees to work on my generator but I created a probability function and slapped that onto the generator and added the y offset for the trees (so they would not be in the ground)