Files
jeopardy/utils/utils.lua
T
2026-06-08 20:29:59 -07:00

134 lines
3.6 KiB
Lua

local gui = require("gui")
local color = require("gui.core.color")
local multi, thread = require("multi"):init()
local function startTimer(opt)
local default = {
duration = 30,
autoText = true,
autoColor = true,
autoCleanup = false,
startColor = color.green,
textColor = color.black,
warnColor = color.yellow,
timeColor = color.red,
finegrained = false,
visibility = 1
}
if type(opt) == "number" then
local d = opt
opt = default
opt.duration = d
elseif type(opt) ~= "table" then
opt = default
else
for i, v in pairs(opt) do
default[i] = v
end
opt = default
end
local timeRemaining = opt.duration or 30
local tpie = gui:newFrame():makeArc("pie", -200, 0, 100, 1, 0, 0, 1.5*math.pi, 3.5*math.pi, 360)
local tlabel = tpie:newTextLabel("")
tlabel.textColor = opt.textColor
tlabel.align = gui.ALIGN_CENTER
tlabel:fullFrame()
tlabel.visibility = 0
tpie.color = opt.startColor
tpie.visibility = opt.visibility
local tm
local stopped = false
local onTimeConn = multi:newConnection()
local onStopConn = multi:newConnection()
local function cleanup()
if stopped then return end
stopped = true
if onTimeConn and not onTimeConn.destroyed then
onTimeConn:Destroy()
end
if not tpie.destroyed then
tpie:destroy()
end
end
local timerThread = thread:newThread("Pie Timer", function()
local startTime = love.timer.getTime()
local lastSecond = timeRemaining
while not stopped do
thread.sleep(1/60)
local now = love.timer.getTime()
local elapsed = now - startTime
local t = math.min(elapsed, timeRemaining)
local num = timeRemaining - math.floor(t)
local p = 3.5 - (t / timeRemaining) * 2
if opt.autoColor then
tpie.color = opt.startColor
if num <= timeRemaining / 3 then
tpie.color = opt.timeColor
elseif num <= timeRemaining / 2 then
tpie.color = opt.warnColor
end
end
tpie:makeArc("pie", -200, 0, 100, 1, 0, 0, 1.5*math.pi, p*math.pi, 360)
if opt.autoText then
tlabel.text = num
tlabel:fitFont(nil, nil, {scale=1/2})
tlabel:centerFont()
end
if opt.finegrained then
onTimeConn:Fire(tm, num, t)
elseif num < lastSecond then
-- crossed a second boundary
lastSecond = num
onTimeConn:Fire(tm, num, t)
end
if elapsed >= timeRemaining then
break
end
end
-- Timer finished
if stopped then return end
if opt.autoText then
tlabel.text = "Time"
tlabel:fitFont(nil, nil, {scale=1/2})
tlabel:centerFont()
end
tpie:makeArc("pie", -200, 0, 100, 1, 0, 0, 1.5*math.pi, 3.5*math.pi, 360)
local onStop = onStopConn
cleanup()
onStop:Fire(tm)
end)
tm = {
Duration = timeRemaining,
OnTime = onTimeConn,
OnStop = onStopConn,
SetText = function(str) tlabel.text = str end,
SetColor = function(c) tpie.color = c end,
Cleanup = function()
timerThread:Kill()
cleanup()
end,
}
return tm
end
return {
startTimer = startTimer
}