Add (broken) visibility

This commit is contained in:
Juhani Krekelä 2019-06-28 21:53:56 +03:00
parent 3202549a2a
commit 3638295e6c
1 changed files with 228 additions and 13 deletions

View File

@ -1,6 +1,9 @@
local cavern = {}
local tiletypes = {unknown = 0, empty = 1, wall = 2}
local visibility_map = {}
local remembered_cavern = {}
local spawn_x = nil
local spawn_y = nil
@ -56,12 +59,12 @@ function generateCavern()
table.insert(queue, {x = spawn_x + 1, y = spawn_y})
repeat
queue, size = stepTilesGeneration(queue, size)
queue, size = stepCavernGeneration(queue, size)
until #queue == 0
until size > 200
end
function stepTilesGeneration(queue, size)
function stepCavernGeneration(queue, size)
-- Tuning this parameter will change how open and cavernous vs. closed and corridory the
-- cavern will be
local spread_probability = 0.6
@ -133,6 +136,185 @@ function spawnPlayer()
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
-- ------------------------------------------------------------------
@ -200,7 +382,7 @@ function movePlayer(direction)
dx = -1
new_direction = directions.down
else
new_direction = player_direction
error("Player facing an impossible direction")
end
elseif direction == directions.downleft then
if player_direction == directions.up then
@ -222,7 +404,7 @@ function movePlayer(direction)
dx = -1
new_direction = directions.up
else
new_direction = player_direction
error("Player facing an impossible direction")
end
elseif direction == directions.downright then
if player_direction == directions.up then
@ -244,7 +426,7 @@ function movePlayer(direction)
dy = 1
new_direction = directions.down
else
new_direction = player_direction
error("Player facing an impossible direction")
end
elseif direction == directions.upright then
if player_direction == directions.up then
@ -266,7 +448,7 @@ function movePlayer(direction)
dy = -1
new_direction = directions.up
else
new_direction = player_direction
error("Player facing an impossible direction")
end
else
error("Player moving in an impossible direction")
@ -291,6 +473,8 @@ function love.load()
generateCavern()
spawnPlayer()
generateVisibilityMap()
initializeRememberedCavern()
end
function love.update(dt)
@ -300,22 +484,40 @@ function love.keypressed(key)
if key == 'r' then
generateCavern()
spawnPlayer()
generateVisibilityMap()
initializeRememberedCavern()
elseif key == 'i' then
rememberVisible()
movePlayer(directions.up)
generateVisibilityMap()
elseif key == 'j' then
rememberVisible()
movePlayer(directions.left)
generateVisibilityMap()
elseif key == 'k' then
rememberVisible()
movePlayer(directions.down)
generateVisibilityMap()
elseif key == 'l' then
rememberVisible()
movePlayer(directions.right)
generateVisibilityMap()
elseif key == 'u' then
rememberVisible()
movePlayer(directions.upleft)
generateVisibilityMap()
elseif key == 'm' then
rememberVisible()
movePlayer(directions.downleft)
generateVisibilityMap()
elseif key == '.' then
rememberVisible()
movePlayer(directions.downright)
generateVisibilityMap()
elseif key == 'o' then
rememberVisible()
movePlayer(directions.upright)
generateVisibilityMap()
elseif key == 'q' then
love.event.quit()
else
@ -328,17 +530,30 @@ function love.draw()
local y_scale = love.graphics.getHeight() / cavern.height
-- 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
for tile_y, tile in ipairs(list) do
for tile_y, visible in ipairs(list) do
local y = (tile_y - 1) * y_scale
if tile == tiletypes.empty then
love.graphics.setColor(0, 0, 0)
elseif tile == tiletypes.wall then
love.graphics.setColor(1, 1, 1)
if visible then
tile = cavern[tile_x][tile_y]
if tile == tiletypes.empty then
love.graphics.setColor(0, 0, 0)
elseif tile == tiletypes.wall then
love.graphics.setColor(1, 1, 1)
else
love.graphics.setColor(1, 0.5, 0.5)
end
else
love.graphics.setColor(1, 0.5, 0.5)
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)