Recently i made this terrain generator that uses fractal noise to generate terrain with trees, hills, rocks and river. i was wondering how i can improve it by adding some area with less trees and some gigantic mountains, or anything you guys suggest.
here is what a gameplay looks like
here is the code:
WIDTH, DEPTH, HEIGHT = 159, 150, 30
local function Round(num, mult)
return math.floor(num / mult + 0.5) * mult
end
FractalNoise = require(script.FractalNoise)
PART_SCALE = 5
NOISE_SCALE = 250
HEIGHT_SCALE = 120
OCTAVES = 25
LACUNARITY = 3
PERSISTENCE = .1
SEED = math.random(1,999999)
FeatureSpawns = {}
function DeletePickedSpot(Position, Distance)
for i, v in ipairs(FeatureSpawns) do
if v then
if (v.Position - Position).Magnitude < Distance then
return true
end
end
end
return false
end
for x=0,WIDTH*PART_SCALE,PART_SCALE do
for z=0,DEPTH*PART_SCALE,PART_SCALE do
local TerrainNoise = FractalNoise["2D"](x, z,
OCTAVES,
LACUNARITY,
PERSISTENCE,
NOISE_SCALE,
SEED
) * HEIGHT_SCALE
TerrainNoise = Round(TerrainNoise, PART_SCALE)
TerrainNoise += (HEIGHT*PART_SCALE) - HEIGHT_SCALE
local SecondTerrainNoise = FractalNoise["2DModified"](x, z,
35,
3,
.2,
100,
SEED * 2
) * HEIGHT_SCALE
SecondTerrainNoise = Round(SecondTerrainNoise, PART_SCALE)
SecondTerrainNoise += (HEIGHT*PART_SCALE) - HEIGHT_SCALE
local VariationNoise = FractalNoise["2D"](x, z,
OCTAVES,
LACUNARITY,
PERSISTENCE,
NOISE_SCALE,
SEED / 2
) * HEIGHT_SCALE
VariationNoise = Round(VariationNoise, PART_SCALE)
VariationNoise += (HEIGHT*PART_SCALE) - HEIGHT_SCALE
local SecondVariationNoise = FractalNoise["2D"](x, z,
OCTAVES,
LACUNARITY,
PERSISTENCE,
190,
SEED / 3
) * HEIGHT_SCALE
SecondVariationNoise = Round(SecondVariationNoise, PART_SCALE)
SecondVariationNoise += (HEIGHT*PART_SCALE) - HEIGHT_SCALE
local MountainNoise = FractalNoise["2DModified"](x, z,
60,
3,
.8,
300,
SEED * 255
) * 400
MountainNoise = Round(MountainNoise, PART_SCALE)
MountainNoise += (HEIGHT*PART_SCALE) - HEIGHT_SCALE
for y=0,HEIGHT*PART_SCALE,PART_SCALE do
if y > TerrainNoise or y > SecondTerrainNoise and y * 2 > MountainNoise then continue end
local Material = Enum.Material.Grass
if y > VariationNoise and y < SecondVariationNoise then
Material = Enum.Material.Rock
elseif y > SecondVariationNoise then
Material = Enum.Material.Grass
elseif y < VariationNoise and y > SecondVariationNoise then
Material = Enum.Material.Rock
end
local RiverNoise = FractalNoise["2D"](x, z,
3,
2,
.35,
1000,
SEED
) * 50
RiverNoise = Round(RiverNoise, PART_SCALE)
RiverNoise += (HEIGHT*PART_SCALE) - HEIGHT_SCALE
if y <= 24 then
Material = Enum.Material.Ground
end
if y <= 30 and y >= 25 and RiverNoise <= 40 then
Material = Enum.Material.Water
end
workspace.Terrain:FillBall(Vector3.new(x,y,z), PART_SCALE, Material)
if Material == Enum.Material.Grass then
if y >= 30 and y <= 90 then
local FeatureNoise = math.noise(x / 25, y / 25, SEED) * 30
-- FeatureNoise >= -1 and FeatureNoise <= 3 and
if math.random(1,3) == 2 and VariationNoise == 35 then
if not DeletePickedSpot(Vector3.new(x + FeatureNoise / math.random(-2.00,2.00),y + 200, z + FeatureNoise / math.random(-2.00,2.00)), math.clamp(FeatureNoise * 2, 0, 1000)) then
if math.random(1,6) == 6 then
local RaycastPart = Instance.new("Part", workspace)
RaycastPart.Anchored = true
RaycastPart.Position = Vector3.new(x + FeatureNoise * 2,y + 200, z + FeatureNoise * 2)
RaycastPart.Size = Vector3.new(1,1,1)
RaycastPart.Rotation = Vector3.new(-90,0,0)
task.wait()
local RaycastResult = workspace:Raycast(RaycastPart.Position, RaycastPart.CFrame.LookVector * 1000)
if RaycastResult then
if RaycastResult.Material == Enum.Material.Grass then
local Tree = game.ServerStorage.Features.Trees:GetChildren()[math.random(1,#game.ServerStorage.Features.Trees:GetChildren())]:Clone()
Tree.Parent = workspace
Tree:PivotTo(CFrame.new(RaycastResult.Position.X,RaycastResult.Position.Y - 3,RaycastResult.Position.Z) * CFrame.Angles(0,math.rad(math.random(-180,180)),0))
RaycastPart:Destroy()
else
RaycastPart:Destroy()
end
else
RaycastPart:Destroy()
end
end
end
end
end
end
end
end
task.wait()
end
and the module code:
FractalNoise = {}
FractalNoise["2D"] = function(x, y, octaves, lacunarity, persistence, scale, seed)
local value = 0
local x1 = x
local y1 = y
local amplitude = 1
for i = 1, octaves, 1 do
value += math.abs(math.noise(x1 / scale, y1 / scale, seed)) * amplitude
y1 *= lacunarity
x1 *= lacunarity
amplitude *= persistence
end
value = value ^ 2
return math.clamp(value, -1, 1)
end
FractalNoise["2DModified"] = function(x, y, octaves, lacunarity, persistence, scale, seed)
local value = 0
local x1 = x
local y1 = y
local amplitude = 1
for i = 1, octaves, 1 do
value += math.abs(math.noise(x1 / scale, y1 / scale, seed)) * amplitude
y1 *= lacunarity
x1 *= lacunarity
amplitude *= persistence
end
return math.clamp(value, -1, 1)
end
FractalNoise["3D"] = function(x, y, z, octaves, lacunarity, persistence, scale, seed)
local value = 0
local x1 = x
local y1 = y
local z1 = z
local amplitude = 1
for i = 1, octaves, 1 do
value += math.noise(x1 / scale, y1 / scale, z1 / scale, seed) * amplitude
y1 *= lacunarity
x1 *= lacunarity
z1 *= lacunarity
amplitude *= persistence
end
return math.clamp(value, -1, 1)
end
return FractalNoise