From 4484e5be27530f68a441bc11813c2ed6c00791a5 Mon Sep 17 00:00:00 2001 From: Tangent Date: Tue, 18 Aug 2026 23:54:35 -0600 Subject: [PATCH] almost forgot to commit today --- src/main.lua | 2 +- src/map_nextgen.lua | 106 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 96 insertions(+), 12 deletions(-) diff --git a/src/main.lua b/src/main.lua index 7bc1b7e..5185488 100644 --- a/src/main.lua +++ b/src/main.lua @@ -67,7 +67,7 @@ love.draw = function() for x = 1, map.size do for y = 1, map.size do -- print(x, y) -- TEMP why am I getting an out of bounds? - local value = map.terrain[x][y] + local value = map.biome[x][y] if value then love.graphics.setColor(value) love.graphics.rectangle("fill", x * map.tile_size, y * map.tile_size, map.tile_size, map.tile_size) diff --git a/src/map_nextgen.lua b/src/map_nextgen.lua index 02f0fd0..a250072 100644 --- a/src/map_nextgen.lua +++ b/src/map_nextgen.lua @@ -1,5 +1,6 @@ -- NOTE the API of this file should probably change? +local lume = require "lib.lume" local simplex = require "lib.simplex" local simplex_map = {} @@ -57,28 +58,111 @@ simplex_map.generate = function(size, scale, min, max) end end - min = min or 0 - max = max or 1 - simplex_map.normalize(map, min, max) + if min or max then + min = min or 0 + max = max or 1 + simplex_map.normalize(map, min, max) + end return map end +local biomes = { + -- biomes are checked in order, with the first candidate always being selected + [900] = { + name = "deep ocean", + altitude = {min = -math.huge, max = -5000}, + temperature = {min = -math.huge, max = math.huge}, + rainfall = {min = -math.huge, max = math.huge}, + color = {0, 0, 0.25, 1}, + }, + [1000] = { + name = "ocean (definition, 0 meters)", + altitude = {min = -math.huge, max = 0}, + temperature = {min = -math.huge, max = math.huge}, + rainfall = {min = -math.huge, max = math.huge}, + color = {0, 0, 0.5, 1}, + }, + [2000] = { + name = "snowline (middle estimate)", + altitude = {min = 4000, max = math.huge}, + temperature = {min = -math.huge, max = math.huge}, + rainfall = {min = -math.huge, max = math.huge}, + color = {1, 1, 1, 1}, + }, + [2100] = { + name = "alpine zone", + altitude = {min = 3500, max = math.huge}, + temperature = {min = -math.huge, max = math.huge}, + rainfall = {min = -math.huge, max = math.huge}, + color = {0.8, 0.8, 0.8, 1}, + }, + [2200] = { + name = "subalpine zone", + altitude = {min = 3000, max = math.huge}, + temperature = {min = -math.huge, max = math.huge}, + rainfall = {min = -math.huge, max = math.huge}, + color = {0.67, 0.67, 0.67, 1}, + }, + [2300] = { + name = "montane zone", + altitude = {min = 2500, max = math.huge}, + temperature = {min = -math.huge, max = math.huge}, + rainfall = {min = -math.huge, max = math.huge}, + color = {0.67, 0.67, 0.5, 1}, + }, +} + 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 = {} + map.altitude = simplex_map.generate(map.size, 0.005, 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 - map.terrain = simplex_map.generate(map.size) - for x = 1, map.size do - for y = 1, map.size do - local value = map.terrain[x][y] - map.terrain[x][y] = {value, value, value, 1} - end + local function earthlike_altitude_adjustment(altitude) + -- TODO replace with a simpler function? + return 6099 - 114909 * altitude + 830891 * altitude^2 - 2.72e6 * altitude^3 + 4.19e6 * altitude^4 - 3.02e6 * altitude^5 + 815866 * altitude^6 end - -- NOTE this is missing the radius modifier, so it's a square map + for x = 1, map.size do + for y = 1, map.size do + map.altitude[x][y] = earthlike_altitude_adjustment(map.altitude[x][y]) + end + end + map.altitude.min = simplex_map.min(map.altitude) + map.altitude.max = simplex_map.max(map.altitude) + + local biome_order = {} + for order in pairs(biomes) do + biome_order[#biome_order + 1] = order + end + table.sort(biome_order) + + local radius_squared = (map.size / 2)^2 + map.biome = {} + for x = 1, map.size do + map.biome[x] = {} + for y = 1, map.size do + if lume.distance(x, y, map.size / 2, map.size / 2, true) < radius_squared then + for _, order in ipairs(biome_order) do + local biome = biomes[order] + local altitude = map.altitude[x][y] + if altitude >= biome.altitude.min and altitude <= biome.altitude.max then + local temperature = map.temperature[x][y] + if temperature >= biome.temperature.min and temperature <= biome.temperature.max then + local rainfall = map.rainfall[x][y] + if rainfall >= biome.rainfall.min and rainfall <= biome.rainfall.max then + map.biome[x][y] = biome.color + break + end + end + end + end + end + end + end return map end