Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4484e5be27 | ||
|
|
3b43fecc3b |
No files matched your search
+1
-1
@@ -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)
|
||||
|
||||
+138
-42
@@ -1,72 +1,168 @@
|
||||
-- NOTE the API of this file should probably change?
|
||||
|
||||
local lume = require "lib.lume"
|
||||
local simplex = require "lib.simplex"
|
||||
|
||||
local generate = function()
|
||||
simplex.Seed(math.random())
|
||||
local simplex_map = {}
|
||||
|
||||
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 = {} -- TEMP only one noise map
|
||||
|
||||
local scale = 0.005
|
||||
local min, max = math.huge, -math.huge
|
||||
for x = 1, map.size do
|
||||
map.altitude[x] = {}
|
||||
for y = 1, map.size do
|
||||
local value = simplex.Noise2D(x * scale, y * scale)
|
||||
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)
|
||||
|
||||
-- TEMP hacked in copy to fix the issue so I can make sure everything is correct aaa
|
||||
local function min(t)
|
||||
local r = t[1][1]
|
||||
for i=1,#t do
|
||||
for j=1,#t[1] do
|
||||
if r > t[i][j] then r = t[i][j] end
|
||||
simplex_map.min = function(map)
|
||||
local r = map[1][1]
|
||||
for i=1,#map do
|
||||
for j=1,#map[1] do
|
||||
if r > map[i][j] then r = map[i][j] end
|
||||
end
|
||||
end
|
||||
return r
|
||||
end
|
||||
local function max(t)
|
||||
local r = t[1][1]
|
||||
for i=1,#t do
|
||||
for j=1,#t[1] do
|
||||
if r < t[i][j] then r = t[i][j] end
|
||||
simplex_map.max = function(map)
|
||||
local r = map[1][1]
|
||||
for i=1,#map do
|
||||
for j=1,#map[1] do
|
||||
if r < map[i][j] then r = map[i][j] end
|
||||
end
|
||||
end
|
||||
return r
|
||||
end
|
||||
local function normalize(map, new_min, new_max)
|
||||
local minimum = min(map)
|
||||
local initialRange = max(map) - minimum
|
||||
|
||||
simplex_map.normalize = function(map, new_min, new_max)
|
||||
local minimum = simplex_map.min(map)
|
||||
local initialRange = simplex_map.max(map) - minimum
|
||||
local finalRange = new_max - new_min
|
||||
for i = 1, #map do
|
||||
for j = 1, #map[1] do
|
||||
map[i][j] = (map[i][j] - minimum) / initialRange * finalRange + new_min
|
||||
end
|
||||
end
|
||||
map.min = min(map)
|
||||
map.max = max(map)
|
||||
map.min = simplex_map.min(map)
|
||||
map.max = simplex_map.max(map)
|
||||
return map -- superfluous
|
||||
end
|
||||
normalize(map.altitude, 0, 1)
|
||||
|
||||
map.terrain = {}
|
||||
simplex_map.generate = function(size, scale, min, max)
|
||||
if type(size) == "table" then
|
||||
scale = size.scale
|
||||
min = size.min
|
||||
max = size.max
|
||||
size = size.size
|
||||
end
|
||||
|
||||
simplex.Seed(math.random())
|
||||
local map = {}
|
||||
map.size = size
|
||||
|
||||
scale = scale or 0.005
|
||||
for x = 1, map.size do
|
||||
map.terrain[x] = {}
|
||||
map[x] = {}
|
||||
for y = 1, map.size do
|
||||
local value = map.altitude[x][y]
|
||||
map.terrain[x][y] = {value, value, value, 1}
|
||||
map[x][y] = simplex.Noise2D(x * scale, y * scale)
|
||||
end
|
||||
end
|
||||
|
||||
-- NOTE this is missing the radius modifier, so it's a square map
|
||||
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 = 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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
Reference in new issue
Block a user