local heightmap = require "lib.heightmap" local lume = require "lib.lume" local biomes = { -- [5] = { -- name = "ocean", -- altitude = {min = 0, max = 0.2}, -- bottom of world is the only part that matters -- temperature = {min = 0, max = 1}, -- humidity = {min = 0, max = 1}, -- color = {0, 0, 0.67, 1}, -- }, -- [6] = { -- name = "beach", -- altitude = {min = 0.2, max = 0.205}, -- just above ocean -- temperature = {min = 0, max = 1}, -- humidity = {min = 0, max = 0.8}, -- excluding upper humidity for swamp -- color = {1, 1, 0.33, 1}, -- brighter yellow to distinguish from sand -- }, -- [8] = { -- name = "swamp", -- fun idea, but generates between ocean and water too often? -- altitude = {min = 0, max = 1}, -- temperature = {min = 0.5, max = 1}, -- humidity = {min = 0.95, max = 1}, -- color = {0, 0.5, 0.33, 1}, -- }, -- [10] = { -- name = "water", -- altitude = {min = 0, max = 0.9}, -- top excluded because it should've gone downhill -- temperature = {min = 0.1, max = 0.9}, -- bottom should be ice, top should evaporate -- humidity = {min = 0.8, max = 1}, -- only the wettest places -- color = {0, 0, 1, 1}, -- }, -- [20] = { -- name = "sand", -- altitude = {min = 0.2, max = 0.9}, -- top falls down, bottom is underwater -- temperature = {min = 0, max = 1}, -- humidity = {min = 0, max = 0.2}, -- only where dry makes more sense for a desert -- color = {1, 1, 0, 1}, -- }, -- [30] = { -- name = "grass", -- altitude = {min = 0.3, max = 0.9}, -- top of the world not enough air, bottom too wet / leaving space for others -- temperature = {min = 0.2, max = 0.8}, -- not very sensitive to temperature -- humidity = {min = 0.2, max = 0.6}, -- not very sensitive to humidity; but excluded from the worst -- color = {0, 1, 0, 1}, -- }, -- [40] = { -- name = "trees", -- altitude = {min = 0.4, max = 0.7}, -- more sensitive than grass -- temperature = {min = 0, max = 0.7}, -- humidity = {min = 0.3, max = 0.8}, -- these are not desert trees, they need more water -- color = {0, 0.67, 0, 1}, -- }, -- [60] = { -- name = "stone", -- altitude = {min = 0, max = 1}, -- temperature = {min = 0, max = 1}, -- humidity = {min = 0, max = 1}, -- color = {0.67, 0.67, 0.67, 1}, -- }, -- [50] = { -- name = "ice", -- altitude = {min = 0, max = 1}, -- temperature = {min = 0, max = 0.01}, -- humidity = {min = 0.2, max = 1}, -- color = {1, 1, 1, 1}, -- }, [900] = { name = "deep ocean", altitude = {min = -math.huge, max = -5000}, temperature = {min = -math.huge, max = math.huge}, humidity = {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}, humidity = {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}, humidity = {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}, humidity = {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}, humidity = {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}, humidity = {min = -math.huge, max = math.huge}, color = {0.67, 0.67, 0.5, 1}, }, } local function generate() local map = {} map.size = 500 map.tile_size = 1 map.altitude = heightmap.create(map.size, map.size, 0, 1) -- meters map.temperature = heightmap.create(map.size, map.size, -89.2, 56.7) -- celsius map.humidity = heightmap.create(map.size, map.size, 18, 3240) -- millimeters rainfall -- local function earthlike_altitude_adjustment(altitude) -- -- max too low, min too high, too much ocean -- return 6099 - 114909 * altitude + 830891 * altitude^2 - 2.72e6 * altitude^3 + 4.19e6 * altitude^4 - 3.02e6 * altitude^5 + 815866 * altitude^6 -- end local function earthlike_altitude_adjustment(altitude) -- good oceans, too much high altitude return -10948 + 101018 * altitude - 643382 * altitude^2 + 2.17e6 * altitude^3 - 3.62e6 * altitude^4 + 2.87e6 * altitude^5 -852042 * altitude^6 end -- local function earthlike_altitude_adjustment(altitude) -- -- only creates ocean (wtf) -- return -10851 + 151279 * altitude - 1.14e6 * altitude^2 +3.84e6 * altitude^3 -6.11e6 * altitude^4 +4.48e6 * altitude^5 - 1.21e6 * altitude^6 -- end local min, max = math.huge, -math.huge for x = 0, map.size do for y = 0, map.size do local value = earthlike_altitude_adjustment(map.altitude[x][y]) if value > max then max = value end if value < min then min = value end map.altitude[x][y] = value end end print("Altitude", "Min: ", min, "Max:", max) -- planetizer! local biome_order = {} for order in pairs(biomes) do biome_order[#biome_order + 1] = order end table.sort(biome_order) map.terrain = {w = map.size, h = map.size} local radius = (map.size / 2)^2 for x = 0, map.size do map.terrain[x] = {} for y = 0, map.size do if lume.distance(x, y, map.size / 2, map.size / 2, true) < radius then -- for _, biome in ipairs(biomes) do 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 humidity = map.humidity[x][y] if humidity >= biome.humidity.min and humidity <= biome.humidity.max then map.terrain[x][y] = biome.color break end end end end end end end return map end return { generate = generate, }