docs
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
2026-02-21 23:53:36 +01:00
parent 3b137fd48e
commit 787b6656b0
6 changed files with 101 additions and 9 deletions

View File

@@ -46,7 +46,11 @@ on than meets the eye.]]
minigame_button_mash = Minigames.get_default_button_mash(), minigame_button_mash = Minigames.get_default_button_mash(),
minigame_rhythm = Minigames.get_default_rhythm(), minigame_rhythm = Minigames.get_default_rhythm(),
meters = Meters.get_initial(), meters = Meters.get_initial(),
--- Table storing currently active sprites to be drawn.
-- Each entry is a table with `id`, `x`, `y`, and other drawing parameters.
sprites = {}, sprites = {},
--- The ID of the currently active situation.
-- Set by `Situation.apply()` and `nil` if no situation is active.
current_situation = nil, current_situation = nil,
} }
end end

View File

@@ -1,5 +1,13 @@
local _screens = {} local _screens = {}
--- Registers a new screen definition with the Screen manager.
-- Overwrites existing screen if an ID conflict occurs.
-- @param screen_data table A table containing the screen definition.
-- Must include an `id` field (string).
-- Optional fields:
-- - `situations` (table): A table of situation IDs allowed on this screen. Defaults to an empty table.
-- - `init` (function): Function to execute once when the screen becomes active. Defaults to an empty function.
-- - `update` (function): Function to execute each frame while the screen is active. Defaults to an empty function.
function Screen.register(screen_data) function Screen.register(screen_data)
if _screens[screen_data.id] then if _screens[screen_data.id] then
trace("Warning: Overwriting screen with id: " .. screen_data.id) trace("Warning: Overwriting screen with id: " .. screen_data.id)
@@ -7,9 +15,18 @@ function Screen.register(screen_data)
if not screen_data.situations then if not screen_data.situations then
screen_data.situations = {} screen_data.situations = {}
end end
if not screen_data.init then
screen_data.init = function() end
end
if not screen_data.update then
screen_data.update = function() end
end
_screens[screen_data.id] = screen_data _screens[screen_data.id] = screen_data
end end
--- Retrieves a registered screen by its ID.
-- @param screen_id string The ID of the screen to retrieve.
-- @return table The screen table, or `nil` if not found.
function Screen.get_by_id(screen_id) function Screen.get_by_id(screen_id)
return _screens[screen_id] return _screens[screen_id]
end end

View File

@@ -1,5 +1,12 @@
local _situations = {} local _situations = {}
--- Registers a new situation with the Situation manager.
-- Overwrites existing situation if an ID conflict occurs.
-- @param situation table A table containing the situation definition.
-- Must include an `id` field (string).
-- Optional fields:
-- - `handle` (function): Function to execute when the situation is applied. Defaults to an empty function.
-- - `update` (function): Function to execute each frame while the situation is active. Defaults to an empty function.
function Situation.register(situation) function Situation.register(situation)
if not situation or not situation.id then if not situation or not situation.id then
PopupWindow.show({"Error: Invalid situation object registered (missing id)!"}) PopupWindow.show({"Error: Invalid situation object registered (missing id)!"})
@@ -8,16 +15,28 @@ function Situation.register(situation)
if not situation.handle then if not situation.handle then
situation.handle = function() end situation.handle = function() end
end end
if not situation.update then
situation.update = function() end
end
if _situations[situation.id] then if _situations[situation.id] then
trace("Warning: Overwriting situation with id: " .. situation.id) trace("Warning: Overwriting situation with id: " .. situation.id)
end end
_situations[situation.id] = situation _situations[situation.id] = situation
end end
--- Retrieves a registered situation by its ID.
-- @param id string The ID of the situation to retrieve.
-- @return table The situation table, or `nil` if not found.
function Situation.get(id) function Situation.get(id)
return _situations[id] return _situations[id]
end end
--- Applies a situation, making it the current active situation.
-- The situation's `handle` function is executed.
-- This function first checks if the situation is valid and if it's allowed
-- on the current screen (as defined in `Context.screens[Context.current_screen].situations`).
-- If successful, `Context.current_situation` is updated with the ID of the applied situation.
-- @param id string The ID of the situation to apply.
function Situation.apply(id) function Situation.apply(id)
local situation = Situation.get(id) local situation = Situation.get(id)
if not situation then if not situation then
@@ -34,4 +53,3 @@ function Situation.apply(id)
Context.current_situation = id Context.current_situation = id
situation.handle() situation.handle()
end end

View File

@@ -1,5 +1,15 @@
local _sprites = {} local _sprites = {}
--- Registers a new sprite or complex sprite definition with the Sprite manager.
-- Overwrites existing sprite if an ID conflict occurs.
-- @param sprite_data table A table containing the sprite definition.
-- Must include an `id` field (string) and either an `s` field (number, for simple sprites)
-- or a `sprites` field (table, for complex sprites).
-- For complex sprites, `sprites` is a table of sub-sprite definitions, each with:
-- - `s` (number): Sprite index.
-- - `x_offset` (number): X-offset relative to the parent sprite's position.
-- - `y_offset` (number): Y-offset relative to the parent sprite's position.
-- - Optional `colorkey`, `scale`, `flip_x`, `flip_y`, `rot` for individual sub-sprites.
function Sprite.register(sprite_data) function Sprite.register(sprite_data)
if not sprite_data or not sprite_data.id then if not sprite_data or not sprite_data.id then
trace("Error: Invalid sprite object registered (missing id)!") trace("Error: Invalid sprite object registered (missing id)!")
@@ -11,6 +21,17 @@ function Sprite.register(sprite_data)
_sprites[sprite_data.id] = sprite_data _sprites[sprite_data.id] = sprite_data
end end
--- Schedules a registered sprite to be drawn at a specific position with optional transformations.
-- The sprite's parameters are stored in `Context.sprites` for deferred rendering by `Sprite.draw()`.
-- If the sprite with the given `id` is already scheduled, its parameters will be updated.
-- @param id string The unique identifier of the sprite to show. Must be registered via `Sprite.register`.
-- @param x number The x-coordinate on the screen where the sprite will be drawn.
-- @param y number The y-coordinate on the screen where the sprite will be drawn.
-- @param[opt] colorkey number The color index to be treated as transparent (default: 0).
-- @param[opt] scale number The scaling factor for the sprite (default: 1).
-- @param[opt] flip_x number Set to 1 to flip the sprite horizontally (default: 0).
-- @param[opt] flip_y number Set to 1 to flip the sprite vertically (default: 0).
-- @param[opt] rot number The rotation of the sprite in degrees (default: 0).
function Sprite.show(id, x, y, colorkey, scale, flip_x, flip_y, rot) function Sprite.show(id, x, y, colorkey, scale, flip_x, flip_y, rot)
-- Ensure the sprite exists before attempting to show it -- Ensure the sprite exists before attempting to show it
if not _sprites[id] then if not _sprites[id] then
@@ -30,10 +51,16 @@ function Sprite.show(id, x, y, colorkey, scale, flip_x, flip_y, rot)
} }
end end
--- Hides a currently displayed sprite by removing it from the `Context.sprites` table.
-- The sprite will no longer be drawn in subsequent frames.
-- @param id string The unique identifier of the sprite to hide.
function Sprite.hide(id) function Sprite.hide(id)
Context.sprites[id] = nil Context.sprites[id] = nil
end end
--- Draws all sprites currently scheduled in `Context.sprites`.
-- This function retrieves the registered sprite definitions and applies the stored
-- position and transformation parameters. It handles both simple and complex sprites.
function Sprite.draw() function Sprite.draw()
for id, params in pairs(Context.sprites) do for id, params in pairs(Context.sprites) do
local sprite_data = _sprites[id] local sprite_data = _sprites[id]

View File

@@ -1,17 +1,17 @@
Sprite.register({ Sprite.register({
id = "norman", id = "norman",
sprites = { sprites = {
-- Body -- Body (sprite index 0)
{ s = 0, x_offset = 0, y_offset = 0 }, { s = 0, x_offset = 0, y_offset = 0 },
-- Head -- Head (sprite index 1)
{ s = 1, x_offset = 0, y_offset = -8 }, { s = 1, x_offset = 0, y_offset = -8 },
-- Left Arm -- Left Arm (sprite index 2)
{ s = 2, x_offset = -4, y_offset = 4 }, { s = 2, x_offset = -4, y_offset = 4 },
-- Right Arm -- Right Arm (sprite index 3, flipped)
{ s = 3, x_offset = 4, y_offset = 4, flip_x = 1 }, -- Flipped arm { s = 3, x_offset = 4, y_offset = 4, flip_x = 1 }, -- Flipped arm
-- Left Leg -- Left Leg (sprite index 4)
{ s = 4, x_offset = -2, y_offset = 8 }, { s = 4, x_offset = -2, y_offset = 8 },
-- Right Leg -- Right Leg (sprite index 5, flipped)
{ s = 5, x_offset = 2, y_offset = 8, flip_x = 1 } -- Flipped leg { s = 5, x_offset = 2, y_offset = 8, flip_x = 1 } -- Flipped leg
} }
}) })

View File

@@ -1,3 +1,6 @@
--- Draws the main game window content.
-- This includes the current screen's background, top bar, decisions, and all active sprites.
-- @function GameWindow.draw
function GameWindow.draw() function GameWindow.draw()
local screen = Context.screens[Context.current_screen] local screen = Context.screens[Context.current_screen]
Map.draw(screen.background) Map.draw(screen.background)
@@ -17,7 +20,13 @@ function GameWindow.draw()
Sprite.draw() Sprite.draw()
end end
--- Updates the logic for the main game window.
-- Handles input, navigates between screens, calls the current screen's and situation's update functions,
-- and processes player decisions.
-- @function GameWindow.update
function GameWindow.update() function GameWindow.update()
local previous_screen_index = Context.current_screen
if Input.menu_back() then if Input.menu_back() then
Context.active_window = WINDOW_MENU Context.active_window = WINDOW_MENU
MenuWindow.refresh_menu_items() MenuWindow.refresh_menu_items()
@@ -37,6 +46,19 @@ function GameWindow.update()
Context.selected_decision_index = 1 end Context.selected_decision_index = 1 end
local screen = Context.screens[Context.current_screen] local screen = Context.screens[Context.current_screen]
screen.update()
if previous_screen_index ~= Context.current_screen then
screen.init()
end
if Context.current_situation then
local current_situation_obj = Situation.get(Context.current_situation)
if current_situation_obj and current_situation_obj.update then
current_situation_obj.update()
end
end
if screen and screen.decisions and #screen.decisions > 0 then if screen and screen.decisions and #screen.decisions > 0 then
local available_decisions = {} local available_decisions = {}
for _, decision_id in ipairs(screen.decisions) do for _, decision_id in ipairs(screen.decisions) do
@@ -64,6 +86,10 @@ function GameWindow.update()
end end
end end
--- Sets the active window state for the game.
-- This function is typically called when transitioning between different game states (e.g., to a minigame).
-- @param new_state number The ID of the new active window (e.g., `WINDOW_MENU`, `WINDOW_GAME`).
-- @function GameWindow.set_state
function GameWindow.set_state(new_state) function GameWindow.set_state(new_state)
Context.active_window = new_state Context.active_window = new_state
end end