Add (broken) visibility
This commit is contained in:
parent
3202549a2a
commit
3638295e6c
1 changed files with 228 additions and 13 deletions
231
bundle/main.lua
231
bundle/main.lua
|
@ -1,6 +1,9 @@
|
||||||
local cavern = {}
|
local cavern = {}
|
||||||
local tiletypes = {unknown = 0, empty = 1, wall = 2}
|
local tiletypes = {unknown = 0, empty = 1, wall = 2}
|
||||||
|
|
||||||
|
local visibility_map = {}
|
||||||
|
local remembered_cavern = {}
|
||||||
|
|
||||||
local spawn_x = nil
|
local spawn_x = nil
|
||||||
local spawn_y = nil
|
local spawn_y = nil
|
||||||
|
|
||||||
|
@ -56,12 +59,12 @@ function generateCavern()
|
||||||
table.insert(queue, {x = spawn_x + 1, y = spawn_y})
|
table.insert(queue, {x = spawn_x + 1, y = spawn_y})
|
||||||
|
|
||||||
repeat
|
repeat
|
||||||
queue, size = stepTilesGeneration(queue, size)
|
queue, size = stepCavernGeneration(queue, size)
|
||||||
until #queue == 0
|
until #queue == 0
|
||||||
until size > 200
|
until size > 200
|
||||||
end
|
end
|
||||||
|
|
||||||
function stepTilesGeneration(queue, size)
|
function stepCavernGeneration(queue, size)
|
||||||
-- Tuning this parameter will change how open and cavernous vs. closed and corridory the
|
-- Tuning this parameter will change how open and cavernous vs. closed and corridory the
|
||||||
-- cavern will be
|
-- cavern will be
|
||||||
local spread_probability = 0.6
|
local spread_probability = 0.6
|
||||||
|
@ -133,6 +136,185 @@ function spawnPlayer()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ------------------------------------------------------------------
|
||||||
|
-- Visibility
|
||||||
|
-- ------------------------------------------------------------------
|
||||||
|
|
||||||
|
function generateVisibilityMap()
|
||||||
|
-- Start by creating a new visibility map (since we'll have to recompute everything anyways)
|
||||||
|
visibility_map = {}
|
||||||
|
for x = 1, cavern.width do
|
||||||
|
local list = {}
|
||||||
|
for y = 1, cavern.height do
|
||||||
|
table.insert(list, false)
|
||||||
|
end
|
||||||
|
table.insert(visibility_map, list)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle visibility from the head
|
||||||
|
local queue = {}
|
||||||
|
|
||||||
|
if player_direction == directions.up then
|
||||||
|
-- ⌜^⌝
|
||||||
|
-- <o>
|
||||||
|
table.insert(queue, {x = player_x - 1, y = player_y - 1, direction = directions.upleft})
|
||||||
|
table.insert(queue, {x = player_x, y = player_y - 1, direction = directions.up})
|
||||||
|
table.insert(queue, {x = player_x + 1, y = player_y - 1, direction = directions.upright})
|
||||||
|
|
||||||
|
table.insert(queue, {x = player_x - 1, y = player_y, direction = directions.left})
|
||||||
|
table.insert(queue, {x = player_x + 1, y = player_y, direction = directions.right})
|
||||||
|
elseif player_direction == directions.left then
|
||||||
|
-- ⌜^
|
||||||
|
-- <o
|
||||||
|
-- ⌞v
|
||||||
|
table.insert(queue, {x = player_x - 1, y = player_y - 1, direction = directions.upleft})
|
||||||
|
table.insert(queue, {x = player_x, y = player_y - 1, direction = directions.up})
|
||||||
|
|
||||||
|
table.insert(queue, {x = player_x - 1, y = player_y, direction = directions.left})
|
||||||
|
|
||||||
|
table.insert(queue, {x = player_x - 1, y = player_y + 1, direction = directions.downleft})
|
||||||
|
table.insert(queue, {x = player_x, y = player_y + 1, direction = directions.down})
|
||||||
|
elseif player_direction == directions.down then
|
||||||
|
-- <o>
|
||||||
|
-- ⌞v⌟
|
||||||
|
table.insert(queue, {x = player_x - 1, y = player_y, direction = directions.left})
|
||||||
|
table.insert(queue, {x = player_x + 1, y = player_y, direction = directions.right})
|
||||||
|
|
||||||
|
table.insert(queue, {x = player_x - 1, y = player_y + 1, direction = directions.downleft})
|
||||||
|
table.insert(queue, {x = player_x, y = player_y + 1, direction = directions.down})
|
||||||
|
table.insert(queue, {x = player_x + 1, y = player_y + 1, direction = directions.downright})
|
||||||
|
elseif player_direction == directions.right then
|
||||||
|
-- ^⌝
|
||||||
|
-- o>
|
||||||
|
-- v⌟
|
||||||
|
table.insert(queue, {x = player_x, y = player_y - 1, direction = directions.up})
|
||||||
|
table.insert(queue, {x = player_x + 1, y = player_y - 1, direction = directions.upright})
|
||||||
|
|
||||||
|
table.insert(queue, {x = player_x + 1, y = player_y, direction = directions.right})
|
||||||
|
|
||||||
|
table.insert(queue, {x = player_x, y = player_y + 1, direction = directions.down})
|
||||||
|
table.insert(queue, {x = player_x + 1, y = player_y + 1, direction = directions.downright})
|
||||||
|
else
|
||||||
|
error("Player facing an impossible direction")
|
||||||
|
end
|
||||||
|
|
||||||
|
repeat
|
||||||
|
queue = stepVisibilityMapGeneration(queue)
|
||||||
|
until #queue == 0
|
||||||
|
|
||||||
|
-- Handle "visibility" from the feet
|
||||||
|
local body_x, body_y = getBodyLocation()
|
||||||
|
|
||||||
|
if player_direction == directions.up then
|
||||||
|
-- <x>
|
||||||
|
-- v
|
||||||
|
visibility_map[body_x - 1][body_y] = true
|
||||||
|
visibility_map[body_x + 1][body_y] = true
|
||||||
|
|
||||||
|
visibility_map[body_x][body_y + 1] = true
|
||||||
|
elseif player_direction == directions.left then
|
||||||
|
-- ^
|
||||||
|
-- x>
|
||||||
|
-- v
|
||||||
|
visibility_map[body_x][body_y - 1] = true
|
||||||
|
|
||||||
|
visibility_map[body_x + 1][body_y] = true
|
||||||
|
|
||||||
|
visibility_map[body_x][body_y + 1] = true
|
||||||
|
elseif player_direction == directions.down then
|
||||||
|
-- ^
|
||||||
|
-- <x>
|
||||||
|
visibility_map[body_x][body_y - 1] = true
|
||||||
|
|
||||||
|
visibility_map[body_x - 1][body_y] = true
|
||||||
|
visibility_map[body_x + 1][body_y] = true
|
||||||
|
elseif player_direction == directions.right then
|
||||||
|
-- ^
|
||||||
|
-- <x
|
||||||
|
-- v
|
||||||
|
visibility_map[body_x][body_y - 1] = true
|
||||||
|
|
||||||
|
visibility_map[body_x - 1][body_y] = true
|
||||||
|
|
||||||
|
visibility_map[body_x][body_y + 1] = true
|
||||||
|
else
|
||||||
|
error("Player facing an impossible direction")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function stepVisibilityMapGeneration(queue)
|
||||||
|
-- TODO: Handle corners somehow correctly
|
||||||
|
-- Do a modified floodfill, where each cell will only expand in its given direction, not
|
||||||
|
-- every direction like in a normal floodfill
|
||||||
|
local new_queue = {}
|
||||||
|
|
||||||
|
for i, item in ipairs(queue) do
|
||||||
|
visibility_map[item.x][item.y] = true
|
||||||
|
|
||||||
|
if cavern[item.x][item.y] == tiletypes.empty then
|
||||||
|
-- Did not yet hit a wall
|
||||||
|
if item.direction == directions.up then
|
||||||
|
table.insert(new_queue, {x = item.x, y = item.y - 1, direction = directions.up})
|
||||||
|
elseif item.direction == directions.left then
|
||||||
|
table.insert(new_queue, {x = item.x - 1, y = item.y, direction = directions.left})
|
||||||
|
elseif item.direction == directions.down then
|
||||||
|
table.insert(new_queue, {x = item.x, y = item.y + 1, direction = directions.down})
|
||||||
|
elseif item.direction == directions.right then
|
||||||
|
table.insert(new_queue, {x = item.x + 1, y = item.y, direction = directions.right})
|
||||||
|
elseif item.direction == directions.upleft then
|
||||||
|
-- ⌜^
|
||||||
|
-- ⌜ <x
|
||||||
|
table.insert(new_queue, {x = item.x - 1, y = item.y - 1, direction = directions.upleft})
|
||||||
|
table.insert(new_queue, {x = item.x, y = item.y - 1, direction = directions.up})
|
||||||
|
table.insert(new_queue, {x = item.x - 1, y = item.y, direction = directions.left})
|
||||||
|
elseif item.direction == directions.downleft then
|
||||||
|
-- ⌞ <x
|
||||||
|
-- ⌞v
|
||||||
|
table.insert(new_queue, {x = item.x - 1, y = item.y, direction = directions.left})
|
||||||
|
table.insert(new_queue, {x = item.x - 1, y = item.y + 1, direction = directions.downleft})
|
||||||
|
table.insert(new_queue, {x = item.x, y = item.y + 1, direction = directions.down})
|
||||||
|
elseif item.direction == directions.downright then
|
||||||
|
-- ⌟ x>
|
||||||
|
-- v⌟
|
||||||
|
table.insert(new_queue, {x = item.x + 1, y = item.y, direction = directions.right})
|
||||||
|
table.insert(new_queue, {x = item.x, y = item.y + 1, direction = directions.down})
|
||||||
|
table.insert(new_queue, {x = item.x + 1, y = item.y + 1, direction = directions.downright})
|
||||||
|
elseif item.direction == directions.upright then
|
||||||
|
-- ^⌝
|
||||||
|
-- ⌝ x>
|
||||||
|
table.insert(new_queue, {x = item.x, y = item.y - 1, direction = directions.up})
|
||||||
|
table.insert(new_queue, {x = item.x + 1, y = item.y - 1, direction = directions.upright})
|
||||||
|
table.insert(new_queue, {x = item.x + 1, y = item.y, direction = directions.right})
|
||||||
|
else
|
||||||
|
error("Visibility floodfill item travelling in an impossible direction")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return new_queue
|
||||||
|
end
|
||||||
|
|
||||||
|
function initializeRememberedCavern()
|
||||||
|
remembered_cavern = {}
|
||||||
|
for x = 1, cavern.width do
|
||||||
|
local list = {}
|
||||||
|
for y = 1, cavern.height do
|
||||||
|
table.insert(list, nil)
|
||||||
|
end
|
||||||
|
table.insert(remembered_cavern, list)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function rememberVisible()
|
||||||
|
for x, list in ipairs(visibility_map) do
|
||||||
|
for y, visible in ipairs(list) do
|
||||||
|
if visible then
|
||||||
|
remembered_cavern[x][y] = cavern[x][y]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- ------------------------------------------------------------------
|
-- ------------------------------------------------------------------
|
||||||
-- Player helper functions
|
-- Player helper functions
|
||||||
-- ------------------------------------------------------------------
|
-- ------------------------------------------------------------------
|
||||||
|
@ -200,7 +382,7 @@ function movePlayer(direction)
|
||||||
dx = -1
|
dx = -1
|
||||||
new_direction = directions.down
|
new_direction = directions.down
|
||||||
else
|
else
|
||||||
new_direction = player_direction
|
error("Player facing an impossible direction")
|
||||||
end
|
end
|
||||||
elseif direction == directions.downleft then
|
elseif direction == directions.downleft then
|
||||||
if player_direction == directions.up then
|
if player_direction == directions.up then
|
||||||
|
@ -222,7 +404,7 @@ function movePlayer(direction)
|
||||||
dx = -1
|
dx = -1
|
||||||
new_direction = directions.up
|
new_direction = directions.up
|
||||||
else
|
else
|
||||||
new_direction = player_direction
|
error("Player facing an impossible direction")
|
||||||
end
|
end
|
||||||
elseif direction == directions.downright then
|
elseif direction == directions.downright then
|
||||||
if player_direction == directions.up then
|
if player_direction == directions.up then
|
||||||
|
@ -244,7 +426,7 @@ function movePlayer(direction)
|
||||||
dy = 1
|
dy = 1
|
||||||
new_direction = directions.down
|
new_direction = directions.down
|
||||||
else
|
else
|
||||||
new_direction = player_direction
|
error("Player facing an impossible direction")
|
||||||
end
|
end
|
||||||
elseif direction == directions.upright then
|
elseif direction == directions.upright then
|
||||||
if player_direction == directions.up then
|
if player_direction == directions.up then
|
||||||
|
@ -266,7 +448,7 @@ function movePlayer(direction)
|
||||||
dy = -1
|
dy = -1
|
||||||
new_direction = directions.up
|
new_direction = directions.up
|
||||||
else
|
else
|
||||||
new_direction = player_direction
|
error("Player facing an impossible direction")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
error("Player moving in an impossible direction")
|
error("Player moving in an impossible direction")
|
||||||
|
@ -291,6 +473,8 @@ function love.load()
|
||||||
|
|
||||||
generateCavern()
|
generateCavern()
|
||||||
spawnPlayer()
|
spawnPlayer()
|
||||||
|
generateVisibilityMap()
|
||||||
|
initializeRememberedCavern()
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.update(dt)
|
function love.update(dt)
|
||||||
|
@ -300,22 +484,40 @@ function love.keypressed(key)
|
||||||
if key == 'r' then
|
if key == 'r' then
|
||||||
generateCavern()
|
generateCavern()
|
||||||
spawnPlayer()
|
spawnPlayer()
|
||||||
|
generateVisibilityMap()
|
||||||
|
initializeRememberedCavern()
|
||||||
elseif key == 'i' then
|
elseif key == 'i' then
|
||||||
|
rememberVisible()
|
||||||
movePlayer(directions.up)
|
movePlayer(directions.up)
|
||||||
|
generateVisibilityMap()
|
||||||
elseif key == 'j' then
|
elseif key == 'j' then
|
||||||
|
rememberVisible()
|
||||||
movePlayer(directions.left)
|
movePlayer(directions.left)
|
||||||
|
generateVisibilityMap()
|
||||||
elseif key == 'k' then
|
elseif key == 'k' then
|
||||||
|
rememberVisible()
|
||||||
movePlayer(directions.down)
|
movePlayer(directions.down)
|
||||||
|
generateVisibilityMap()
|
||||||
elseif key == 'l' then
|
elseif key == 'l' then
|
||||||
|
rememberVisible()
|
||||||
movePlayer(directions.right)
|
movePlayer(directions.right)
|
||||||
|
generateVisibilityMap()
|
||||||
elseif key == 'u' then
|
elseif key == 'u' then
|
||||||
|
rememberVisible()
|
||||||
movePlayer(directions.upleft)
|
movePlayer(directions.upleft)
|
||||||
|
generateVisibilityMap()
|
||||||
elseif key == 'm' then
|
elseif key == 'm' then
|
||||||
|
rememberVisible()
|
||||||
movePlayer(directions.downleft)
|
movePlayer(directions.downleft)
|
||||||
|
generateVisibilityMap()
|
||||||
elseif key == '.' then
|
elseif key == '.' then
|
||||||
|
rememberVisible()
|
||||||
movePlayer(directions.downright)
|
movePlayer(directions.downright)
|
||||||
|
generateVisibilityMap()
|
||||||
elseif key == 'o' then
|
elseif key == 'o' then
|
||||||
|
rememberVisible()
|
||||||
movePlayer(directions.upright)
|
movePlayer(directions.upright)
|
||||||
|
generateVisibilityMap()
|
||||||
elseif key == 'q' then
|
elseif key == 'q' then
|
||||||
love.event.quit()
|
love.event.quit()
|
||||||
else
|
else
|
||||||
|
@ -328,11 +530,14 @@ function love.draw()
|
||||||
local y_scale = love.graphics.getHeight() / cavern.height
|
local y_scale = love.graphics.getHeight() / cavern.height
|
||||||
|
|
||||||
-- Draw the cavern
|
-- Draw the cavern
|
||||||
for tile_x, list in ipairs(cavern) do
|
for tile_x, list in ipairs(visibility_map) do
|
||||||
local x = (tile_x - 1) * x_scale
|
local x = (tile_x - 1) * x_scale
|
||||||
for tile_y, tile in ipairs(list) do
|
for tile_y, visible in ipairs(list) do
|
||||||
local y = (tile_y - 1) * y_scale
|
local y = (tile_y - 1) * y_scale
|
||||||
|
|
||||||
|
if visible then
|
||||||
|
tile = cavern[tile_x][tile_y]
|
||||||
|
|
||||||
if tile == tiletypes.empty then
|
if tile == tiletypes.empty then
|
||||||
love.graphics.setColor(0, 0, 0)
|
love.graphics.setColor(0, 0, 0)
|
||||||
elseif tile == tiletypes.wall then
|
elseif tile == tiletypes.wall then
|
||||||
|
@ -340,6 +545,16 @@ function love.draw()
|
||||||
else
|
else
|
||||||
love.graphics.setColor(1, 0.5, 0.5)
|
love.graphics.setColor(1, 0.5, 0.5)
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
tile = remembered_cavern[tile_x][tile_y]
|
||||||
|
if tile == tiletypes.empty then
|
||||||
|
love.graphics.setColor(0.2, 0.2, 0.2)
|
||||||
|
elseif tile == tiletypes.wall then
|
||||||
|
love.graphics.setColor(0.8, 0.8, 0.8)
|
||||||
|
else
|
||||||
|
love.graphics.setColor(0.3, 0.3, 0.3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
love.graphics.rectangle('fill', x, y, x_scale, y_scale)
|
love.graphics.rectangle('fill', x, y, x_scale, y_scale)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue