134 lines
3.8 KiB
Lua
134 lines
3.8 KiB
Lua
local heightmap = require "lib.heightmap"
|
|
local lovebird = require "lib.lovebird"
|
|
local lume = require "lib.lume"
|
|
|
|
local map = {}
|
|
|
|
local biomes = {
|
|
water = {
|
|
altitude = {min = 0, max = 0.2},
|
|
color = {0, 0, 1, 1},
|
|
},
|
|
sand = {
|
|
altitude = {min = 0.2, max = 0.215},
|
|
color = {1, 1, 0, 1},
|
|
},
|
|
grass = {
|
|
altitude = {min = 0.215, max = 0.34},
|
|
color = {0, 1, 0, 1},
|
|
},
|
|
trees = {
|
|
altitude = {min = 0.34, max = 0.72},
|
|
color = {0, 0.67, 0, 1},
|
|
},
|
|
stone = {
|
|
altitude = {min = 0.72, max = 0.9},
|
|
color = {0.67, 0.67, 0.67, 1},
|
|
},
|
|
ice = {
|
|
altitude = {min = 0.9, max = 1},
|
|
color = {1, 1, 1, 1}
|
|
},
|
|
}
|
|
|
|
love.load = function()
|
|
map.size = 150
|
|
map.altitude = heightmap.create(map.size, map.size, 0, 1)
|
|
map.temperature = heightmap.create(map.size, map.size, 0, 1)
|
|
map.humidity = heightmap.create(map.size, map.size, 0, 1)
|
|
|
|
-- if true then return end
|
|
|
|
-- lower temperature by half height
|
|
-- NOTE ruins "normalization" but that's fine once we have "real" numbers to work with
|
|
for x = 0, map.temperature.w do
|
|
for y = 0, map.temperature.h do
|
|
map.temperature[x][y] = math.max(0, map.temperature[x][y] - map.altitude[x][y] / 2)
|
|
end
|
|
end
|
|
heightmap.normalize(map.temperature, 0, 1)
|
|
|
|
-- modify temperature by latitude
|
|
-- TODO would be more efficient to calculate Y in outer loop, since X does not change the distance
|
|
-- NOTE only subtracts temperature, which further "ruins normalization" and makes everything too cold:
|
|
local center_y = map.size / 2
|
|
for x = 0, map.temperature.w do
|
|
for y = 0, map.temperature.h do
|
|
local distance = math.abs(y - center_y)
|
|
map.temperature[x][y] = lume.clamp(map.temperature[x][y] - distance / map.size / 2, 0, 1)
|
|
end
|
|
end
|
|
heightmap.normalize(map.temperature, 0, 1)
|
|
|
|
-- increase humidity by half temperature
|
|
for x = 0, map.humidity.w do
|
|
for y = 0, map.humidity.h do
|
|
map.humidity[x][y] = math.min(1, map.humidity[x][y] + map.temperature[x][y] / 2)
|
|
end
|
|
end
|
|
|
|
-- planetizer!
|
|
map.terrain = {}
|
|
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 name, biome in pairs(biomes) do
|
|
local value = map.altitude[x][y]
|
|
-- this allows a non-deterministic change of terrain
|
|
-- depending on which biome is checked first but I don't care right now]
|
|
if value >= biome.altitude.min and value <= biome.altitude.max then
|
|
map.terrain[x][y] = biome.color
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
love.update = function(dt)
|
|
lovebird.update()
|
|
end
|
|
|
|
love.draw = function()
|
|
local tile_size = 2
|
|
|
|
for x = 0, map.altitude.w do
|
|
for y = 0, map.altitude.h do
|
|
-- raw heightmap
|
|
local value = map.altitude[x][y]
|
|
if value then
|
|
love.graphics.setColor(value, value, value, 1)
|
|
love.graphics.rectangle("fill", x * tile_size, y * tile_size, tile_size, tile_size)
|
|
end
|
|
|
|
-- temperature map
|
|
local value = map.temperature[x][y]
|
|
love.graphics.setColor(value, 0, 0, 1)
|
|
love.graphics.rectangle("fill", map.size * tile_size + x * tile_size, y * tile_size, tile_size, tile_size)
|
|
|
|
-- humidity map
|
|
local value = map.humidity[x][y]
|
|
love.graphics.setColor(0, 0, value, 1)
|
|
love.graphics.rectangle("fill", x * tile_size, map.size * tile_size + y * tile_size, tile_size, tile_size)
|
|
|
|
-- "naive" biomed map
|
|
local value = map.terrain[x][y]
|
|
if value then
|
|
love.graphics.setColor(value)
|
|
love.graphics.rectangle("fill", map.size * tile_size + x * tile_size, map.size * tile_size + y * tile_size, tile_size, tile_size)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
love.keypressed = function(key)
|
|
if key == "escape" then
|
|
love.event.quit()
|
|
elseif key == "r" then
|
|
love.load()
|
|
end
|
|
end
|