Skip to content

Commit

Permalink
add basic death screen
Browse files Browse the repository at this point in the history
  • Loading branch information
Bauumm committed Sep 3, 2023
1 parent fb5693c commit 07e671e
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 25 deletions.
51 changes: 41 additions & 10 deletions game_handler/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ local games = {
[20] = require("compat.game20"),
[21] = require("compat.game21"),
}
local last_pack, last_level, last_level_settings, last_version
local current_game
local current_game_version
local first_play = true
Expand Down Expand Up @@ -47,13 +48,15 @@ function game_handler.set_version(version)
error("Game with version '" .. version .. "' does not exist or is unsupported.")
end
current_game_version = version
last_version = version
end

---start a level and start recording a replay
---@param pack string
---@param level string
---@param level_settings table
function game_handler.record_start(pack, level, level_settings)
---@param is_retry boolean = false
function game_handler.record_start(pack, level, level_settings, is_retry)
current_game.death_callback = function()
if current_game.update_save_data ~= nil then
current_game.update_save_data()
Expand All @@ -66,8 +69,7 @@ function game_handler.record_start(pack, level, level_settings)
end
current_game.persistent_data = game_handler.profile.get_data(pack)

-- TODO: false when retrying
first_play = true
first_play = not is_retry

input.replay = Replay:new()
input.replay:set_game_data(
Expand All @@ -79,11 +81,21 @@ function game_handler.record_start(pack, level, level_settings)
level,
level_settings
)
current_game.first_play = first_play
input.record_start()
current_game.start(pack, level, level_settings)
start_time = love.timer.getTime()
real_start_time = start_time
current_game.update(1 / current_game.tickrate)
last_pack = pack
last_level = level
last_level_settings = level_settings
end

---retry the level that was last started with record_start
function game_handler.retry()
game_handler.set_version(last_version)
game_handler.record_start(last_pack, last_level, last_level_settings, true)
end

---read a replay file and run the game with its inputs and seeds
Expand Down Expand Up @@ -131,6 +143,12 @@ function game_handler.stop()
current_game.stop()
end

---check if the game is replaying a replay
---@return boolean
function game_handler.is_replaying()
return input.is_replaying()
end

---process an event (mainly used for aspect ratio resizing)
---@param name string
---@param ... unknown
Expand Down Expand Up @@ -161,6 +179,25 @@ function game_handler.process_event(name, ...)
end
end

---get the dimensions of the game canvas (returns 0, 0 if it was not created yet)
---@return integer
---@return integer
function game_handler.get_game_dimensions()
if screen then
return screen:getDimensions()
else
return 0, 0
end
end

---get the position of the game canvas on the screen
---@return number
---@return number
function game_handler.get_game_position()
local width, height = love.graphics.getDimensions()
return (width - width * scale[1]) / 2, (height - height * scale[2]) / 2
end

---save the score and replay of the current attempt (gets called automatically on death)
function game_handler.save_score()
local elapsed_time = love.timer.getTime() - real_start_time
Expand Down Expand Up @@ -193,13 +230,6 @@ function game_handler.update(ensure_tickrate)
game_handler.onupdate()
end
end
--for "testing" purposes only (i just wante to play the game
if current_game.is_dead() then
current_game.stop()
local ui = require("ui")
ui.open_screen("levelselect")
--note: when reloading this room after the game, the score isnt in the menu until you reselect. this isnt a bug because there will be a proper death screen with retrying stuff in the future.
end
end
end

Expand All @@ -223,6 +253,7 @@ function game_handler.draw(frametime)
-- the color of the canvas' contents will look wrong if color isn't white
love.graphics.setColor(1, 1, 1, 1)
love.graphics.draw(screen)
love.graphics.origin()
end
end

Expand Down
4 changes: 4 additions & 0 deletions game_handler/input.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ function input.replay_start()
input.is_done_replaying = false
end

function input.is_replaying()
return replaying
end

---save the next seed when recording or get the next seed when replaying
---@param seed number
---@return number?
Expand Down
5 changes: 0 additions & 5 deletions ui/elements/dropdown.lua
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,6 @@ function dropdown:new(selections, options)
end
end
end
local quad_scale = obj.set_scale
obj.set_scale = function(elem, scale)
quad_scale(elem, scale)
elem.selection_quad:set_scale(scale)
end
local quad_layout = obj.calculate_layout
obj.calculate_layout = function(elem, available_area)
local w, h = quad_layout(elem, available_area)
Expand Down
22 changes: 17 additions & 5 deletions ui/init.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local signal = require("ui.anim.signal")
local overlays = require("ui.overlays")
local flex = require("ui.layout.flex")
local game_handler = require("game_handler")
local ui = {}
local screens = {
test = require("ui.screens.test"),
Expand All @@ -22,11 +23,16 @@ function ui.set_scale(scale)
end

local function calculate_layout(width, height)
local game_width, game_height, x, y
if game_handler.is_running() then
game_width, game_height = game_handler.get_game_dimensions()
x, y = game_handler.get_game_position()
end
local screen_area = {
x = 0,
y = 0,
width = width or love.graphics.getWidth(),
height = height or love.graphics.getHeight(),
x = x or 0,
y = y or 0,
width = width or game_width or love.graphics.getWidth(),
height = height or game_height or love.graphics.getHeight(),
}
local res_width, res_height = current_screen:calculate_layout(screen_area)
-- as long as the resulting layout is smaller than the window, up gui scale (until user setting is reached)
Expand Down Expand Up @@ -59,15 +65,21 @@ function ui.open_screen(name)
end
end

function ui.get_screen()
return current_screen
end

---process a window event
---@param name string
---@param ... unknown
function ui.process_event(name, ...)
local stop_propagation = overlays.process_event(name, ...)
if current_screen then
if name == "resize" then
calculate_layout(...)
end
end
local stop_propagation = overlays.process_event(name, ...)
if current_screen then
if not stop_propagation then
stop_propagation = current_screen:process_event(name, ...)
end
Expand Down
13 changes: 9 additions & 4 deletions ui/keyboard_navigation.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ local function get_first_element(element)
return element
elseif element.elements then
if element.last_selection then
return element.last_selection
local last_selected_elem = get_first_element(element.last_selection)
if last_selected_elem then
return last_selected_elem
end
end
for i = 1, #element.elements do
local first_elem = get_first_element(element.elements[i])
Expand All @@ -32,9 +35,11 @@ function keyboard_navigation.set_screen(screen)
current_screen.last_selected_element = selected_element
end
current_screen = screen
keyboard_navigation.select_element(nil, false)
if current_screen.last_selected_element then
keyboard_navigation.select_element(current_screen.last_selected_element, false)
if current_screen then
keyboard_navigation.select_element(nil, false)
if current_screen.last_selected_element then
keyboard_navigation.select_element(current_screen.last_selected_element, false)
end
end
end

Expand Down
10 changes: 9 additions & 1 deletion ui/overlays/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ function overlay_module.add_overlay(element)
table.remove(free_overlay_indices, 1)
end
overlays[index] = element
-- require here to avoid circular import (now require just returns the cached table)
local ui = require("ui")
element:set_scale(ui.get_screen().scale)
return index
end

Expand All @@ -35,6 +38,11 @@ end
function overlay_module.process_event(name, ...)
for i = 1, #overlays do
if overlays[i] then
if name == "resize" then
-- require here to avoid circular import (now require just returns the cached table)
local ui = require("ui")
overlays[i]:set_scale(ui.get_screen().scale)
end
if overlays[i]:process_event(name, ...) then
return true
end
Expand All @@ -56,7 +64,7 @@ end
---@param dt number
function overlay_module.update(dt)
for i = 1, #overlays do
if overlays[i] then
if overlays[i] and overlays[i].update then
overlays[i]:update(dt)
end
end
Expand Down
44 changes: 44 additions & 0 deletions ui/screens/game.lua
Original file line number Diff line number Diff line change
@@ -1,13 +1,47 @@
local label = require("ui.elements.label")
local quad = require("ui.elements.quad")
local game_handler = require("game_handler")
local get_death_overlay = require("ui.overlays.death")
local keyboard_navigation = require("ui.keyboard_navigation")
local overlays = require("ui.overlays")

local timer = quad:new({
child_element = label:new("", { font_size = 64 }),
style = { padding = 0, border_thickness = 0 },
vertex_offsets = { 0, 0, 40, 0, 0, 0, 0, 0 },
})

local death_overlay_index

local function back_to_menu()
if death_overlay_index then
keyboard_navigation.set_screen()
overlays.remove_overlay(death_overlay_index)
death_overlay_index = nil
end
game_handler.stop()
local ui = require("ui")
ui.open_screen("levelselect")
end

local function retry()
if death_overlay_index then
keyboard_navigation.set_screen()
overlays.remove_overlay(death_overlay_index)
death_overlay_index = nil
end
game_handler.retry()
end

local death_overlay = get_death_overlay(back_to_menu, retry)

-- monkey patch layout calculation to add overlay (TODO: make this cleaner)
local old_calculate_layout = timer.calculate_layout
timer.calculate_layout = function(self, available_area)
death_overlay:calculate_layout(available_area)
return old_calculate_layout(self, available_area)
end

game_handler.onupdate = function()
local score = game_handler.get_score()
score = math.floor(score * 1000) / 1000
Expand All @@ -26,6 +60,16 @@ game_handler.onupdate = function()
end
timer.element.raw_text = score_str
timer:calculate_layout()
-- show death screen when dead
if game_handler.is_dead() then
if game_handler.is_replaying() then
-- TODO: show appropriate ui when replay ends (retry/back buttons would be wrong here)
back_to_menu()
elseif keyboard_navigation.get_screen() ~= death_overlay then
death_overlay_index = overlays.add_overlay(death_overlay)
keyboard_navigation.set_screen(death_overlay)
end
end
end

return timer

0 comments on commit 07e671e

Please sign in to comment.