From ae97703bb411b62113e3b76e30e61dabccda1ce9 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Fri, 12 Jun 2026 00:10:06 -0700 Subject: [PATCH] added refresh when working with quiz folder, debug logs enabled in folder mode, added new zoom content --- build.lua | 2 +- gui | 2 +- main.lua | 5 +- menus/board.lua | 205 ++++++++++++++++++++++++++++++----- menus/title.lua | 2 +- templates/imageword.lua | 25 +---- templates/multiplechoice.lua | 1 + templates/one-image.lua | 25 +---- templates/whatis.lua | 21 +--- templates/whatsound.lua | 31 ++---- templates/whatvideo.lua | 24 +--- templates/zoom.lua | 37 +++---- version.txt | 2 +- 13 files changed, 225 insertions(+), 157 deletions(-) diff --git a/build.lua b/build.lua index a451794..fd32f8e 100644 --- a/build.lua +++ b/build.lua @@ -3,7 +3,7 @@ return { name = 'Jeopardy', -- name of the game for your executable developer = 'Ryan Ward', -- dev name used in metadata of the file output = 'bin', -- output location for your game, defaults to $SAVE_DIRECTORY - version = '1.0.2', -- 'version' of your game, used to name the folder in output + version = '1.0.4', -- 'version' of your game, used to name the folder in output love = '11.5', -- version of LÖVE to use, must match github releases ignore = {'bin', 'love', 'server_test', '.gitignore', '.gitmodules', 'build.lua', 'login_dialog.yaml', 'package.bat', 'README.md'}, -- folders/files to ignore in your project icon = 'assets/icon.png', -- 256x256px PNG icon for game, will be converted for you diff --git a/gui b/gui index c4cf5cb..e33a6f4 160000 --- a/gui +++ b/gui @@ -1 +1 @@ -Subproject commit c4cf5cbc9e5a570fc3611c795c169e4e2d02db1a +Subproject commit e33a6f4e146ea3bc61b1621fd1cdecf48c60e40b diff --git a/main.lua b/main.lua index 62617f7..ef211cd 100644 --- a/main.lua +++ b/main.lua @@ -16,7 +16,7 @@ local fileHandler, logCtrl = lovehandler.new("logs/jeopardy.log", { lovehandler.auto_flush_on_quit(logCtrl) log = logger.new("jeopardy", { - level = logger.LEVELS.DEBUG, + level = logger.LEVELS.INFO, handlers = { logger.handlers.ConsoleHandler({ colours = true }), fileHandler, @@ -36,6 +36,9 @@ color.indexColor("title_font","#b16d24") color.indexColor("question_bg","#363ac8") color.indexColor("tile_font","#ffffff") color.indexColor("header_font","#fef6eeda") +color.indexColor("correct", "#52b11b") +color.indexColor("skip", "#5d5d5d") +color.indexColor("wrong", "#bd2626") require("gui.addons") diff --git a/menus/board.lua b/menus/board.lua index a604528..733cec6 100644 --- a/menus/board.lua +++ b/menus/board.lua @@ -6,6 +6,8 @@ local fmt = require("utils/fmt") local timer = require("utils/utils") local multi, thread = require("multi"):init() local menu = require("gui.core.menus") +local transition = require("gui.core.transitions") +local logger = require("utils/logger") local timesup = love.audio.newSource("assets/sounds/timesup.mp3", "static") local double = love.audio.newSource("assets/sounds/double.mp3", "static") @@ -18,12 +20,17 @@ local activePlayer local playerList = {} local playerStaticList = {} local scoreboard = {} +local handler +local handler_conn = boardUpdater:newConnection() +local reference +local multiply + +local reset = boardUpdater:newConnection() + +local default_text = "Pick a Category" local boardLog = log:child("board") --- Function to resize fonts for all managed elements -boardLog:debug("Creating resize fonts handler") - local completed_questions = 0 local min_questions = 0 local dd_count = 0 @@ -31,6 +38,25 @@ local dd_enabled = false local applied_dd = false local board, question +local function cleanUp() + activePlayer = nil + handler_conn:Remove() + playerList = {} + playerStaticList = {} + scoreboard = {} + handler = nil + reference = nil + multiply = nil + reset:Remove() + default_text = "Pick a Category" + completed_questions = 0 + min_questions = 0 + dd_enabled = false + applied_dd = false + board = nil + question = nil +end + local function pickUniqueIndices(t, count) assert(#t >= count, "Not enough elements to pick " .. count .. " unique items") @@ -78,6 +104,15 @@ function applyDD() end end +local function setMultiplier(m) + multiply = m +end + +local function useDefaultHandler(callback) + handler.visible = true + reference = handler_conn(callback) +end + local templateLog = log:child("template") function LoadTemplate(name, path) boardLog:debug("Loading Template: %s", name) @@ -139,9 +174,11 @@ function LoadTemplate(name, path) theme = theme, gui = gui, timer = timer, + useDefaultHandler = useDefaultHandler, + setMultiplier = setMultiplier, -- love stuff newSource = love.audio.newSource, - log = templateLog + log = templateLog, } env._G = env @@ -172,14 +209,11 @@ function gui:cleanup() completed_questions = completed_questions + 1 end -local reset = boardUpdater:newConnection() - -local default_text = "Pick a Category" - -function Menu(frame, path) +function Menu(frame, path, deb) + local frameRef = frame:newFrame():fullFrame() + frameRef.visibility = 0 boardLog:info("Building board") if path:match(".zip") then - -- local basename = path:match("([^/\\]+)$") local success = love.filesystem.mount(path, "quiz", true) if not success then gui:newMessageBox({ @@ -199,23 +233,133 @@ function Menu(frame, path) path = "quiz" end + local scoreboard = ScoreBoard(frameRef, 0, 0, 0, 0, .06, .1, .170, .8) + + local qframe = frameRef:newFrame(0, 0, 0, 0, .24, .1, .70, .8) + + local dframe = frameRef:newTextLabel("",0, 0, 0, 0, .24, .1, .7, .8) + dframe:scaleFont(.075) + dframe:centerFont() + dframe.align = gui.ALIGN_CENTER + dframe.color = color.bg + dframe.visible = false + dframe:OnReleased(function(self) + if self.click then + boardUpdater:newThread(function() + thread.skip(1) + dframe.visible = false + end) + end + end) + + if deb then + boardLog.level = logger.LEVELS.DEBUG + templateLog.level = logger.LEVELS.DEBUG + boardLog:debug("Debug mode is activated when quiz directory is in the save directory") + local refresh = frameRef:newTextButton("Refresh", 0, -30, 140, 30, 0, 1) + refresh:centerFont() + refresh:scaleFont(.9) + refresh.align = gui.ALIGN_CENTER + refresh.color = color.green + refresh:OnReleased(function() + boardLog:debug("Cleaning up state and returning to title screen") + scoreboard:removeAllPlayers() + cleanUp() + frameRef:destroy() + menu.getMenu("title"):visible(true) + menu.getMenu("board"):visible(frame, path, deb) + end) + end + -- Start the processors now boardLog:debug("Starting processors") boardUpdater.Start() + boardLog:debug("Starting board-updater Started") qUpdater.Start() + boardLog:debug("Starting question-updater Started") scoreUpdater.Start() + boardLog:debug("Starting score-updater Started") - local scoreboard = ScoreBoard(frame, 0, 0, 0, 0, .06, .1, .170, .8) + local glide = transition.glide() - local qframe = frame:newFrame(0, 0, 0, 0, .24, .1, .70, .8) + local function displayAnswer(q) + dframe.text = q.answer + dframe.visible = true + dframe.click = q["display-mode"] == "click" + local sleep = 5 + local fade = 1 + if type(q["display-mode"]) == "number" then + sleep = q["display-mode"] + end + if type(q["display-fade"]) == "number" and q["display-fade"] > 0 then + fade = q["display-fade"] + end + if not dframe.click then + boardUpdater:newThread(function() + thread.sleep(sleep) + local handle = glide(1,0,fade) + handle:OnStep(function(p) + dframe.textVisibility = p + dframe.visibility = p + end) + handle:OnStop(function() + dframe.visible = false + dframe.textVisibility = 1 + dframe.visibility = 1 + handle.OnStep:Remove() + handle.OnStop:Remove() + end) + end) + end + end + + local label = frameRef:newTextLabel(default_text, 0, 10, 0, -20, .29, 0, .6, .1) + handler = frameRef:newFrame(0, 10, 0, -20, .29, .9, .6, .1) + handler.visible = false + local correct = handler:newTextButton("Correct", 5,0,-10,0,0,.1,1/3,.8) + correct.color = color.correct + local skip = handler:newTextButton("Skip", 8,0,-15,0,1/3,.1,1/3,.8) + skip.color = color.skip + local wrong = handler:newTextButton("Wrong", 5,0,-10,0,2/3,.1,1/3,.8) + wrong.color = color.wrong + + gui.apply({ + setRoundness = {15,15,60}, + centerFont = {}, + scaleFont = {1/2}, + align = gui.ALIGN_CENTER, + OnEnter = function(self) + self:setShader(gui.SHADERS.glow) + end, + OnExit = function(self) + self:setShader() + end, + OnReleased=function(self) + if self.text == "Skip" then + handler_conn:Fire() + reference:Unconnect() + handler.visible = false + return + end + local val = self.text == "Correct" + print(multiply) + handler_conn:Fire(val, multiply) + if val then + reference:Unconnect() + handler.visible = false + end + end, + },correct,skip,wrong) - local label = frame:newTextLabel(default_text, 0, 10, 0, -20, .29, 0, .6, .1) label.visibility = .85 label.drawBorder = false label.align = gui.ALIGN_CENTER label.color = color.bg label.textColor = color.status_font label:setRoundness(20,20,60) + handler:setRoundness(20,20,60) + handler.visibility = .9 + handler.color = color.bg label:scaleFont(2/3) label:centerFont() @@ -261,10 +405,13 @@ function Menu(frame, path) end end - reset(function() + reset(function(q) question:cleanup() - manageCosmetics(frame, cosmetics, true) + manageCosmetics(frame, cosmetics) label.text = default_text + if q["display-answer"] then + displayAnswer(q) + end end) for cat,v in pairs(index.categories) do @@ -307,7 +454,7 @@ function Menu(frame, path) if dd_enabled then applyDD() -- check and run DD if conditions meet end - if index.categories[cat].questions == nil then boardLog:info("Question not defined: File: %s Category: %s - %s\n",path,index.categories[cat].name,start + inc*(tier-1)) return end + if index.categories[cat].questions == nil then boardLog:debug("Question not defined: File: %s Category: %s - %s",path,index.categories[cat].name,start + inc*(tier-1)) return end local globals = index.categories[cat].global if not globals then globals = {} @@ -321,7 +468,7 @@ function Menu(frame, path) mt.__metatable = nil end setmetatable(q, {__index = globals}) - if q == nil then boardLog:info("Question contains no data: File: %s Category: %s Tier: %s\n",path,index.categories[cat].name,start + inc*(tier-1)) return end + if q == nil then boardLog:debug("Question contains no data: File: %s Category: %s Tier: %s",path,index.categories[cat].name,start + inc*(tier-1)) return end if q.cosmetics then manageCosmetics(frame, q.cosmetics) end @@ -364,14 +511,14 @@ function Menu(frame, path) player:Add((self.price*mul)*m) finished = true question.visible = false - reset:Fire() + reset:Fire(q) elseif ans == false then player:Add(-self.price*mul) player = GetNextPlayer() else finished = true question.visible = false - reset:Fire() + reset:Fire(q) end -- nil is a valid option where you weren't right or wrong, you just skipped self.text = "" end) @@ -488,13 +635,10 @@ function ScoreBoard(frame, x, y, w, h, sx, sy, sw, sh) textColor = C_TEXT_MUTED, }, headernum, headerplayer, headerscore) - local updateList = {headernum, headerplayer, headerscore} + local updateList = {headernum, headerplayer, headerscore, header} - header:centerFont() - header:scaleFont(2/3) - for _,object in pairs(updateList) do - object:fitFont(nil, nil, {scale = 5/6}) + object:scaleFont(2/3) object:centerFont() end @@ -533,10 +677,12 @@ function ScoreBoard(frame, x, y, w, h, sx, sy, sw, sh) local add_player = leaderboard:newFrame(5,-5,-10,0,0,1-PLAYER_HEIGHT,1,PLAYER_HEIGHT) local edit_player = leaderboard:newFrame(5,-10,-10,0,0,1-2*PLAYER_HEIGHT,1,PLAYER_HEIGHT) local remove_player = leaderboard:newTextButton("Remove Selected",5,-15,-10,0,0,1-3*PLAYER_HEIGHT,1,PLAYER_HEIGHT) - remove_player:setFont(20) remove_player.align = gui.ALIGN_CENTER local embededWatch = {remove_player} - remove_player:centerFont() + gui.apply({ + centerFont = {}, + scaleFont = {.5} + },add_player,edit_player,remove_player) local function embedTextEdit(reference, default, but_text, callback) reference.color = C_BORDER_NRM @@ -555,7 +701,7 @@ function ScoreBoard(frame, x, y, w, h, sx, sy, sw, sh) callback(textbox) end) gui.apply({ - setFont = {20}, + scaleFont = {.5}, align = gui.ALIGN_CENTER, centerFont = {}, },textbox,button,reference) @@ -593,6 +739,11 @@ function ScoreBoard(frame, x, y, w, h, sx, sy, sw, sh) end end) + function scoreboard:removeAllPlayers() + playerList = {} + playerStaticList = {} + end + function scoreboard:RenderPlayer(list) for index, player in ipairs(list) do if player.Ref then diff --git a/menus/title.lua b/menus/title.lua index 63b11b4..0b29e51 100644 --- a/menus/title.lua +++ b/menus/title.lua @@ -59,7 +59,7 @@ function Menu(frame) play:OnReleased(function() titleLog:debug("Play button pressed") if love.filesystem.getInfo("quiz") then - menu.getMenu("board"):visible(true, "quiz") + menu.getMenu("board"):visible(true, "quiz", true) return else gui:newFilePicker("File picker test",nil, {".zip"}, function(file) diff --git a/templates/imageword.lua b/templates/imageword.lua index d12be36..9347dea 100644 --- a/templates/imageword.lua +++ b/templates/imageword.lua @@ -10,8 +10,9 @@ local function index(window, q, callback) label.align = ALIGN_CENTER label.textColor = color.white label.color = color.new("#363ac8") - label.borderColor = color.new("#363ac8") - label:scaleFont(.075) + label.drawBorder = false + label:scaleFont(.4) + label:centerFont() if not q.imageA or q.imageA == "" then error("Missing 'imageA' field for question!") @@ -38,29 +39,11 @@ local function index(window, q, callback) imageHolder2:setAspectSize(imageHolder2.imageWidth, imageHolder2.imageHeight) imageHolder2:setDualDim(0, 0, 0, 0, .6, 0, .4, 1) - local correct = window:newTextButton("Correct",0,-200,0,100,0,1,.5) - correct.color = color.new("#52b11b") - local wrong = window:newTextButton("Wrong",0,-200,0,100,.5,1,.5) - wrong.color = color.new("#bd2626") - local skip = window:newTextButton("Skip",0,-100,0,100,.25,1,.5) - skip.color = color.new("#5d5d5d") - window.apply({ centerY = {true}, }, imageHolder, plusLabel, imageHolder2) - window.apply({ - scaleFont={.7}, - centerFont={}, - align=window.ALIGN_CENTER, - OnReleased=function(self) - if self.text == "Skip" then - callback() - return - end - callback(self.text == "Correct") - end, - }, correct, wrong, skip) + useDefaultHandler(callback) end local function update(dt) diff --git a/templates/multiplechoice.lua b/templates/multiplechoice.lua index 2742dee..c398292 100644 --- a/templates/multiplechoice.lua +++ b/templates/multiplechoice.lua @@ -25,6 +25,7 @@ local function index(window, q, callback) label:setFont(50) label:centerFont() label:scaleFont(2/3) + label.drawBorder = false local choices = window:newFrame(noOf(0,.3,1,.7)) choices.color = color.new("#363ac8") diff --git a/templates/one-image.lua b/templates/one-image.lua index 2acbfd7..68c4817 100644 --- a/templates/one-image.lua +++ b/templates/one-image.lua @@ -10,14 +10,15 @@ local label local imageHolder local function index(window, q, callback) - frame = window:newFrame(0,0,0,-200,0,.2,1,.8) + frame = window:newFrame(0,0,0,0,0,.2,1,.8) frame.visibility = 0 label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2) label.align = ALIGN_CENTER label.textColor = color.white label.color = color.new("#363ac8") - label:scaleFont(.5) + label:scaleFont(.4) label:centerFont() + label.drawBorder = false if not q.image or q.image == "" then error("Missing 'image' field for question!") end @@ -26,24 +27,8 @@ local function index(window, q, callback) imageHolder:centerX(true) imageHolder:centerY(true) imageHolder:setDualDim(0,0,imageHolder.imageWidth,imageHolder.imageHeight) - local correct = window:newTextButton("Correct",0,-200,0,100,0,1,.5) - correct.color = color.new("#52b11b") - local wrong = window:newTextButton("Wrong",0,-200,0,100,.5,1,.5) - wrong.color = color.new("#bd2626") - local skip = window:newTextButton("Skip",0,-100,0,100,.25,1,.5) - skip.color = color.new("#5d5d5d") - window.apply({ - scaleFont={.7}, - centerFont={}, - align=window.ALIGN_CENTER, - OnReleased=function(self) - if self.text == "Skip" then - callback() - return - end - callback(self.text == "Correct") - end, - },correct,wrong,skip) + + useDefaultHandler(callback) end local function update(dt) -- time in seconds that has passed since diff --git a/templates/whatis.lua b/templates/whatis.lua index f0e0cc3..fc95669 100644 --- a/templates/whatis.lua +++ b/templates/whatis.lua @@ -16,24 +16,9 @@ local function index(window, q, callback) label.color = color.new("#363ac8") label:centerFont() label:scaleFont(.075) - local correct = window:newTextButton("Correct",0,-200,0,100,0,1,.5) - correct.color = color.new("#52b11b") - local wrong = window:newTextButton("Wrong",0,-200,0,100,.5,1,.5) - wrong.color = color.new("#bd2626") - local skip = window:newTextButton("Skip",0,-100,0,100,.25,1,.5) - skip.color = color.new("#5d5d5d") - gui.apply({ - scaleFont={.7}, - centerFont={}, - align=gui.ALIGN_CENTER, - OnReleased=function(self) - if self.text == "Skip" then - callback() - return - end - callback(self.text == "Correct") - end, - },correct,wrong,skip) + label.drawBorder = false + + useDefaultHandler(callback) end local function update(dt) -- time in seconds that has passed since diff --git a/templates/whatsound.lua b/templates/whatsound.lua index de7ad26..31f7c6f 100644 --- a/templates/whatsound.lua +++ b/templates/whatsound.lua @@ -15,13 +15,17 @@ local function index(window, q, callback) callback() return end - frame = window:newFrame(0,0,0,-200,0,.2,1,.8) + frame = window:newFrame(0,0,0,0,0,.2,1,.8) frame.visibility = 0 label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2) label.align = ALIGN_CENTER label.textColor = color.white label.color = color.new("#363ac8") - imageHolder = frame:newImageButton("assets/images/speaker.png",0,0,0,0,0,0,.3,.4) + label:scaleFont(.4) + label:centerFont() + label.drawBorder = false + imageHolder = frame:newImageButton("assets/images/speaker.png",0,0,0,0,0,0,.3,.3) + imageHolder.scale = "h" imageHolder:setAspectSize(imageHolder.imageWidth,imageHolder.imageHeight) imageHolder:centerX(true) imageHolder:centerY(true) @@ -38,29 +42,12 @@ local function index(window, q, callback) sound:seek(0) end) end) - local correct = window:newTextButton("Correct",0,-200,0,100,0,1,.5) - correct.color = color.new("#52b11b") - local wrong = window:newTextButton("Wrong",0,-200,0,100,.5,1,.5) - wrong.color = color.new("#bd2626") - local skip = window:newTextButton("Skip",0,-100,0,100,.25,1,.5) - skip.color = color.new("#5d5d5d") - window.apply({ - fitFont={}, - align=window.ALIGN_CENTER, - OnReleased=function(self) - sound:stop() - if self.text == "Skip" then - callback() - return - end - callback(self.text == "Correct") - end, - },correct,wrong,skip) + + useDefaultHandler(callback) end local function update(dt) -- time in seconds that has passed since - label:fitFont() - label:centerFont() + end return { diff --git a/templates/whatvideo.lua b/templates/whatvideo.lua index 433ca73..66b6bb7 100644 --- a/templates/whatvideo.lua +++ b/templates/whatvideo.lua @@ -22,7 +22,8 @@ local function index(window, q, callback) label.textColor = color.white label.color = color.new("#363ac8") label:centerFont() - label:scaleFont(.5) + label:scaleFont(.4) + label.drawBorder = false local holder = frame:newFrame(-300, -200, 600, 400, .5, .5) holder:centerX(true) holder:centerY(true) @@ -33,25 +34,8 @@ local function index(window, q, callback) video:play() end) video.XButton.visible = false - local correct = window:newTextButton("Correct",0,-200,0,100,0,1,.5) - correct.color = color.new("#52b11b") - local wrong = window:newTextButton("Wrong",0,-200,0,100,.5,1,.5) - wrong.color = color.new("#bd2626") - local skip = window:newTextButton("Skip",0,-100,0,100,.25,1,.5) - skip.color = color.new("#5d5d5d") - window.apply({ - scaleFont={.7}, - centerFont={}, - align=window.ALIGN_CENTER, - OnReleased=function(self) - video:stop() - if self.text == "Skip" then - callback() - return - end - callback(self.text == "Correct") - end, - },correct,wrong,skip) + + useDefaultHandler(callback) end local function update(dt) -- time in seconds that has passed since diff --git a/templates/zoom.lua b/templates/zoom.lua index a206e9a..5d337d0 100644 --- a/templates/zoom.lua +++ b/templates/zoom.lua @@ -10,14 +10,16 @@ local label local imageHolder local function index(window, q, callback) - frame = window:newFrame(0,0,0,-200,0,.2,1,.8) + frame = window:newFrame(0,0,0,0,0,.2,1,.8) frame.visibility = 0 label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2) label.align = ALIGN_CENTER label.textColor = color.white label.color = color.new("#363ac8") - label:scaleFont(.5) + label:scaleFont(.4) label:centerFont() + label.drawBorder = false + local errors = {} if type(q.zoom) ~= "string" and q.zoom ~= "" then @@ -33,7 +35,7 @@ local function index(window, q, callback) end local zooms = {q.zoom, q.minzoom, q.fullimage} - print(q.fullimage) + local index = 1 local mul = 1 @@ -55,35 +57,22 @@ local function index(window, q, callback) imageHolder:OnReleased(function() index = index + 1 - print(index) if index == 2 then - mul = .5 + if q["zoom-deduct"] then + mul = .5 + end elseif index == 3 then - mul = .25 + if q["zoom-deduct"] then + mul = .25 + end else index = 3 end imageHolder:setImage(zooms[index]) + setMultiplier(mul) end) - local correct = window:newTextButton("Correct",0,-200,0,100,0,1,.5) - correct.color = color.new("#52b11b") - local wrong = window:newTextButton("Wrong",0,-200,0,100,.5,1,.5) - wrong.color = color.new("#bd2626") - local skip = window:newTextButton("Skip",0,-100,0,100,.25,1,.5) - skip.color = color.new("#5d5d5d") - window.apply({ - scaleFont={.7}, - centerFont={}, - align=window.ALIGN_CENTER, - OnReleased=function(self) - if self.text == "Skip" then - callback() - return - end - callback(self.text == "Correct", mul) - end, - },correct,wrong,skip) + useDefaultHandler(callback) end local function update(dt) -- time in seconds that has passed since diff --git a/version.txt b/version.txt index e4c0d46..a6a3a43 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0.3 \ No newline at end of file +1.0.4 \ No newline at end of file