diff --git a/inc/init/init.context.lua b/inc/init/init.context.lua index cdc133a..c476a09 100644 --- a/inc/init/init.context.lua +++ b/inc/init/init.context.lua @@ -46,7 +46,11 @@ on than meets the eye.]] minigame_button_mash = Minigames.get_default_button_mash(), minigame_rhythm = Minigames.get_default_rhythm(), 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 = {}, + --- The ID of the currently active situation. + -- Set by `Situation.apply()` and `nil` if no situation is active. current_situation = nil, } end diff --git a/inc/screen/screen.manager.lua b/inc/screen/screen.manager.lua index 42b50f3..3facdea 100644 --- a/inc/screen/screen.manager.lua +++ b/inc/screen/screen.manager.lua @@ -1,5 +1,13 @@ 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) if _screens[screen_data.id] then trace("Warning: Overwriting screen with id: " .. screen_data.id) @@ -7,9 +15,18 @@ function Screen.register(screen_data) if not screen_data.situations then screen_data.situations = {} 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 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) return _screens[screen_id] end diff --git a/inc/situation/situation.manager.lua b/inc/situation/situation.manager.lua index 88c6b2d..f561c97 100644 --- a/inc/situation/situation.manager.lua +++ b/inc/situation/situation.manager.lua @@ -1,5 +1,12 @@ 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) if not situation or not situation.id then PopupWindow.show({"Error: Invalid situation object registered (missing id)!"}) @@ -8,16 +15,28 @@ function Situation.register(situation) if not situation.handle then situation.handle = function() end end + if not situation.update then + situation.update = function() end + end if _situations[situation.id] then trace("Warning: Overwriting situation with id: " .. situation.id) end _situations[situation.id] = situation 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) return _situations[id] 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) local situation = Situation.get(id) if not situation then @@ -34,4 +53,3 @@ function Situation.apply(id) Context.current_situation = id situation.handle() end - diff --git a/inc/sprite/sprite.manager.lua b/inc/sprite/sprite.manager.lua index 60d5a97..030ca5b 100644 --- a/inc/sprite/sprite.manager.lua +++ b/inc/sprite/sprite.manager.lua @@ -1,5 +1,15 @@ 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) if not sprite_data or not sprite_data.id then trace("Error: Invalid sprite object registered (missing id)!") @@ -11,6 +21,17 @@ function Sprite.register(sprite_data) _sprites[sprite_data.id] = sprite_data 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) -- Ensure the sprite exists before attempting to show it if not _sprites[id] then @@ -30,10 +51,16 @@ function Sprite.show(id, x, y, colorkey, scale, flip_x, flip_y, rot) } 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) Context.sprites[id] = nil 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() for id, params in pairs(Context.sprites) do local sprite_data = _sprites[id] diff --git a/inc/sprite/sprite.norman.lua b/inc/sprite/sprite.norman.lua index 67cfbcb..d56eaaf 100644 --- a/inc/sprite/sprite.norman.lua +++ b/inc/sprite/sprite.norman.lua @@ -1,17 +1,17 @@ Sprite.register({ id = "norman", sprites = { - -- Body + -- Body (sprite index 0) { s = 0, x_offset = 0, y_offset = 0 }, - -- Head + -- Head (sprite index 1) { s = 1, x_offset = 0, y_offset = -8 }, - -- Left Arm + -- Left Arm (sprite index 2) { 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 - -- Left Leg + -- Left Leg (sprite index 4) { 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 } -}) +}) \ No newline at end of file diff --git a/inc/window/window.game.lua b/inc/window/window.game.lua index 85b9375..3ab2a52 100644 --- a/inc/window/window.game.lua +++ b/inc/window/window.game.lua @@ -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() local screen = Context.screens[Context.current_screen] Map.draw(screen.background) @@ -17,7 +20,13 @@ function GameWindow.draw() Sprite.draw() 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() + local previous_screen_index = Context.current_screen + if Input.menu_back() then Context.active_window = WINDOW_MENU MenuWindow.refresh_menu_items() @@ -37,6 +46,19 @@ function GameWindow.update() Context.selected_decision_index = 1 end 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 local available_decisions = {} for _, decision_id in ipairs(screen.decisions) do @@ -64,6 +86,10 @@ function GameWindow.update() 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) Context.active_window = new_state - end \ No newline at end of file +end