Here lies my good perlin noise generator:
You see, Im trying to upscale my previous script that worked REALLY well!
However, I wanted to upscale it because the way it’s set up, it can only generate one “packet.”
My new script’s goal is to have it generate more packets and potentially with it some islands.
Old Script
--scripted by GreekForge
local pCont = workspace.PerlinContainer
local coms = game.ReplicatedStorage.RemoteEvent
local deb = true
local gridPart = Instance.new("Part")
gridPart.TopSurface = Enum.SurfaceType.Smooth
gridPart.Name = "GridPart"
gridPart.Anchored = true
gridPart.CanCollide = false
gridPart.Size = Vector3.new(5, 5, 5)
local function generateGrid(gridSize) --generates the grid :T
--clean up section
for _, p in pairs(pCont:GetChildren()) do
p:Destroy()
end
wait()
gridSize = math.clamp(gridSize, 5, 99) or 5
gridSize = gridSize - 1
for x=0, gridSize do
wait()
coroutine.wrap(function()
local tX = x
for y=0, gridSize do
local nPar = gridPart:Clone()
nPar.Position = Vector3.new(tX * gridPart.Size.X + gridPart.Size.X, 0, y * gridPart.Size.Z + gridPart.Size.Z)
nPar.Parent = pCont
end
end)()
end
end
local function perl(gridSize)
deb = true
generateGrid(gridSize)
wait(0.5)
local function rand(n)
return math.random(-n, n)
end
local GradVects = { --yup, its a doozy
Vector2.new(rand(500)/500, rand(500)/500).Unit,
Vector2.new(rand(500)/500, rand(500)/500).Unit,
Vector2.new(rand(500)/500, rand(500)/500).Unit,
Vector2.new(rand(500)/500, rand(500)/500).Unit,
}
local cStones = { --corner stones or points...
Vector2.new(0,0),
Vector2.new(gridSize*gridPart.Size.X + gridPart.Size.X, 0),
Vector2.new(0, gridSize*gridPart.Size.Z + gridPart.Size.Z),
Vector2.new(gridSize*gridPart.Size.X + gridPart.Size.X, gridSize*gridPart.Size.Z + gridPart.Size.Z)
}
for _, p in pairs(pCont:GetChildren()) do
wait()
if p:IsA("Part") then
local v2Pos = Vector2.new(p.Position.X, p.Position.Z)
local dVectors = {
(v2Pos - cStones[1]).Unit,
(v2Pos - cStones[2]).Unit,
(v2Pos - cStones[3]).Unit,
(v2Pos - cStones[4]).Unit,
}
local dots = {
dVectors[1]:Dot(GradVects[1]),
dVectors[2]:Dot(GradVects[2]),
dVectors[3]:Dot(GradVects[3]),
dVectors[4]:Dot(GradVects[4]),
}
local ab = dots[1] + (v2Pos.X/(cStones[1] - cStones[2]).Magnitude)*(dots[2] - dots[1])
local cd = dots[3] + (v2Pos.X/(cStones[3] - cStones[4]).Magnitude)*(dots[4] - dots[3])
local finVal = ab + (v2Pos.Y/(cStones[1] - cStones[3]).Magnitude)*(cd - ab)
p.Position = Vector3.new(v2Pos.X, finVal * gridPart.Size.Y * 1.75, v2Pos.Y)
p.Color = Color3.new((finVal+1)/2, -((finVal+1)/2)*(((finVal+1)/2)+1), 1-((finVal+1)/2))
--print(finVal)
end
end
deb = false
end
math.randomseed(tick() + time()) --second step
wait(3)
perl(9)
coms.OnServerEvent:Connect(function(plr, mess)
math.randomseed(tick() + time()) --second step
if mess == "MakeNew" and not deb then
perl(9)
end
end)
New Script
--scripted by GreekForge
local pCont = workspace.PerlinContainer
local coms = game.ReplicatedStorage.RemoteEvent
local deb = true
local gridPart = Instance.new("Part")
gridPart.TopSurface = Enum.SurfaceType.Smooth
gridPart.Name = "GridPart"
gridPart.Anchored = true
gridPart.CanCollide = false
gridPart.Size = Vector3.new(5, 5, 5)
local function rand(n)
return math.random(-n, n)
end
local function generate(pSize, gSize)
deb = true
--clean up section
for _, p in pairs(pCont:GetChildren()) do
p:Destroy()
end
--grid section
gSize = math.clamp(gSize, pSize, pSize*100) or pSize
if gSize % pSize ~= 0 then
gSize = gSize + (gSize%pSize)
end
--packet and gridpart generation
for i=1, gSize, pSize do
wait()
for j=1, gSize, pSize do
wait()
coroutine.wrap(function()
local f = Instance.new("Folder")
f.Name = "Packet"..(((i-1)/pSize)+1)..(((j-1)/pSize)+1)
f.Parent = pCont
local index1 = i
local index2 = j
for x=1, pSize do
wait()
coroutine.wrap(function()
for z=1, pSize do
wait()
local c = gridPart:Clone()
c.Position = Vector3.new((index1 * gridPart.Size.X ) + x * gridPart.Size.X, 0, (index2 * gridPart.Size.Z ) + z * gridPart.Size.Z)
c.Parent = f
end
end)()
end
end)()
end
end
local vectCont = Instance.new("Folder")
vectCont.Name = "VectorContainer"
vectCont.Parent = pCont
local vectNum = math.sqrt(#pCont:GetChildren())
for x=0, vectNum do
coroutine.wrap(function()
for z=0, vectNum do
local Vect = Instance.new("Folder") --the Vector "object"
Vect.Name = "Vector"..(x+1)..(z+1)
Vect.Parent = vectCont
local vVectX = Instance.new("NumberValue") --the vector x
vVectX.Name = "VecX"
vVectX.Value = math.clamp(rand(500)/500, -1, 1)
vVectX.Parent = Vect
local vVectZ = Instance.new("NumberValue") --the vector Z
vVectZ.Name = "VecZ"
vVectZ.Value = math.clamp(rand(500)/500, -1, 1)
vVectZ.Parent = Vect
local PosInfo = Instance.new("Vector3Value") --the positional vector
PosInfo.Name = "Position"
PosInfo.Value = Vector3.new(x*gridPart.Size.X*pSize, 0, z*gridPart.Size.Z*pSize)
PosInfo.Parent = Vect
end
end)()
end
end
local function perl()
local partContainers = {}
for _, fold in pairs(pCont:GetChildren()) do --basically got to remove vector container (Damn thats annoying)
if fold.Name ~= "VectorContainer" then
table.insert(partContainers, fold)
end
end
for _, partFolder in pairs(partContainers) do --for every part folder in the container
local CenterX = string.sub(partFolder.Name, #partFolder.Name-1, #partFolder.Name-1)
local CenterZ = string.sub(partFolder.Name, #partFolder.Name, #partFolder.Name)
local vecTable = {
pCont.VectorContainer["Vector"..CenterX..CenterZ],
pCont.VectorContainer["Vector"..(CenterX+1)..CenterZ],
pCont.VectorContainer["Vector"..CenterX..(CenterZ+1)],
pCont.VectorContainer["Vector"..(CenterX+1)..(CenterZ+1)],
}
for _, part in pairs(partFolder:GetChildren()) do --for every part in the part folder
wait()
local v2Pos = Vector2.new(part.Position.X, part.Position.Z) --why do i translate every thing to 2 dimension? idk
local GradVects = { --god this is a lot
Vector2.new(vecTable[1].VecX.Value, vecTable[1].VecZ.Value).Unit,
Vector2.new(vecTable[2].VecX.Value, vecTable[2].VecZ.Value).Unit,
Vector2.new(vecTable[3].VecX.Value, vecTable[3].VecZ.Value).Unit,
Vector2.new(vecTable[4].VecX.Value, vecTable[4].VecZ.Value).Unit,
}
local cStones = { --corner stones or points...
Vector2.new(vecTable[1].Position.Value.X, vecTable[1].Position.Value.Z),
Vector2.new(vecTable[2].Position.Value.X, vecTable[2].Position.Value.Z),
Vector2.new(vecTable[3].Position.Value.X, vecTable[3].Position.Value.Z),
Vector2.new(vecTable[4].Position.Value.X, vecTable[4].Position.Value.Z),
}
local dVectors = {
(v2Pos - cStones[1]).Unit,
(v2Pos - cStones[2]).Unit,
(v2Pos - cStones[3]).Unit,
(v2Pos - cStones[4]).Unit,
}
local dots = {
dVectors[1]:Dot(GradVects[1]),
dVectors[2]:Dot(GradVects[2]),
dVectors[3]:Dot(GradVects[3]),
dVectors[4]:Dot(GradVects[4]),
}
local ab = dots[1] + (v2Pos.X/(cStones[1] - cStones[2]).Magnitude)*(dots[2] - dots[1])
local cd = dots[3] + (v2Pos.X/(cStones[3] - cStones[4]).Magnitude)*(dots[4] - dots[3])
local finVal = ab + (v2Pos.Y/(cStones[1] - cStones[3]).Magnitude)*(cd - ab)
part.Position = Vector3.new(v2Pos.X, finVal * gridPart.Size.Y, v2Pos.Y)
part.Color = Color3.new((finVal+1)/2, -((finVal+1)/2)*(((finVal+1)/2)+1), 1-((finVal+1)/2))
print(finVal)
end
end
deb = false
end
math.randomseed(tick() + time()) --second step
wait(1.5)
generate(3, 9)
wait(1.5)
perl()
deb = false
coms.OnServerEvent:Connect(function(plr, mess)
math.randomseed(tick() + time()) --second step
if mess == "MakeNew" and not deb then
generate(3, 9)
wait(1.5)
perl()
end
end)
As you can see, the only changes between them is the amount of packets, and therefore gradient vectors. Now I’m unsure if I’m correctly generating them, but my main issue seems to be from the interpolation step of the algorithm.
Snippet (cStones being the position of the gradient vector):
local ab = dots[1] + (v2Pos.X/(cStones[1] - cStones[2]).Magnitude)*(dots[2] - dots[1])
local cd = dots[3] + (v2Pos.X/(cStones[3] - cStones[4]).Magnitude)*(dots[4] - dots[3])
local finVal = ab + (v2Pos.Y/(cStones[1] - cStones[3]).Magnitude)*(cd - ab)
I think the Fractions I’m getting are incorrect, however I am unsure of what is really my issue.
I’ve basically copied the code exactly from the old script, so It might not even be my issue…
So I’ve tried to rewrite the code (which I got from this video) to this:
local abSlope = (dots[2] - dots[1])/(cStones[2].X - cStones[1].X)
local ab = abSlope * (v2Pos.X - cStones[1].X) + dots[1]
local cdSlope = (dots[4] - dots[3])/(cStones[4].X - cStones[3].X)
local cd = cdSlope * (v2Pos.X - cStones[3].X) + dots[3]
local finValSlope = (cd - ab)/(cStones[3].Y - cStones[1].Y)
local finVal = finValSlope * (cd - ab) + ab
But it didn’t really help :T
I’ve also noticed that moving the packet size to a larger number as well as grid size makes the generation a little better…
If anyone has any experience with this, or sees something glaring in my code, please give me some advice.
If you dont get my new system, just ask and I’ll explain it to you.
I’m gonna sleep now, its 1:07 AM here…