Add slimes

This commit is contained in:
Juhani Krekelä 2019-06-29 23:18:18 +03:00
parent 9e136ab4c9
commit 98030a09a1
1 changed files with 112 additions and 15 deletions

View File

@ -1,7 +1,7 @@
local debug = false
local cavern = {}
local tiletypes = {unknown = 0, empty = 1, wall = 2, orb = 3}
local tiletypes = {unknown = 0, empty = 1, wall = 2, orb = 3, slime = 4}
local visibility_map = {}
local remembered_cavern = {}
@ -14,6 +14,8 @@ local player_x = nil
local player_y = nil
local player_direction = nil
local slimes = {}
local last_key_pressed = nil
local last_direction_moved = nil
local move_repeat_counter = nil
@ -168,11 +170,24 @@ function spawnOrb()
repeat
orb_x = math.random(2, cavern.width - 1)
orb_y = math.random(2, cavern.height - 1)
until passable(orb_x, orb_y)
until cavern[orb_x][orb_y] == tiletypes.empty
cavern[orb_x][orb_y] = tiletypes.orb
end
function spawnSlimes()
-- Try spawning 20 slimes, but if they don't hit any location then don't care
for i = 1, 20 do
local x = math.random(2, cavern.width - 1)
local y = math.random(2, cavern.height - 1)
if cavern[x][y] == tiletypes.empty then
cavern[x][y] = tiletypes.slime
table.insert(slimes, {x = x, y = y})
end
end
end
-- ------------------------------------------------------------------
-- Visibility
-- ------------------------------------------------------------------
@ -291,22 +306,22 @@ function stepVisibilityMapGeneration(queue)
for i, item in ipairs(queue) do
if item.direction == directions.up then
visibility_map[item.x][item.y] = true
if passable(item.x, item.y) then
if seethrough(item.x, item.y) then
table.insert(new_queue, {x = item.x, y = item.y - 1, direction = directions.up})
end
elseif item.direction == directions.left then
visibility_map[item.x][item.y] = true
if passable(item.x, item.y) then
if seethrough(item.x, item.y) then
table.insert(new_queue, {x = item.x - 1, y = item.y, direction = directions.left})
end
elseif item.direction == directions.down then
visibility_map[item.x][item.y] = true
if passable(item.x, item.y) then
if seethrough(item.x, item.y) then
table.insert(new_queue, {x = item.x, y = item.y + 1, direction = directions.down})
end
elseif item.direction == directions.right then
visibility_map[item.x][item.y] = true
if passable(item.x, item.y) then
if seethrough(item.x, item.y) then
table.insert(new_queue, {x = item.x + 1, y = item.y, direction = directions.right})
end
elseif item.direction == directions.upleft then
@ -322,9 +337,9 @@ function stepVisibilityMapGeneration(queue)
-- it is not. We can therefore check whether the movement is valid
-- by testing if either the cell to our right or below us (the
-- directions opposite to the ones in an up.left movement) is empty
if passable(item.x + 1, item.y) or passable(item.x, item.y + 1) then
if seethrough(item.x + 1, item.y) or seethrough(item.x, item.y + 1) then
visibility_map[item.x][item.y] = true
if passable(item.x, item.y) then
if seethrough(item.x, item.y) then
-- ⌜^
-- ⌜ <x
table.insert(new_queue, {x = item.x - 1, y = item.y - 1, direction = directions.upleft})
@ -334,9 +349,9 @@ function stepVisibilityMapGeneration(queue)
end
elseif item.direction == directions.downleft then
-- See under item.direction == directions.upleft
if passable(item.x + 1, item.y) or passable(item.x, item.y - 1) then
if seethrough(item.x + 1, item.y) or seethrough(item.x, item.y - 1) then
visibility_map[item.x][item.y] = true
if passable(item.x, item.y) then
if seethrough(item.x, item.y) then
-- ⌞ <x
-- ⌞v
table.insert(new_queue, {x = item.x - 1, y = item.y, direction = directions.left})
@ -346,9 +361,9 @@ function stepVisibilityMapGeneration(queue)
end
elseif item.direction == directions.downright then
-- See under item.direction == directions.upleft
if passable(item.x - 1, item.y) or passable(item.x, item.y - 1) then
if seethrough(item.x - 1, item.y) or seethrough(item.x, item.y - 1) then
visibility_map[item.x][item.y] = true
if passable(item.x, item.y) then
if seethrough(item.x, item.y) then
-- ⌟ x>
-- v⌟
table.insert(new_queue, {x = item.x + 1, y = item.y, direction = directions.right})
@ -358,9 +373,9 @@ function stepVisibilityMapGeneration(queue)
end
elseif item.direction == directions.upright then
-- See under item.direction == directions.upleft
if passable(item.x - 1, item.y) or passable(item.x, item.y + 1) then
if seethrough(item.x - 1, item.y) or seethrough(item.x, item.y + 1) then
visibility_map[item.x][item.y] = true
if passable(item.x, item.y) then
if seethrough(item.x, item.y) then
-- ^⌝
-- ⌝ x>
table.insert(new_queue, {x = item.x, y = item.y - 1, direction = directions.up})
@ -404,11 +419,20 @@ function passable(x, y)
return cavern[x][y] == tiletypes.empty or cavern[x][y] == tiletypes.orb
end
function seethrough(x, y)
return cavern[x][y] == tiletypes.empty or cavern[x][y] == tiletypes.orb or cavern[x][y] == tiletypes.slime
end
function collidedPlayerOrb()
local body_x, body_y = getBodyLocation()
return cavern[player_x][player_y] == tiletypes.orb or cavern[body_x][body_y] == tiletypes.orb
end
function collidedPlayerSlime()
local body_x, body_y = getBodyLocation()
return cavern[player_x][player_y] == tiletypes.slime or cavern[body_x][body_y] == tiletypes.slime
end
-- ------------------------------------------------------------------
-- Player helper functions
-- ------------------------------------------------------------------
@ -567,6 +591,7 @@ function newGame()
spawnPlayer()
spawnOrb()
spawnSlimes()
generateVisibilityMap()
initializeRememberedCavern()
@ -576,6 +601,56 @@ function newGame()
end
end
function moveSlimes()
for i, slime in ipairs(slimes) do
local dx = 0
local dy = 0
local to_player_dx = player_x - slime.x
local to_player_dy = player_y - slime.y
if math.abs(to_player_dx) + math.abs(to_player_dy) <= 7 then
-- If at max 7 moves away from player, book for it
if math.abs(to_player_dx) > math.abs(to_player_dy) then
-- Needs to move more in the horizontal direction → move horizontally
if to_player_dx < 0 then
dx = -1
else
dx = 1
end
else
-- Otherwise move vertically
if to_player_dy < 0 then
dy = -1
else
dy = 1
end
end
else
local movement = math.random(0, 3)
if movement == 0 then
-- Up
dy = -1
elseif movement == 1 then
-- Left
dx = -1
elseif movement == 2 then
-- Down
dy = 1
elseif movement == 3 then
-- Right
dx = 1
end
end
-- We test for empty instead of using passable(), since we are overwriting a tile
if cavern[slime.x + dx][slime.y + dy] == tiletypes.empty then
cavern[slime.x + dx][slime.y + dy] = tiletypes.slime
cavern[slime.x][slime.y] = tiletypes.empty
slimes[i] = {x = slime.x + dx, y = slime.y + dy}
end
end
end
function step(direction)
if game_mode == gamemodes.normal then
if last_direction_moved == direction then
@ -587,12 +662,19 @@ function step(direction)
end
rememberVisible()
movePlayer(direction)
moveSlimes()
generateVisibilityMap()
if collidedPlayerOrb() then
game_mode = gamemodes.won
end
if collidedPlayerSlime() then
newGame()
end
end
end
@ -622,6 +704,10 @@ function drawCavern()
love.graphics.rectangle('fill', x, y, x_scale, y_scale)
love.graphics.setColor(0, 1, 0)
love.graphics.ellipse('fill', x + 0.5 * x_scale, y + 0.5 * y_scale, 0.7 * x_scale/2, 0.7 * y_scale/2)
elseif tile == tiletypes.slime then
love.graphics.setColor(0, 0, 1)
love.graphics.ellipse('fill', x + 0.5 * x_scale, y + 0.5 * y_scale, 0.8 * x_scale/2, 0.8 * y_scale/2)
love.graphics.rectangle('fill', x + 0.1 * x_scale , y + 0.5 * y_scale, 0.8 * x_scale, 0.8 * y_scale/2)
else
love.graphics.setColor(1, 0.5, 0.5)
love.graphics.rectangle('fill', x, y, x_scale, y_scale)
@ -640,11 +726,20 @@ function drawCavern()
love.graphics.rectangle('fill', x, y, x_scale, y_scale)
love.graphics.setColor(0.2, 0.7, 0.2)
love.graphics.ellipse('fill', x + 0.5 * x_scale, y + 0.5 * y_scale, 0.7 * x_scale/2, 0.7 * y_scale/2)
elseif tile == tiletypes.slime then
love.graphics.setColor(0.2, 0.2, 0.7)
love.graphics.ellipse('fill', x + 0.5 * x_scale, y + 0.5 * y_scale, 0.8 * x_scale/2, 0.8 * y_scale/2)
love.graphics.rectangle('fill', x + 0.1 * x_scale , y + 0.5 * y_scale, 0.8 * x_scale, 0.8 * y_scale/2)
else
love.graphics.setColor(0.7, 0.5, 0.5)
love.graphics.rectangle('fill', x, y, x_scale, y_scale)
end
end
if debug and tile_x == player_x and tile_y == player_y then
love.graphics.setColor(1, 1, 0)
love.graphics.rectangle('fill', x + 0.5 * x_scale, y + 0.5 * y_scale, x_scale/2, y_scale/2)
end
end
end
end
@ -781,7 +876,9 @@ end
function love.draw()
if game_mode == gamemodes.normal then
drawCavern()
drawPlayer()
if not debug then
drawPlayer()
end
elseif game_mode == gamemodes.won then
drawWin()
elseif game_mode == gamemodes.config then