From 98030a09a1921ed2bdbc6cf6b6982aadff171bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Sat, 29 Jun 2019 23:18:18 +0300 Subject: [PATCH] Add slimes --- bundle/main.lua | 127 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 112 insertions(+), 15 deletions(-) diff --git a/bundle/main.lua b/bundle/main.lua index 643f24f..6c516f5 100644 --- a/bundle/main.lua +++ b/bundle/main.lua @@ -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 -- ⌜^ -- ⌜ -- 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