Hello there im trying to make a terrain generator with biomes but its not working properly. The generation is very wonky(image below). How can i fix this?
The diffrent types of biomes i have are as listed :
- Mountain : snow and rock very hilly
- Desert : small hills and sand
- Grassland : small hills and grass
- Ice : medium hills and snow
I also want the biomes to be decent sized too.
the script i have is
local X, Z = 20,20
BiomeScaleA = 40*4*3/2/8/8
BiomeScaleB = 30*4*3/2/8/8
BiomeScaleC = 30*4*2/2/8/8
BiomeScaleD = 20*4*1/2/8/8
BiomeScaleE = 20*4/2/8/8
BiomeStrengthA = 1 * 1.5
BiomeStrengthB = .5 * 1.5
BiomeStrengthC = -0.5 * 1.5
BiomeStrengthD = .5 * 1.5
BiomeStrengthE = -0.5 * 1.5
BiomeZoneMin = -200000
BiomeZoneMax = 200000
Rvar = math.random(BiomeZoneMin,BiomeZoneMax)
Gvar = math.random(BiomeZoneMin,BiomeZoneMax)
Bvar = math.random(BiomeZoneMin,BiomeZoneMax)
Svar = math.random(BiomeZoneMin,BiomeZoneMax)
TempGrid = {}
WetGrid = {}
Final = {}
local Budget = 1/60 -- seconds
local expireTime = 0
-- Call at start of process.
function ResetTimer()
expireTime = tick() + Budget
end
-- Call where appropriate, such as at the top of loops.
function MaybeYield()
if tick() >= expireTime then
game:GetService("RunService").Heartbeat:Wait() -- insert preferred yielding method
ResetTimer()
end
end
function sig(x, k)
return (x-k*x)/(k-2*k*math.abs(x) + 1)
end
ResetTimer()
for x = -X, X do
MaybeYield()
TempGrid[x] = {}
for z = -Z, Z do
local y = (math.noise(x/30,0,z/30)) * 0.5 + (math.noise(x/40,0,z/40)) * 0.3 + (math.noise(x/7,0,z/7)) * 0.2
local r = (math.noise(x/BiomeScaleA + Rvar, 0, z/BiomeScaleA + Rvar)) * BiomeStrengthA + (math.noise(x/BiomeScaleB + Rvar, 0, z/BiomeScaleB + Rvar)) * BiomeStrengthB + (math.noise(x/BiomeScaleC + Rvar, 0, z/BiomeScaleC + Rvar)) * BiomeStrengthC + (math.noise(x/BiomeScaleD + Rvar, 0, z/BiomeScaleD + Rvar)) * BiomeStrengthD + (math.noise(x/BiomeScaleE + Rvar, 0, z/BiomeScaleE + Rvar)) * BiomeStrengthE
local g = (math.noise(x/BiomeScaleA + Gvar, 0, z/BiomeScaleA + Gvar)) * BiomeStrengthA + (math.noise(x/BiomeScaleB + Gvar, 0, z/BiomeScaleB + Gvar)) * BiomeStrengthB + (math.noise(x/BiomeScaleC + Gvar, 0, z/BiomeScaleC + Gvar)) * BiomeStrengthC + (math.noise(x/BiomeScaleD + Gvar, 0, z/BiomeScaleD + Gvar)) * BiomeStrengthD + (math.noise(x/BiomeScaleE + Gvar, 0, z/BiomeScaleE + Gvar)) * BiomeStrengthE
local b = (math.noise(x/BiomeScaleA + Bvar, 0, z/BiomeScaleA + Bvar)) * BiomeStrengthA + (math.noise(x/BiomeScaleB + Bvar, 0, z/BiomeScaleB + Bvar)) * BiomeStrengthB + (math.noise(x/BiomeScaleC + Bvar, 0, z/BiomeScaleC + Bvar)) * BiomeStrengthC + (math.noise(x/BiomeScaleD + Bvar, 0, z/BiomeScaleD + Bvar)) * BiomeStrengthD + (math.noise(x/BiomeScaleE + Bvar, 0, z/BiomeScaleE + Bvar)) * BiomeStrengthE
local s = (math.noise(x/BiomeScaleA*3 + Svar, 0, z/BiomeScaleA*3 + Svar)) * BiomeStrengthA + (math.noise(x/BiomeScaleB*3 + Svar, 0, z/BiomeScaleB*3 + Svar)) * BiomeStrengthB + (math.noise(x/BiomeScaleC*3 + Svar, 0, z/BiomeScaleC*3 + Svar)) * BiomeStrengthC + (math.noise(x/BiomeScaleD*3 + Svar, 0, z/BiomeScaleD*3 + Svar)) * BiomeStrengthD + (math.noise(x/BiomeScaleE*3 + Svar, 0, z/BiomeScaleE*3 + Svar)) * BiomeStrengthE
local yVar = (1 + math.noise(x/200 + 999,0,z/200 + 999))*5
y = (y*yVar*(r*4+g*7-b*6)+sig(s*3,-0.4)*16*r * g * 2)
local val = ""
if y < 0 then
val = "High"
elseif y > 0 then
val = "Low"
end
TempGrid[x][z] = val
end
end
ResetTimer()
Rvar = math.random(BiomeZoneMin,BiomeZoneMax)
Gvar = math.random(BiomeZoneMin,BiomeZoneMax)
Bvar = math.random(BiomeZoneMin,BiomeZoneMax)
Svar = math.random(BiomeZoneMin,BiomeZoneMax)
for x = -X, X do
MaybeYield()
WetGrid[x] = {}
for z = -Z, Z do
local y = (math.noise(x/30,0,z/30)) * 0.5 + (math.noise(x/40,0,z/40)) * 0.3 + (math.noise(x/7,0,z/7)) * 0.2
local r = (math.noise(x/BiomeScaleA + Rvar, 0, z/BiomeScaleA + Rvar)) * BiomeStrengthA + (math.noise(x/BiomeScaleB + Rvar, 0, z/BiomeScaleB + Rvar)) * BiomeStrengthB + (math.noise(x/BiomeScaleC + Rvar, 0, z/BiomeScaleC + Rvar)) * BiomeStrengthC + (math.noise(x/BiomeScaleD + Rvar, 0, z/BiomeScaleD + Rvar)) * BiomeStrengthD + (math.noise(x/BiomeScaleE + Rvar, 0, z/BiomeScaleE + Rvar)) * BiomeStrengthE
local g = (math.noise(x/BiomeScaleA + Gvar, 0, z/BiomeScaleA + Gvar)) * BiomeStrengthA + (math.noise(x/BiomeScaleB + Gvar, 0, z/BiomeScaleB + Gvar)) * BiomeStrengthB + (math.noise(x/BiomeScaleC + Gvar, 0, z/BiomeScaleC + Gvar)) * BiomeStrengthC + (math.noise(x/BiomeScaleD + Gvar, 0, z/BiomeScaleD + Gvar)) * BiomeStrengthD + (math.noise(x/BiomeScaleE + Gvar, 0, z/BiomeScaleE + Gvar)) * BiomeStrengthE
local b = (math.noise(x/BiomeScaleA + Bvar, 0, z/BiomeScaleA + Bvar)) * BiomeStrengthA + (math.noise(x/BiomeScaleB + Bvar, 0, z/BiomeScaleB + Bvar)) * BiomeStrengthB + (math.noise(x/BiomeScaleC + Bvar, 0, z/BiomeScaleC + Bvar)) * BiomeStrengthC + (math.noise(x/BiomeScaleD + Bvar, 0, z/BiomeScaleD + Bvar)) * BiomeStrengthD + (math.noise(x/BiomeScaleE + Bvar, 0, z/BiomeScaleE + Bvar)) * BiomeStrengthE
local s = (math.noise(x/BiomeScaleA*3 + Svar, 0, z/BiomeScaleA*3 + Svar)) * BiomeStrengthA + (math.noise(x/BiomeScaleB*3 + Svar, 0, z/BiomeScaleB*3 + Svar)) * BiomeStrengthB + (math.noise(x/BiomeScaleC*3 + Svar, 0, z/BiomeScaleC*3 + Svar)) * BiomeStrengthC + (math.noise(x/BiomeScaleD*3 + Svar, 0, z/BiomeScaleD*3 + Svar)) * BiomeStrengthD + (math.noise(x/BiomeScaleE*3 + Svar, 0, z/BiomeScaleE*3 + Svar)) * BiomeStrengthE
local yVar = (1 + math.noise(x/200 + 999,0,z/200 + 999))*5
y = (y*yVar*(r*4+g*7-b*6)+sig(s*3,-0.4)*16*r * g * 2)
local val = ""
if y < 0 then
val = "High"
elseif y > 0 then
val = "Low"
end
WetGrid[x][z] = val
end
end
ResetTimer()
for x = -X, X do
MaybeYield()
Final[x] = {}
for z = -Z, Z do
local val = ""
local firstvalue = TempGrid[x][z]
local secondvalue = WetGrid[x][z]
if firstvalue == "High" and secondvalue == "Low" then
val = "Desert"
elseif firstvalue == "Low" and secondvalue == "Low" then
val = "Mountains"
elseif firstvalue == "High" and secondvalue == "High" then
val = "Grass"
elseif firstvalue == "Low" and secondvalue == "High" then
val = "Ice"
end
Final[x][z] = val
end
end
local wedge = Instance.new("WedgePart");
wedge.Anchored = true;
wedge.TopSurface = Enum.SurfaceType.Smooth;
wedge.BottomSurface = Enum.SurfaceType.Smooth;
local function draw3dTriangle(a, b, c, part)
local ab, ac, bc = b - a, c - a, c - b;
local abd, acd, bcd = ab:Dot(ab), ac:Dot(ac), bc:Dot(bc);
if (abd > acd and abd > bcd) then
c, a = a, c;
elseif (acd > bcd and acd > abd) then
a, b = b, a;
end
ab, ac, bc = b - a, c - a, c - b;
local right = ac:Cross(ab).unit;
local up = bc:Cross(right).unit;
local back = bc.unit;
local height = math.abs(ab:Dot(up));
local w1 = wedge:Clone();
w1.Size = Vector3.new(2, height, math.abs(ab:Dot(back)));
w1.CFrame = CFrame.fromMatrix((a + b)/2, right, up, back);
w1.Parent = workspace.BlockTerrain;
local w2 = wedge:Clone();
w2.Size = Vector3.new(2, height, math.abs(ac:Dot(back)));
w2.CFrame = CFrame.fromMatrix((a + c)/2, -right, up, -back);
w2.Parent = workspace.BlockTerrain;
local s= w1.Size+Vector3.new(20,0,0)
local v = w2
if part == "Desert" then
workspace.Terrain:FillBlock(w1.CFrame,s,Enum.Material.Sand)
w1:Destroy()
workspace.Terrain:FillBlock(v.CFrame,s,Enum.Material.Sand)
v:Destroy()
else
if w1.Position.Y < -3 then
workspace.Terrain:FillBlock(w1.CFrame,s,Enum.Material.Sand)
w1:Destroy()
elseif w1.Position.Y > -5 and w1.Position.Y < 100 then
local terraintype = math.random(1,10)
if terraintype == 1 then
workspace.Terrain:FillBlock(w1.CFrame,s,Enum.Material.Ground)
w1:Destroy()
elseif terraintype == 2 then
workspace.Terrain:FillBlock(w1.CFrame,s,Enum.Material.LeafyGrass)
w1:Destroy()
else
workspace.Terrain:FillBlock(w1.CFrame,s,Enum.Material.Grass)
w1:Destroy()
end
else
local terraintype = math.random(1,10)
if terraintype == 1 then
workspace.Terrain:FillBlock(w1.CFrame,s,Enum.Material.Rock)
w1:Destroy()
else
workspace.Terrain:FillBlock(w1.CFrame,s,Enum.Material.Snow)
w1:Destroy()
end
end
local s= v.Size+Vector3.new(20,0,0)
if v.Position.Y < -3 then
workspace.Terrain:FillBlock(v.CFrame,s,Enum.Material.Sand)
v:Destroy()
elseif v.Position.Y > -5 and v.Position.Y < 100 then
local terraintype = math.random(1,10)
if terraintype == 1 then
workspace.Terrain:FillBlock(v.CFrame,s,Enum.Material.Ground)
v:Destroy()
elseif terraintype == 2 then
workspace.Terrain:FillBlock(v.CFrame,s,Enum.Material.LeafyGrass)
v:Destroy()
else
workspace.Terrain:FillBlock(v.CFrame,s,Enum.Material.Grass)
v:Destroy()
end
else
local terraintype = math.random(1,10)
if terraintype == 1 then
workspace.Terrain:FillBlock(v.CFrame,s,Enum.Material.Rock)
v:Destroy()
else
workspace.Terrain:FillBlock(v.CFrame,s,Enum.Material.Snow)
v:Destroy()
end
end
end
return w1, w2;
end
local positionGrid = {}
local count = 0
ResetTimer()
Rvar = math.random(BiomeZoneMin,BiomeZoneMax)
Gvar = math.random(BiomeZoneMin,BiomeZoneMax)
Bvar = math.random(BiomeZoneMin,BiomeZoneMax)
Svar = math.random(BiomeZoneMin,BiomeZoneMax)
for x = -X, X do
MaybeYield()
positionGrid[x] = {}
for z = -Z, Z do
local biome = Final[x][z]
if biome == "Mountains" then
BiomeScaleA = 40*4*3/2/5
BiomeScaleB = 30*4*3/2/5
BiomeScaleC = 30*4*2/2/5
BiomeScaleD = 20*4*1/2/5
BiomeScaleE = 20*4/2/5
elseif biome == "Grass" then
BiomeScaleA = 40*4*3/2
BiomeScaleB = 30*4*3/2
BiomeScaleC = 30*4*2/2
BiomeScaleD = 20*4*1/2
BiomeScaleE = 20*4/2
elseif biome == "Desert" then
BiomeScaleA = 40*4*3/2
BiomeScaleB = 30*4*3/2
BiomeScaleC = 30*4*2/2
BiomeScaleD = 20*4*1/2
BiomeScaleE = 20*4/2
elseif biome == "Ice" then
BiomeScaleA = 40*4*3/2
BiomeScaleB = 30*4*3/2
BiomeScaleC = 30*4*2/2
BiomeScaleD = 20*4*1/2
BiomeScaleE = 20*4/2
end
local y = (math.noise(x/30,0,z/30)) * 0.5 + (math.noise(x/40,0,z/40)) * 0.3 + (math.noise(x/7,0,z/7)) * 0.2
local r = (math.noise(x/BiomeScaleA + Rvar, 0, z/BiomeScaleA + Rvar)) * BiomeStrengthA + (math.noise(x/BiomeScaleB + Rvar, 0, z/BiomeScaleB + Rvar)) * BiomeStrengthB + (math.noise(x/BiomeScaleC + Rvar, 0, z/BiomeScaleC + Rvar)) * BiomeStrengthC + (math.noise(x/BiomeScaleD + Rvar, 0, z/BiomeScaleD + Rvar)) * BiomeStrengthD + (math.noise(x/BiomeScaleE + Rvar, 0, z/BiomeScaleE + Rvar)) * BiomeStrengthE
local g = (math.noise(x/BiomeScaleA + Gvar, 0, z/BiomeScaleA + Gvar)) * BiomeStrengthA + (math.noise(x/BiomeScaleB + Gvar, 0, z/BiomeScaleB + Gvar)) * BiomeStrengthB + (math.noise(x/BiomeScaleC + Gvar, 0, z/BiomeScaleC + Gvar)) * BiomeStrengthC + (math.noise(x/BiomeScaleD + Gvar, 0, z/BiomeScaleD + Gvar)) * BiomeStrengthD + (math.noise(x/BiomeScaleE + Gvar, 0, z/BiomeScaleE + Gvar)) * BiomeStrengthE
local b = (math.noise(x/BiomeScaleA + Bvar, 0, z/BiomeScaleA + Bvar)) * BiomeStrengthA + (math.noise(x/BiomeScaleB + Bvar, 0, z/BiomeScaleB + Bvar)) * BiomeStrengthB + (math.noise(x/BiomeScaleC + Bvar, 0, z/BiomeScaleC + Bvar)) * BiomeStrengthC + (math.noise(x/BiomeScaleD + Bvar, 0, z/BiomeScaleD + Bvar)) * BiomeStrengthD + (math.noise(x/BiomeScaleE + Bvar, 0, z/BiomeScaleE + Bvar)) * BiomeStrengthE
local s = (math.noise(x/BiomeScaleA*3 + Svar, 0, z/BiomeScaleA*3 + Svar)) * BiomeStrengthA + (math.noise(x/BiomeScaleB*3 + Svar, 0, z/BiomeScaleB*3 + Svar)) * BiomeStrengthB + (math.noise(x/BiomeScaleC*3 + Svar, 0, z/BiomeScaleC*3 + Svar)) * BiomeStrengthC + (math.noise(x/BiomeScaleD*3 + Svar, 0, z/BiomeScaleD*3 + Svar)) * BiomeStrengthD + (math.noise(x/BiomeScaleE*3 + Svar, 0, z/BiomeScaleE*3 + Svar)) * BiomeStrengthE
local yVar = (1 + math.noise(x/200 + 999,0,z/200 + 999))*5
y = (y*yVar*(r*4+g*7-b*6)+sig(s*3,-0.4)*16*r * g * 2) + 3
if y < -1 then
y = sig(y, -0.02)
end
positionGrid[x][z] = x*15 .. ":" .. y * 10 .. ":" .. z*15 .. ":".. biome
end
end
ResetTimer()
for x = -X, X-1 do
MaybeYield()
for z = -Z, Z-1 do
local a = positionGrid[x][z]
local info = string.split(a, ":")
local one = info[1]
local two = info[2]
local three = info[3]
local part = info[4]
a = Vector3.new(one, two, three)
local b = positionGrid[x+1][z]
local info = string.split(b, ":")
local one = info[1]
local two = info[2]
local three = info[3]
b = Vector3.new(one, two, three)
local c = positionGrid[x][z+1]
local info = string.split(c, ":")
local one = info[1]
local two = info[2]
local three = info[3]
c = Vector3.new(one, two, three)
local d = positionGrid[x+1][z+1]
local info = string.split(d, ":")
local one = info[1]
local two = info[2]
local three = info[3]
d = Vector3.new(one, two, three)
draw3dTriangle(a, b, c, part)
draw3dTriangle(b, c, d, part)
end
end
print(Final)