diff --git a/.luacheckrc b/.luacheckrc index 1d94ea5..9264fa8 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -22,8 +22,9 @@ globals = { "Meter", "Minigame", "Window", - "SplashWindow", - "IntroWindow", + "TTGIntroWindow", + "BriefIntroWindow", + "TitleIntroWindow", "MenuWindow", "GameWindow", "PopupWindow", diff --git a/impostor.inc b/impostor.inc index 24e6e84..3818fb7 100644 --- a/impostor.inc +++ b/impostor.inc @@ -46,8 +46,9 @@ screen/screen.work.lua window/window.manager.lua window/window.register.lua window/window.end.lua -window/window.splash.lua -window/window.intro.lua +window/window.intro.title.lua +window/window.intro.ttg.lua +window/window.intro.brief.lua window/window.menu.lua window/window.configuration.lua window/window.audiotest.lua diff --git a/inc/init/init.config.lua b/inc/init/init.config.lua index 9bf0fd0..626cd7b 100644 --- a/inc/init/init.config.lua +++ b/inc/init/init.config.lua @@ -20,7 +20,6 @@ function Config.initial_data() meter_bg = 1 }, timing = { - splash_duration = 120, minigame_win_duration = 180 } } @@ -37,21 +36,19 @@ end local CONFIG_SAVE_BANK = 7 local CONFIG_MAGIC_VALUE_ADDRESS = 2 -local CONFIG_SPLASH_DURATION_ADDRESS = 3 local CONFIG_MAGIC_VALUE = 0xDE --- Saves the current configuration. --- @within Config function Config.save() mset(CONFIG_MAGIC_VALUE, CONFIG_MAGIC_VALUE_ADDRESS, CONFIG_SAVE_BANK) - mset(Config.timing.splash_duration, CONFIG_SPLASH_DURATION_ADDRESS, CONFIG_SAVE_BANK) end --- Loads saved configuration. --- @within Config function Config.load() if mget(CONFIG_MAGIC_VALUE_ADDRESS, CONFIG_SAVE_BANK) == CONFIG_MAGIC_VALUE then - Config.timing.splash_duration = mget(CONFIG_SPLASH_DURATION_ADDRESS, CONFIG_SAVE_BANK) + return else Config.reset() end diff --git a/inc/init/init.context.lua b/inc/init/init.context.lua index 5f41a31..6b35e6e 100644 --- a/inc/init/init.context.lua +++ b/inc/init/init.context.lua @@ -11,7 +11,6 @@ Context = {} --- @return result table Initial context data or nil.
--- Fields:
--- * current_menu_item (number) Index of the currently selected menu item.
---- * splash_timer (number) Remaining frames for the splash screen timer.
--- * popup (table) Popup window state. Contains: `show` (boolean) whether popup is visible, `content` (table) array of strings to display.
--- * game_in_progress (boolean) Whether a game is currently active.
--- * minigame_ddr (table) DDR minigame state (see Minigame.get_default_ddr).
@@ -24,7 +23,6 @@ Context = {} function Context.initial_data() return { current_menu_item = 1, - splash_timer = Config.timing.splash_duration, popup = { show = false, content = {} diff --git a/inc/system/system.main.lua b/inc/system/system.main.lua index 7522b1e..8407975 100644 --- a/inc/system/system.main.lua +++ b/inc/system/system.main.lua @@ -5,11 +5,12 @@ local initialized_game = false --- @within Main --- @return boolean initialized_game True if game has been initialized, false otherwise. local function init_game() - if initialized_game then return end + if initialized_game then return false end Context.reset() - Window.set_current("splash") -- Set initial window using new manager + Window.set_current("intro_title") -- Set initial window using new manager MenuWindow.refresh_menu_items() initialized_game = true + return true end --- Main game loop (TIC-80 callback). @@ -24,9 +25,9 @@ function TIC() Meter.update() Timer.update() Trigger.update() + Glitch.draw() if Context.game_in_progress then Meter.draw() Timer.draw() - Glitch.draw() end end diff --git a/inc/window/window.intro.brief.lua b/inc/window/window.intro.brief.lua new file mode 100644 index 0000000..f1863a1 --- /dev/null +++ b/inc/window/window.intro.brief.lua @@ -0,0 +1,37 @@ +--- @section BriefIntroWindow +BriefIntroWindow.y = Config.screen.height +BriefIntroWindow.speed = 0.5 +BriefIntroWindow.text = [[ +Norman Reds’ everyday life +seems ordinary: work, +meetings, coffee, and +endless notifications. +But beneath him, or around +him — something is +constantly building, and +it soon becomes clear +that there is more going +on than meets the eye. +]] + +--- Draws the brief intro window. +--- @within BriefIntroWindow +function BriefIntroWindow.draw() + local x = (Config.screen.width - 132) / 2 + Print.text(BriefIntroWindow.text, x, BriefIntroWindow.y, Config.colors.light_blue) +end + +--- Updates the brief intro window logic. +--- @within BriefIntroWindow +function BriefIntroWindow.update() + BriefIntroWindow.y = BriefIntroWindow.y - BriefIntroWindow.speed + + local lines = 1 + for _ in string.gmatch(BriefIntroWindow.text, "\n") do + lines = lines + 1 + end + + if BriefIntroWindow.y < -lines * 8 or Input.select() or Input.menu_confirm() then + Window.set_current("menu") + end +end diff --git a/inc/window/window.intro.lua b/inc/window/window.intro.lua deleted file mode 100644 index 0364eb8..0000000 --- a/inc/window/window.intro.lua +++ /dev/null @@ -1,41 +0,0 @@ ---- @section IntroWindow -IntroWindow.y = Config.screen.height -IntroWindow.speed = 0.5 -IntroWindow.text = [[ -Norman Reds’ everyday life -seems ordinary: work, -meetings, coffee, and -endless notifications. -But beneath him, or around -him — something is -constantly building, and -it soon becomes clear -that there is more going -on than meets the eye. -]] - ---- Draws the intro window. ---- @within IntroWindow -function IntroWindow.draw() - local x = (Config.screen.width - 132) / 2 - Print.text(IntroWindow.text, x, IntroWindow.y, Config.colors.light_blue) -end - ---- Updates the intro window logic. ---- @within IntroWindow -function IntroWindow.update() - IntroWindow.y = IntroWindow.y - IntroWindow.speed - - local lines = 1 - for _ in string.gmatch(IntroWindow.text, "\n") do - lines = lines + 1 - end - - if IntroWindow.y < -lines * 8 then - Window.set_current("menu") - end - - if Input.menu_confirm() then - Window.set_current("menu") - end -end diff --git a/inc/window/window.intro.title.lua b/inc/window/window.intro.title.lua new file mode 100644 index 0000000..9d007e8 --- /dev/null +++ b/inc/window/window.intro.title.lua @@ -0,0 +1,78 @@ +--- @section TitleIntroWindow +TitleIntroWindow.timer = 180 -- 3 seconds at 60fps +TitleIntroWindow.text = [[ +## ### ### ### ### ### ### ### ## # # +# # # # # # # # # # # # # # +# # ### ### # # # # # ### # # # +# # # # # # # # # # # # # +## ### # ### # # ### # ### ## # + + # # ### ### ## # # + ## # # # # # # ## # + # ## # # # #### # ## + # # # # # # # # # + # # ### # # # # # + +### ### ### ### ### ### ### ### + # # # # # # # # # # # ### + # # # ### ### ### # # # # # + # # # # # # # # # # # +### # # # # ### # ### # # +]] + +--- Draws the title intro window. +--- @within TitleIntroWindow +function TitleIntroWindow.draw() + local lines = {} + local max_len = 0 + -- Get all lines and find max length + for line in (TitleIntroWindow.text .. "\n"):gmatch("(.-)\n") do + table.insert(lines, line) + if #line > max_len then max_len = #line end + end + + -- Clean up empty lines from the start/end + if #lines > 0 and lines[1] == "" then table.remove(lines, 1) end + if #lines > 0 and lines[#lines] == "" then table.remove(lines, #lines) end + + local char_w = 4 + local char_h = 5 + local line_gap = 0 + local word_gap = 6 + + local total_h = 0 + for _, line in ipairs(lines) do + if line:find("#") then + total_h = total_h + char_h + line_gap + else + total_h = total_h + word_gap + end + end + total_h = total_h - line_gap + + local current_y = (Config.screen.height - total_h) / 2 + local x_offset = (Config.screen.width - (max_len * char_w)) / 2 + + for _, line in ipairs(lines) do + if line:find("#") then + for j = 1, #line do + local char = line:sub(j, j) + if char == "#" then + rect(x_offset + (j - 1) * char_w, current_y, char_w - 1, char_h - 1, Config.colors.light_blue) + end + end + current_y = current_y + char_h + line_gap + else + current_y = current_y + word_gap + end + end +end + +--- Updates the title intro window logic. +--- @within TitleIntroWindow +function TitleIntroWindow.update() + TitleIntroWindow.timer = TitleIntroWindow.timer - 1 + if TitleIntroWindow.timer <= 0 or Input.select() or Input.menu_confirm() then + Window.set_current("intro_ttg") + end +end diff --git a/inc/window/window.intro.ttg.lua b/inc/window/window.intro.ttg.lua new file mode 100644 index 0000000..a58aa21 --- /dev/null +++ b/inc/window/window.intro.ttg.lua @@ -0,0 +1,56 @@ +--- @section TTGIntroWindow +TTGIntroWindow.timer = 180 +TTGIntroWindow.glitch_started = false +TTGIntroWindow.text = [[ +###### ###### ###### + ## ## # + ## ## # #### + ## ## # # + ## ## ###### +]] + +--- Draws the TTG intro window. +--- @within TTGIntroWindow +function TTGIntroWindow.draw() + if not TTGIntroWindow.glitch_started then + Glitch.show() + TTGIntroWindow.glitch_started = true + end + + local lines = {} + local max_len = 0 + for line in TTGIntroWindow.text:gmatch("[^\r\n]+") do + table.insert(lines, line) + if #line > max_len then max_len = #line end + end + + local char_w = 6 + local char_h = 7 + local y = (Config.screen.height - (#lines * char_h + 12)) / 2 + local x_offset = (Config.screen.width - (max_len * char_w)) / 2 + + for i, line in ipairs(lines) do + for j = 1, #line do + local char = line:sub(j, j) + if char == "#" then + rect(x_offset + (j - 1) * char_w, y + (i - 1) * char_h, char_w - 1, char_h - 1, Config.colors.light_blue) + end + end + end + + Print.text_center("Teletype Games", Config.screen.width / 2, y + #lines * char_h + 4, Config.colors.light_blue) +end +--- Updates the TTG intro window logic. +--- @within TTGIntroWindow +function TTGIntroWindow.update() + if not TTGIntroWindow.glitch_started then + Glitch.show() + TTGIntroWindow.glitch_started = true + end + + TTGIntroWindow.timer = TTGIntroWindow.timer - 1 + if TTGIntroWindow.timer <= 0 or Input.select() or Input.menu_confirm() then + Glitch.hide() + Window.set_current("intro_brief") + end +end diff --git a/inc/window/window.manager.lua b/inc/window/window.manager.lua index 84e6af6..316af6b 100644 --- a/inc/window/window.manager.lua +++ b/inc/window/window.manager.lua @@ -4,7 +4,7 @@ local _windows = {} --- Registers a window table. --- @within Window --- @param id string The ID of the window (e.g., "splash", "menu").
---- @param window_table table The actual window module table (e.g., SplashWindow).
+--- @param window_table table The actual window module table (e.g., GameWindow).
function Window.register(id, window_table) _windows[id] = window_table end diff --git a/inc/window/window.register.lua b/inc/window/window.register.lua index 46ad6ff..7746845 100644 --- a/inc/window/window.register.lua +++ b/inc/window/window.register.lua @@ -1,8 +1,11 @@ -SplashWindow = {} -Window.register("splash", SplashWindow) +TitleIntroWindow = {} +Window.register("intro_title", TitleIntroWindow) -IntroWindow = {} -Window.register("intro", IntroWindow) +TTGIntroWindow = {} +Window.register("intro_ttg", TTGIntroWindow) + +BriefIntroWindow = {} +Window.register("intro_brief", BriefIntroWindow) MenuWindow = {} Window.register("menu", MenuWindow) diff --git a/inc/window/window.splash.lua b/inc/window/window.splash.lua deleted file mode 100644 index 8b4795b..0000000 --- a/inc/window/window.splash.lua +++ /dev/null @@ -1,16 +0,0 @@ ---- Draws the splash window. ---- @within SplashWindow -function SplashWindow.draw() - local txt = "Definitely not an Impostor" - local y = (Config.screen.height - 6) / 2 - Print.text_center(txt, Config.screen.width / 2, y, Config.colors.white) -end - ---- Updates the splash window logic. ---- @within SplashWindow -function SplashWindow.update() - Context.splash_timer = Context.splash_timer - 1 - if Context.splash_timer <= 0 or Input.menu_confirm() then - Window.set_current("intro") - end -end