local tex = love.graphics.newImage("atlas.png") tex:setFilter("nearest", "nearest") local function water_color(layer) local value = layer / 24 return value / 4, value / 2, value end local function sand_color(layer) return layer / 32 + 0.2, layer / 32 + 0.15, 0.4 end local function dirt_color(layer) if layer < 32 then return layer / 40 / 2.5, layer / 80 / 2.5, 0.1 else return 0.05, (layer - 32) / 36 + 0.3, 0.05 end end local function mountain_color(layer) if layer < 58 then local value = layer / 64 / 2 - 0.1 return value, value, value else local value = (layer - 58) / 20 + 0.7 return value, value, value end end local function pick_colorfn(maxlayer) if maxlayer < 16 then return water_color elseif maxlayer < 22 then return sand_color elseif maxlayer < 46 then return dirt_color else return mountain_color end end local function ease(n) return 5 ^ (3.1 * (n ^ 0.3) - 3) + 1 - 1.1 ^ n end local WATER = love.graphics.newQuad(1, 1, 8, 8, tex) local SAND = love.graphics.newQuad(11, 1, 8, 8, tex) local DIRT = love.graphics.newQuad(21, 1, 8, 8, tex) local GRASS = love.graphics.newQuad(31, 1, 8, 8, tex) local STONE = love.graphics.newQuad(1, 11, 8, 8, tex) local SNOW = love.graphics.newQuad(11, 11, 8, 8, tex) local function dirt_sprite(layer) if layer < 32 then return DIRT end return GRASS end local function mountain_sprite(layer) if layer < 58 then return STONE end return SNOW end local function pick_sprite(maxlayer) if maxlayer < 16 then return WATER end if maxlayer < 22 then return SAND end if maxlayer < 46 then return dirt_sprite end return mountain_sprite end local z = require("zprite").zchunk.new(tex, 128, 64) local function update_map() z:clear() for i = -160, 160 do for j = -160, 160 do local noise_value = love.math.simplexNoise(i * 0.008, j * 0.008) local layers = ease(noise_value) * 64 z:put(i * 8, j * 8, pick_sprite(layers), math.floor(layers) + 1, pick_colorfn(layers)) coroutine.yield() end end end local co = coroutine.create(update_map) local x = 0 local y = 0 local angle = 0 local scale = 1 function love.update(dt) for _ = 1, 64 do if coroutine.status(co) == "suspended" then coroutine.resume(co) end end if love.keyboard.isDown("d") then local dx = 256 * math.cos(-angle) local dy = 256 * math.sin(-angle) x = x - dx * dt y = y - dy * dt end if love.keyboard.isDown("a") then local dx = 256 * math.cos(-angle) local dy = 256 * math.sin(-angle) x = x + dx * dt y = y + dy * dt end if love.keyboard.isDown("s") then local dx = 256 * math.cos(-angle + math.pi / 2) local dy = 256 * math.sin(-angle + math.pi / 2) x = x - dx * dt y = y - dy * dt end if love.keyboard.isDown("w") then local dx = 256 * math.cos(-angle + math.pi / 2) local dy = 256 * math.sin(-angle + math.pi / 2) x = x + dx * dt y = y + dy * dt end if love.keyboard.isDown("q") then angle = angle + dt end if love.keyboard.isDown("e") then angle = angle - dt end if love.keyboard.isDown("f") then scale = scale - dt * 5 if scale < 0.2 then scale = 0.2 end end if love.keyboard.isDown("r") then scale = scale + dt * 5 if scale > 5 then scale = 5 end end end local t = love.math.newTransform() function love.draw() for _, chunk in pairs(z._chunks) do chunk.z._height_scale = 12 * scale end t:reset() t:translate(love.graphics.getWidth() / 2, love.graphics.getHeight() / 2) t:scale(scale, scale) t:rotate(angle) t:translate(x, y) z:draw(t) end