diff --git a/src/main.lua b/src/main.lua index 93a9037..29a000d 100644 --- a/src/main.lua +++ b/src/main.lua @@ -1,139 +1,11 @@ -local heightmap = require "lib.heightmap" +local map_generator = require "map_generator" local lovebird = require "lib.lovebird" local lume = require "lib.lume" -local map = {} - -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 = -400}, - 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 map love.load = function() - map.size = 500 - map.tile_size = 1 - map.altitude = heightmap.create(map.size, map.size, -440, 8849) -- 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 altitude_ocean_bias(altitude) - local bias = 3.5 -- higher -> more ocean - local normalized_altitude = (altitude - -400) / (8849 - -440) - return -440 + normalized_altitude^bias * (8849 - -440) - end - local min, max = math.huge, -math.huge - for x = 0, map.size do - for y = 0, map.size do - local value = altitude_ocean_bias(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) + map = map_generator.generate() -- if true then return end @@ -165,38 +37,6 @@ love.load = function() -- end -- end -- heightmap.normalize(map.humidity, 18, 3240) - - -- 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 end local camera = { diff --git a/src/map_generator.lua b/src/map_generator.lua new file mode 100644 index 0000000..8df32b6 --- /dev/null +++ b/src/map_generator.lua @@ -0,0 +1,174 @@ +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 = -400}, + 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, -440, 8849) -- 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 altitude_ocean_bias(altitude) + local bias = 3.5 -- higher -> more ocean + local normalized_altitude = (altitude - -400) / (8849 - -440) + return -440 + normalized_altitude^bias * (8849 - -440) + end + local min, max = math.huge, -math.huge + for x = 0, map.size do + for y = 0, map.size do + local value = altitude_ocean_bias(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, +}