From c04b9d457484975e8ea2f58575fe2ed6073481a9 Mon Sep 17 00:00:00 2001 From: Rose Liverman Date: Wed, 19 Aug 2026 00:20:16 -0600 Subject: [PATCH] better sizing of current status --- src/lib/simplex.lua | 159 ++++++++++++++++++++++++-------------------- src/main.lua | 6 ++ src/map_nextgen.lua | 4 +- 3 files changed, 96 insertions(+), 73 deletions(-) diff --git a/src/lib/simplex.lua b/src/lib/simplex.lua index e10e60a..6513774 100644 --- a/src/lib/simplex.lua +++ b/src/lib/simplex.lua @@ -82,14 +82,14 @@ local sim = { {2,1,0,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,1,0,2},{0,0,0,0},{3,2,0,1},{3,2,1,0}}; local function Dot2D(tbl, x, y) - return tbl[1]*x + tbl[2]*y; + return tbl[1]*x + tbl[2]*y; end local function Dot3D(tbl, x, y, z) return tbl[1]*x + tbl[2]*y + tbl[3]*z end -local function Dot4D( tbl, x,y,z,w) +local function Dot4D( tbl, x,y,z,w) return tbl[1]*x + tbl[2]*y + tbl[3]*z + tbl[3]*w; end @@ -99,7 +99,7 @@ local Prev2D = {} -- 2D simplex noise function simplex.Noise2D(xin, yin) - if simplex.internalCache and Prev2D[xin] and Prev2D[xin][yin] then return Prev2D[xin][yin] end + if simplex.internalCache and Prev2D[xin] and Prev2D[xin][yin] then return Prev2D[xin][yin] end local n0, n1, n2; -- Noise contributions from the three corners -- Skew the input space to determine which simplex cell we're in @@ -108,24 +108,24 @@ function simplex.Noise2D(xin, yin) local i = math.floor(xin+s); local j = math.floor(yin+s); local G2 = (3.0-math.sqrt(3.0))/6.0; - + local t = (i+j)*G2; local X0 = i-t; -- Unskew the cell origin back to (x,y) space local Y0 = j-t; local x0 = xin-X0; -- The x,y distances from the cell origin local y0 = yin-Y0; - + -- For the 2D case, the simplex shape is an equilateral triangle. -- Determine which simplex we are in. local i1, j1; -- Offsets for second (middle) corner of simplex in (i,j) coords - if(x0>y0) then - i1=1 + if(x0>y0) then + i1=1 j1=0 -- lower triangle, XY order: (0,0)->(1,0)->(1,1) else i1=0 j1=1 -- upper triangle, YX order: (0,0)->(0,1)->(1,1) end - + -- A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and -- a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where -- c = (3-sqrt(3))/6 @@ -144,13 +144,13 @@ function simplex.Noise2D(xin, yin) -- Calculate the contribution from the three corners local t0 = 0.5 - x0*x0-y0*y0; - if t0<0 then + if t0<0 then n0 = 0.0; else t0 = t0 * t0 n0 = t0 * t0 * Dot2D(Gradients3D[gi0], x0, y0); -- (x,y) of Gradients3D used for 2D gradient end - + local t1 = 0.5 - x1*x1-y1*y1; if (t1<0) then n1 = 0.0; @@ -158,7 +158,7 @@ function simplex.Noise2D(xin, yin) t1 = t1*t1 n1 = t1 * t1 * Dot2D(Gradients3D[gi1], x1, y1); end - + local t2 = 0.5 - x2*x2-y2*y2; if (t2<0) then n2 = 0.0; @@ -167,17 +167,17 @@ function simplex.Noise2D(xin, yin) n2 = t2 * t2 * Dot2D(Gradients3D[gi2], x2, y2); end - + -- Add contributions from each corner to get the final noise value. -- The result is scaled to return values in the localerval [-1,1]. - + local retval = 70.0 * (n0 + n1 + n2) - + if simplex.internalCache then if not Prev2D[xin] then Prev2D[xin] = {} end Prev2D[xin][yin] = retval end - + return retval; end @@ -185,127 +185,127 @@ local Prev3D = {} -- 3D simplex noise function simplex.Noise3D(xin, yin, zin) - + if simplex.internalCache and Prev3D[xin] and Prev3D[xin][yin] and Prev3D[xin][yin][zin] then return Prev3D[xin][yin][zin] end - + local n0, n1, n2, n3; -- Noise contributions from the four corners - + -- Skew the input space to determine which simplex cell we're in local F3 = 1.0/3.0; local s = (xin+yin+zin)*F3; -- Very nice and simple skew factor for 3D local i = math.floor(xin+s); local j = math.floor(yin+s); local k = math.floor(zin+s); - + local G3 = 1.0/6.0; -- Very nice and simple unskew factor, too local t = (i+j+k)*G3; - + local X0 = i-t; -- Unskew the cell origin back to (x,y,z) space local Y0 = j-t; local Z0 = k-t; - + local x0 = xin-X0; -- The x,y,z distances from the cell origin local y0 = yin-Y0; local z0 = zin-Z0; - + -- For the 3D case, the simplex shape is a slightly irregular tetrahedron. -- Determine which simplex we are in. local i1, j1, k1; -- Offsets for second corner of simplex in (i,j,k) coords local i2, j2, k2; -- Offsets for third corner of simplex in (i,j,k) coords - + if (x0>=y0) then if (y0>=z0) then i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; -- X Y Z order elseif (x0>=z0) then i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; -- X Z Y order - else + else i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; -- Z X Y order end else -- x0y>z>w makes x=3 and 1 or 0; j1 = sim[c][2]>=3 and 1 or 0; k1 = sim[c][3]>=3 and 1 or 0; @@ -391,7 +391,7 @@ function simplex.Noise4D(x,y,z,w) local y4 = y0 - 1.0 + 4.0*G4; local z4 = z0 - 1.0 + 4.0*G4; local w4 = w0 - 1.0 + 4.0*G4; - + -- Work out the hashed gradient indices of the five simplex corners local ii = math.floor(i % 255) local jj = math.floor(j % 255) @@ -402,8 +402,8 @@ function simplex.Noise4D(x,y,z,w) local gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]] % 32; local gi3 = perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]] % 32; local gi4 = perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]] % 32; - - + + -- Calculate the contribution from the five corners local t0 = 0.5 - x0*x0 - y0*y0 - z0*z0 - w0*w0; if (t0<0) then @@ -412,15 +412,15 @@ function simplex.Noise4D(x,y,z,w) t0 = t0*t0; n0 = t0 * t0 * Dot4D(Gradients4D[gi0], x0, y0, z0, w0); end - + local t1 = 0.5 - x1*x1 - y1*y1 - z1*z1 - w1*w1; if (t1<0) then n1 = 0.0; - else + else t1 = t1*t1; n1 = t1 * t1 * Dot4D(Gradients4D[gi1], x1, y1, z1, w1); end - + local t2 = 0.5 - x2*x2 - y2*y2 - z2*z2 - w2*w2; if (t2<0) then n2 = 0.0; @@ -428,15 +428,15 @@ function simplex.Noise4D(x,y,z,w) t2 = t2*t2; n2 = t2 * t2 * Dot4D(Gradients4D[gi2], x2, y2, z2, w2); end - + local t3 = 0.5 - x3*x3 - y3*y3 - z3*z3 - w3*w3; if (t3<0) then n3 = 0.0; - else + else t3 = t3*t3; n3 = t3 * t3 * Dot4D(Gradients4D[gi3], x3, y3, z3, w3); end - + local t4 = 0.5 - x4*x4 - y4*y4 - z4*z4 - w4*w4; if (t4<0) then n4 = 0.0; @@ -444,22 +444,22 @@ function simplex.Noise4D(x,y,z,w) t4 = t4*t4; n4 = t4 * t4 * Dot4D(Gradients4D[gi4], x4, y4, z4, w4); end - + -- Sum up and scale the result to cover the range [-1,1] - + local retval = 27.0 * (n0 + n1 + n2 + n3 + n4) - + if simplex.internalCache then if not Prev4D[x] then Prev4D[x] = {} end if not Prev4D[x][y] then Prev4D[x][y] = {} end if not Prev4D[x][y][z] then Prev4D[x][y][z] = {} end Prev4D[x][y][z][w] = retval end - + return retval; -end +end local e = 2.71828182845904523536 @@ -469,14 +469,14 @@ function simplex.GBlur2D(x,y,stdDev) if simplex.internalCache and PrevBlur2D[x] and PrevBlur2D[x][y] and PrevBlur2D[x][y][stdDev] then return PrevBlur2D[x][y][stdDev] end local pwr = ((x^2+y^2)/(2*(stdDev^2)))*-1 local ret = (1/(2*math.pi*(stdDev^2)))*(e^pwr) - + if simplex.internalCache then if not PrevBlur2D[x] then PrevBlur2D[x] = {} end if not PrevBlur2D[x][y] then PrevBlur2D[x][y] = {} end PrevBlur2D[x][y][stdDev] = ret end return ret -end +end local PrevBlur1D = {} @@ -497,7 +497,7 @@ function simplex.FractalSum(func, iter, ...) for i=1,iter do local power = 2^iter local s = power/i - + local scaled = {} for elem in ipairs({...}) do table.insert(scaled, elem*s) @@ -512,7 +512,7 @@ function simplex.FractalSumAbs(func, iter, ...) for i=1,iter do local power = 2^iter local s = power/i - + local scaled = {} for elem in ipairs({...}) do table.insert(scaled, elem*s) @@ -527,7 +527,7 @@ function simplex.Turbulence(func, direction, iter, ...) for i=1,iter do local power = 2^iter local s = power/i - + local scaled = {} for elem in ipairs({...}) do table.insert(scaled, elem*s) @@ -556,4 +556,21 @@ function simplex.Seed(seed) end end +-- TODO test functionality +function simplex.FractalBrownianMotion2D(x, y, octaves, lacunarity, gain) + octaves = octaves or 4 + lacunarity = lacunarity or 2 + gain = gain or 0.5 + + local total, amplitude, frequency, peak_amplitude = 0, 1, 1, 0 + for i = 1, octaves do + total = total + amplitude * simplex.Noise2D(x * frequency, y * frequency) + peak_amplitude = peak_amplitude + amplitude + amplitude = amplitude * gain + frequency = frequency * lacunarity + end + + return total / peak_amplitude -- normalize to [-1, 1] +end + return simplex diff --git a/src/main.lua b/src/main.lua index 5185488..74c16e1 100644 --- a/src/main.lua +++ b/src/main.lua @@ -1,3 +1,5 @@ +math.randomseed(os.time()) + local map_generator = require "map_nextgen" local lovebird = require "lib.lovebird" local lume = require "lib.lume" @@ -81,5 +83,9 @@ love.keypressed = function(key) love.event.quit() elseif key == "r" then love.load() + elseif key == "=" then + map.tile_size = map.tile_size * 2 + elseif key == "-" then + map.tile_size = map.tile_size / 2 end end diff --git a/src/map_nextgen.lua b/src/map_nextgen.lua index a250072..8d88066 100644 --- a/src/map_nextgen.lua +++ b/src/map_nextgen.lua @@ -54,7 +54,7 @@ simplex_map.generate = function(size, scale, min, max) for x = 1, map.size do map[x] = {} for y = 1, map.size do - map[x][y] = simplex.Noise2D(x * scale, y * scale) + map[x][y] = simplex.FractalBrownianMotion2D(x * scale, y * scale, 7) end end @@ -117,7 +117,7 @@ local generate = function() local map = {} map.size = 500 map.tile_size = 1 -- TODO tile_size really shouldn't be the responsibility of the map generator - it's a rendering detail, not a map feature - map.altitude = simplex_map.generate(map.size, 0.005, 0, 1) -- meters + map.altitude = simplex_map.generate(map.size, 0.001, 0, 1) -- meters map.temperature = simplex_map.generate(map.size, 0.005, -89.2, 56.7) -- celsius map.rainfall = simplex_map.generate(map.size, 0.005, 18, 3240) -- millimeters rainfall