local random, randomseed = math.random, math.randomseed local floor = math.floor local max, min = math.max, math.min local octaves = 3 local persistence = 0.5 local noised = {} local function cos_interpolate(a, b, x) local ft = x * math.pi local f = (1 - math.cos(ft)) * .5 return a * (1 - f) + b * f end local function noise_2d(x, y, i, seed) local nx = noised[x] if (nx and nx[y]) then return nx[y] else nx = nx or {} randomseed((x * seed + y * i ^ 1.1 + 14) / 789221 + 33 * x + 15731 * y * seed) end random() noised[x] = nx nx[y] = random(-1000, 1000) / 1000 return nx[y] end local function smooth_noise_2d(x, y, i, seed) local corners = (noise_2d(x - 1, y - 1, i, seed) + noise_2d(x + 1, y - 1, i, seed) + noise_2d(x - 1, y + 1, i, seed) + noise_2d(x + 1, y + 1, i, seed)) / 16 local sides = (noise_2d(x - 1, y, i, seed) + noise_2d(x + 1, y, i, seed) + noise_2d(x, y - 1, i, seed) + noise_2d(x, y + 1, i, seed)) / 8 local center = noise_2d(x, y, i, seed) / 4 return corners + sides + center end local function interpolate_noise_2d(x, y, i, seed) local int_x = floor(x) local frac_x = x - int_x local int_y = floor(y) local frac_y = y - int_y local v1 = smooth_noise_2d(int_x, int_y, i, seed) local v2 = smooth_noise_2d(int_x + 1, int_y, i, seed) local v3 = smooth_noise_2d(int_x, int_y + 1, i, seed) local v4 = smooth_noise_2d(int_x + 1, int_y + 1, i, seed) local i1 = cos_interpolate(v1, v2, frac_x) local i2 = cos_interpolate(v3, v4, frac_x) return cos_interpolate(i1, i2, frac_y) end local function perlin_2d(x, y, seed) local total = 0 local p = persistence local n = octaves - 1 for i = 0, n do local frequency = 2 ^ i local amplitude = p ^ i total = total + interpolate_noise_2d(x * frequency, y * frequency, i, seed) * amplitude end return total end local points = {} local size = 150 local scale = 2 local can local time_taken = 0 local mx, my = 0, 0 function love.update() mx, my = love.mouse.getPosition() mx = floor((mx + 100 + (size / 2)) / scale) my = floor((my + 100 + (size / 2)) / scale) end function love.keydown(key) if (key == "escape") then love.event.push("quit") end end function love.load() local start = love.timer.getMicroTime() for x = -size, size do points[x] = {} local ax = points[x] for y = -size, size do ax[y] = min(max(perlin_2d(x / 4, y / 4, 4923), -1), 1) end end time_taken = love.timer.getMicroTime() - start can = love.graphics.newCanvas() love.graphics.setCanvas(can) love.graphics.setPointStyle("rough") love.graphics.setPointSize(scale) for x = -size, size do local ax = points[x] for y = -size, size do local c = ax[y] * 127.5 + 127.5 love.graphics.setColor(c, c, c) love.graphics.point(x, y) end end love.graphics.setCanvas() end function love.draw() love.graphics.setColor(255, 255, 255) love.graphics.print("Generated in " .. time_taken .. " seconds!", 4, 4) if (points[mx] and points[mx][my]) then love.graphics.print("(" .. mx .. ", " .. my .. "): " .. points[mx][my], 4, 20) end love.graphics.draw(can, 100, 100, 0, scale, scale) end