adding menus and title handling
BIN
ai-anime/quiz.zip
Normal file
@ -1,33 +0,0 @@
|
|||||||
questions:
|
|
||||||
- title: "This Death Note villain is a world-famous detective who refuses to sit in a normal chair."
|
|
||||||
time-limit: 15
|
|
||||||
answer: "L"
|
|
||||||
template: "whatis"
|
|
||||||
|
|
||||||
- title: "In Fullmetal Alchemist: Brotherhood, Father created seven Homunculi. Which of these is NOT one of them?"
|
|
||||||
answer: 4
|
|
||||||
choices:
|
|
||||||
- "Gluttony"
|
|
||||||
- "Envy"
|
|
||||||
- "Wrath"
|
|
||||||
- "Malice"
|
|
||||||
template: "multiplechoice"
|
|
||||||
|
|
||||||
- title: "In Attack on Titan, this character orchestrated the Rumbling to trample the world outside Paradis Island."
|
|
||||||
time-limit: 20
|
|
||||||
answer: "Eren Yeager"
|
|
||||||
template: "whatis"
|
|
||||||
|
|
||||||
- title: "Which of these best describes Griffith's betrayal in Berserk, the event known as the Eclipse?"
|
|
||||||
answer: 1
|
|
||||||
choices:
|
|
||||||
- "He sacrificed the Band of the Hawk to be reborn as the demon king Femto"
|
|
||||||
- "He defected to the Midland king and had Guts executed"
|
|
||||||
- "He destroyed Guts' sword to prevent him from following him"
|
|
||||||
- "He erased everyone's memories of the Band of the Hawk"
|
|
||||||
template: "multiplechoice"
|
|
||||||
|
|
||||||
- title: "Dio Brando's Stand in JoJo's Bizarre Adventure Part 3 has the ability to stop time. This is its name."
|
|
||||||
time-limit: 20
|
|
||||||
answer: "The World"
|
|
||||||
template: "whatis"
|
|
||||||
@ -20,7 +20,7 @@ questions: # expects a list equal to the tier
|
|||||||
- "9000"
|
- "9000"
|
||||||
- "-4"
|
- "-4"
|
||||||
- "wack"
|
- "wack"
|
||||||
template: "multiplechoice" # template to use
|
template: "multiplechoice"
|
||||||
- title: "Who directed the groundbreaking film 'Akira',\nwhich helped introduce anime to Western audiences?"
|
- title: "Who directed the groundbreaking film 'Akira',\nwhich helped introduce anime to Western audiences?"
|
||||||
time-limit: 10 # If omitted there is no time limit
|
time-limit: 10 # If omitted there is no time limit
|
||||||
answer: "Katsuhiro Otomo"
|
answer: "Katsuhiro Otomo"
|
||||||
@ -32,4 +32,4 @@ questions: # expects a list equal to the tier
|
|||||||
start: 4
|
start: 4
|
||||||
playFor: 3
|
playFor: 3
|
||||||
template: "whatvideo" # template to use
|
template: "whatvideo" # template to use
|
||||||
display-answer: true # displays the correct answer before returning to the main screen
|
display-answer: true # displays the correct answer before returning to the main screen
|
||||||
|
|||||||
BIN
assets/images/CLOUD.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
assets/images/background.jpg
Normal file
|
After Width: | Height: | Size: 982 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 179 KiB After Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
BIN
assets/sounds/finaltheme.mp3
Normal file
13
board.lua
@ -6,12 +6,17 @@ local fmt = require("fmt")
|
|||||||
local timer = require("utils")
|
local timer = require("utils")
|
||||||
local multi, thread = require("multi"):init()
|
local multi, thread = require("multi"):init()
|
||||||
|
|
||||||
local timesup = love.audio.newSource("assets/timesup.mp3", "static")
|
local timesup = love.audio.newSource("assets/sounds/timesup.mp3", "static")
|
||||||
local double = love.audio.newSource("assets/double.mp3", "static")
|
local double = love.audio.newSource("assets/sounds/double.mp3", "static")
|
||||||
|
|
||||||
local boardUpdater = gui:getProcessor():newProcessor("board-updater")
|
local boardUpdater = gui:getProcessor():newProcessor("board-updater")
|
||||||
boardUpdater.Start()
|
boardUpdater.Start()
|
||||||
|
|
||||||
|
local activePlayer
|
||||||
|
local playerList = {}
|
||||||
|
local playerStaticList = {}
|
||||||
|
local scoreboard = {}
|
||||||
|
|
||||||
-- Create a table to manage GUI elements
|
-- Create a table to manage GUI elements
|
||||||
local manage = {}
|
local manage = {}
|
||||||
|
|
||||||
@ -101,7 +106,7 @@ end
|
|||||||
|
|
||||||
local function buildBoard(frame, path)
|
local function buildBoard(frame, path)
|
||||||
local data = loader:new(path)
|
local data = loader:new(path)
|
||||||
board, question, dailydouble = frame:newFrame(), frame:newFrame(), frame:newImageLabel("assets/double.jpg")
|
board, question, dailydouble = frame:newFrame(), frame:newFrame(), frame:newImageLabel("assets/images/double.jpg")
|
||||||
index = data.index
|
index = data.index
|
||||||
board:fullFrame()
|
board:fullFrame()
|
||||||
question:fullFrame()
|
question:fullFrame()
|
||||||
@ -132,7 +137,7 @@ local function buildBoard(frame, path)
|
|||||||
|
|
||||||
c.UUID = multi.generate_uuid7() -- Each otpion gets a unique UUID
|
c.UUID = multi.generate_uuid7() -- Each otpion gets a unique UUID
|
||||||
|
|
||||||
img = c:newImageButton("assets/placeholder.jpg")
|
img = c:newImageButton("assets/images/placeholder.jpg")
|
||||||
img.visibility = 0
|
img.visibility = 0
|
||||||
|
|
||||||
img:OnReleased(function(self)
|
img:OnReleased(function(self)
|
||||||
|
|||||||
34
gui/init.lua
@ -16,7 +16,6 @@ local max, min, abs, rad, floor, ceil = math.max, math.min, math.abs, math.rad,
|
|||||||
local frame, image, text, box, video, button, anim = 0, 1, 2, 4, 8, 16, 32
|
local frame, image, text, box, video, button, anim = 0, 1, 2, 4, 8, 16, 32
|
||||||
local global_drag
|
local global_drag
|
||||||
local object_focus = gui
|
local object_focus = gui
|
||||||
local first_loop = false
|
|
||||||
|
|
||||||
-- Types
|
-- Types
|
||||||
gui.TYPE_FRAME = frame
|
gui.TYPE_FRAME = frame
|
||||||
@ -324,7 +323,7 @@ end
|
|||||||
|
|
||||||
function gui:isDescendantOf(obj)
|
function gui:isDescendantOf(obj)
|
||||||
local parent = self.parent
|
local parent = self.parent
|
||||||
while parent ~= gui do
|
while parent ~= gui and parent ~= nil do
|
||||||
if parent == obj then return true end
|
if parent == obj then return true end
|
||||||
parent = parent.parent
|
parent = parent.parent
|
||||||
end
|
end
|
||||||
@ -575,7 +574,7 @@ function gui:clone(opt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function gui:isActive()
|
function gui:isActive()
|
||||||
return self.active and not (self:isDescendantOf(gui.virtual))
|
return self.active and not self:isDescendantOf(gui.virtual)
|
||||||
end
|
end
|
||||||
|
|
||||||
function gui:isOnScreen()
|
function gui:isOnScreen()
|
||||||
@ -934,7 +933,7 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual)
|
|||||||
end
|
end
|
||||||
-- shader stuff
|
-- shader stuff
|
||||||
|
|
||||||
function c:setShader(shader)
|
function c:setShader(shader, env)
|
||||||
if type(shader) == "string" then
|
if type(shader) == "string" then
|
||||||
self.shader = love.graphics.newShader(shader)
|
self.shader = love.graphics.newShader(shader)
|
||||||
elseif type(shader) == "table" then
|
elseif type(shader) == "table" then
|
||||||
@ -948,6 +947,13 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual)
|
|||||||
else
|
else
|
||||||
self.shader:send(i, self[i])
|
self.shader:send(i, self[i])
|
||||||
end
|
end
|
||||||
|
elseif env[i] then
|
||||||
|
if type(v) == "function" then
|
||||||
|
local data = v(env)
|
||||||
|
self.shader:send(i, data)
|
||||||
|
else
|
||||||
|
self.shader:send(i, env[i])
|
||||||
|
end
|
||||||
else
|
else
|
||||||
error(i .. " is a required argument!\n\n".. shader.usage())
|
error(i .. " is a required argument!\n\n".. shader.usage())
|
||||||
end
|
end
|
||||||
@ -969,10 +975,14 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual)
|
|||||||
self.shader:send(name, ...)
|
self.shader:send(name, ...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
local st
|
||||||
function c:enableShaderTime()
|
function c:shaderTime(b)
|
||||||
|
if not b then
|
||||||
|
st:Unconnect()
|
||||||
|
end
|
||||||
|
if st then return end
|
||||||
self.__shaderTime = 0
|
self.__shaderTime = 0
|
||||||
mainupdater.OnLoop(function(_, _, dt)
|
st = mainupdater.OnLoop(function(_, _, dt)
|
||||||
if not self.shader then return end
|
if not self.shader then return end
|
||||||
self.__shaderTime = self.__shaderTime + dt
|
self.__shaderTime = self.__shaderTime + dt
|
||||||
if self.shader:hasUniform("time") then
|
if self.shader:hasUniform("time") then
|
||||||
@ -2311,24 +2321,18 @@ local draw_loop = drawer:newLoop(function(self, dt)
|
|||||||
draw_handler(child, nil, dt)
|
draw_handler(child, nil, dt)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
first_loop = true
|
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
end)
|
end)
|
||||||
draw_loop:setName("GUI Draw Handler")
|
draw_loop:setName("GUI Draw Handler")
|
||||||
|
|
||||||
drawer:newThread("Draw Handler",function()
|
drawer:newThread("Draw Handler",function()
|
||||||
while true do
|
while true do
|
||||||
thread.sleep(.01)
|
thread.sleep(.1)
|
||||||
local children = gui.virtual:getAllChildren()
|
local children = gui.virtual:getAllChildren()
|
||||||
for i = 1, #children do
|
for i = 1, #children do
|
||||||
local child = children[i]
|
local child = children[i]
|
||||||
if child.effect then
|
draw_handler(child, true, 0)
|
||||||
child.effect(function() draw_handler(child, true, 0) end)
|
|
||||||
else
|
|
||||||
draw_handler(child, true, 0)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
first_loop = true
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|||||||
340
main.lua
@ -1,8 +1,4 @@
|
|||||||
local gui, color, theme, utils, board, yaml, loader, scoreUpdater
|
local gui, color, theme, utils, board, yaml, loader, scoreUpdater
|
||||||
local activePlayer
|
|
||||||
local playerList = {}
|
|
||||||
local playerStaticList = {}
|
|
||||||
local scoreboard = {}
|
|
||||||
|
|
||||||
multi, thread = require("multi"):init({priority=true})
|
multi, thread = require("multi"):init({priority=true})
|
||||||
multi.setClock(require("socket").gettime) -- When on linux os.clock doesn't reture actual seconds the program has elapsed for
|
multi.setClock(require("socket").gettime) -- When on linux os.clock doesn't reture actual seconds the program has elapsed for
|
||||||
@ -17,20 +13,10 @@ yaml = require("yaml")
|
|||||||
loader = require("loader")
|
loader = require("loader")
|
||||||
require("gui.addons")
|
require("gui.addons")
|
||||||
|
|
||||||
scoreUpdater = gui:getProcessor():newProcessor("score-updater")
|
title = require("menus.title")
|
||||||
scoreUpdater.Start()
|
|
||||||
|
|
||||||
gui.registerExtension({
|
|
||||||
sayHello = function(self)
|
|
||||||
print("Extended Hello World")
|
|
||||||
end,
|
|
||||||
sayBye = function(self)
|
|
||||||
print("Extended Bye World")
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
function love.load()
|
function love.load()
|
||||||
gui:cacheImage({"assets/checked.png","assets/unchecked.png","assets/speaker.png"})
|
gui:cacheImage({"assets/images/checked.png","assets/images/unchecked.png","assets/images/speaker.png"})
|
||||||
gui:setAspectSize(1920, 1080)
|
gui:setAspectSize(1920, 1080)
|
||||||
gui.aspect_ratio = true
|
gui.aspect_ratio = true
|
||||||
|
|
||||||
@ -38,25 +24,10 @@ function love.load()
|
|||||||
bg:fullFrame()
|
bg:fullFrame()
|
||||||
bg.color = color.new("#242f9b")
|
bg.color = color.new("#242f9b")
|
||||||
|
|
||||||
local btn = bg:newImageButton("rainbow.jpg", 100, 100, 600, 450)
|
require("menus.menus").init(bg)
|
||||||
btn.color = color.light_blue
|
|
||||||
btn.align = gui.ALIGN_CENTER
|
|
||||||
|
|
||||||
btn.direction = {1,0}
|
title:visible(true)
|
||||||
|
|
||||||
btn:enableShaderTime()
|
|
||||||
btn.OnEnter(function()
|
|
||||||
btn:setShader(gui.SHADERS.blur)
|
|
||||||
end)
|
|
||||||
|
|
||||||
btn.OnExit(function()
|
|
||||||
btn:setShader()
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- btn:fitFont()
|
|
||||||
-- btn:centerFont()
|
|
||||||
|
|
||||||
-- bg:setBlur(10)
|
|
||||||
bg:OnUpdate(function(self, dt)
|
bg:OnUpdate(function(self, dt)
|
||||||
if self.__blur then
|
if self.__blur then
|
||||||
-- pulse the blur between 2 and 12
|
-- pulse the blur between 2 and 12
|
||||||
@ -64,309 +35,6 @@ function love.load()
|
|||||||
self:setBlurRadius(7 + 5 * math.sin(t * 2))
|
self:setBlurRadius(7 + 5 * math.sin(t * 2))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- StartGame(bg)
|
|
||||||
end
|
|
||||||
|
|
||||||
function GetActivePlayer()
|
|
||||||
if not activePlayer then return end
|
|
||||||
return activePlayer.link
|
|
||||||
end
|
|
||||||
|
|
||||||
local function GetPlayerPos()
|
|
||||||
for i,v in pairs(playerStaticList) do
|
|
||||||
if v == GetActivePlayer() then
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function GetNextPlayer()
|
|
||||||
local pos = GetPlayerPos()
|
|
||||||
|
|
||||||
if pos >= #playerStaticList then
|
|
||||||
activePlayer = playerStaticList[1].Ref.Frame
|
|
||||||
else
|
|
||||||
activePlayer = playerStaticList[pos + 1].Ref.Frame
|
|
||||||
end
|
|
||||||
scoreboard:RenderPlayer(playerList)
|
|
||||||
return GetActivePlayer()
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.filedropped(file)
|
|
||||||
file:open("r")
|
|
||||||
local data = file:read()
|
|
||||||
print("Load file? " .. file:getFilename())
|
|
||||||
end
|
|
||||||
|
|
||||||
function ScoreBoard(frame, x, y, w, h, sx, sy, sw, sh)
|
|
||||||
-- Colors
|
|
||||||
local C_BG_PANEL = color.new("#1a1a2e")
|
|
||||||
local C_BG_HEADER = color.new("#16213e")
|
|
||||||
local C_ACCENT = color.new("#e94560")
|
|
||||||
local C_ROW_TOP = color.new("#1c2641")
|
|
||||||
local C_ROW_NORM = color.new("#121226")
|
|
||||||
local C_BORDER_TOP = color.new("#323c6e")
|
|
||||||
local C_BORDER_NRM = color.new("#1c1c37")
|
|
||||||
local C_BAR_EMPTY = color.new("#232341")
|
|
||||||
local C_TEXT_MUTED = color.new("#786e96")
|
|
||||||
local C_WHITE = color.new("#ffffff")
|
|
||||||
local C_GOLD = color.new("#ffd700")
|
|
||||||
local C_SILVER = color.new("#C0C0C0")
|
|
||||||
local C_BRONZE = color.new("#cd7f32")
|
|
||||||
|
|
||||||
-- Config stuff
|
|
||||||
local LEADER_HEIGHT_SCALE = .06
|
|
||||||
local HEIGHT_SCALE = .03
|
|
||||||
local PLAYER_HEIGHT = .05
|
|
||||||
--
|
|
||||||
|
|
||||||
local rankColors = { C_GOLD, C_SILVER, C_BRONZE }
|
|
||||||
|
|
||||||
local leaderboard = frame:newFrame(x, y, w, h, sx, sy, sw, sh)
|
|
||||||
leaderboard.color = C_BORDER_NRM
|
|
||||||
|
|
||||||
local headernum = leaderboard:newTextLabel("#",0,0,0,0,0,LEADER_HEIGHT_SCALE,1/6,HEIGHT_SCALE)
|
|
||||||
headernum.align = gui.ALIGN_CENTER
|
|
||||||
|
|
||||||
local headerplayer = leaderboard:newTextLabel("PLAYER",0,0,0,0,1/6,LEADER_HEIGHT_SCALE,3/6,HEIGHT_SCALE)
|
|
||||||
headerplayer.align = gui.ALIGN_LEFT
|
|
||||||
|
|
||||||
local headerscore = leaderboard:newTextLabel("SCORE",0,0,0,0,4/6,LEADER_HEIGHT_SCALE,2/6,HEIGHT_SCALE)
|
|
||||||
headerscore.align = gui.ALIGN_RIGHT
|
|
||||||
|
|
||||||
local header = leaderboard:newTextLabel("LEADERBOARD",0,0,0,0,0,0,1,LEADER_HEIGHT_SCALE)
|
|
||||||
header.borderColor = C_ACCENT
|
|
||||||
header.textColor = C_ACCENT
|
|
||||||
header.color = C_BG_HEADER
|
|
||||||
header.align = gui.ALIGN_CENTER
|
|
||||||
|
|
||||||
local BASE_HEIGHT = LEADER_HEIGHT_SCALE + HEIGHT_SCALE
|
|
||||||
|
|
||||||
gui.apply({
|
|
||||||
drawBorder = false,
|
|
||||||
color = color.new("#0f2a60"),
|
|
||||||
textColor = C_TEXT_MUTED,
|
|
||||||
}, headernum, headerplayer, headerscore)
|
|
||||||
|
|
||||||
local updateList = {header, headernum, headerplayer, headerscore}
|
|
||||||
|
|
||||||
local function ScoreResize()
|
|
||||||
scoreUpdater:newThread(function()
|
|
||||||
thread.skip(2)
|
|
||||||
|
|
||||||
for _,object in pairs(updateList) do
|
|
||||||
object:fitFont(nil, nil, {scale = 5/6})
|
|
||||||
object:centerFont()
|
|
||||||
end
|
|
||||||
|
|
||||||
for _,object in pairs(playerList) do
|
|
||||||
if type(object) == "table" and object.Ref then
|
|
||||||
for i, player in pairs(object.Ref) do
|
|
||||||
if player:hasType(gui.TYPE_TEXT) then
|
|
||||||
player:fitFont(nil, nil, {scale = 5/6})
|
|
||||||
player:centerFont()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function scoreboard:AddPlayer(name, score, icon)
|
|
||||||
local player = {
|
|
||||||
Name = name,
|
|
||||||
Score = score,
|
|
||||||
Icon = icon,
|
|
||||||
UUID = multi.generate_uuid7(),
|
|
||||||
Add = function(self, amt)
|
|
||||||
self.Score = tostring(tonumber(self.Score) + amt)
|
|
||||||
table.sort(playerList, function(a, b)
|
|
||||||
if a.Score == b.Score then
|
|
||||||
return a.Name < b.Name
|
|
||||||
end
|
|
||||||
return tonumber(a.Score) > tonumber(b.Score)
|
|
||||||
end)
|
|
||||||
scoreboard:RenderPlayer(playerList)
|
|
||||||
ScoreResize()
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
table.insert(playerList, player)
|
|
||||||
table.insert(playerStaticList, player)
|
|
||||||
scoreboard:RenderPlayer(playerList)
|
|
||||||
ScoreResize()
|
|
||||||
return player
|
|
||||||
end
|
|
||||||
|
|
||||||
local colors = {C_GOLD, C_SILVER, C_BRONZE}
|
|
||||||
local function MapColor(index)
|
|
||||||
if index <=3 and index > 0 then
|
|
||||||
return colors[index]
|
|
||||||
else
|
|
||||||
return C_WHITE
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
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}
|
|
||||||
scoreUpdater:newThread(function()
|
|
||||||
while true do
|
|
||||||
thread.sleep(.01)
|
|
||||||
for i,v in pairs(embededWatch) do
|
|
||||||
v:centerFont()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function embedTextEdit(reference, default, but_text, callback)
|
|
||||||
reference.color = C_BORDER_NRM
|
|
||||||
local textbox = reference:newTextBox(default,0,0,0,0,.015,.1,.8,.8)
|
|
||||||
textbox.textColor = C_GOLD
|
|
||||||
textbox.blink = false
|
|
||||||
textbox.color = C_BORDER_TOP
|
|
||||||
textbox.textColor = C_WHITE
|
|
||||||
textbox:OnPressed(function()
|
|
||||||
textbox.text = ""
|
|
||||||
end)
|
|
||||||
|
|
||||||
local button = reference:newTextButton(but_text,5,0,-10,0,.815,.1,.185,.8)
|
|
||||||
button.color = color.new("#7eae5b")
|
|
||||||
button:OnReleased(function()
|
|
||||||
callback(textbox)
|
|
||||||
end)
|
|
||||||
gui.apply({
|
|
||||||
setFont = {20},
|
|
||||||
align = gui.ALIGN_CENTER
|
|
||||||
},textbox,button,reference)
|
|
||||||
table.insert(embededWatch,textbox)
|
|
||||||
table.insert(embededWatch,button)
|
|
||||||
end
|
|
||||||
|
|
||||||
remove_player.color = color.new("#a13a3a")
|
|
||||||
remove_player:OnReleased(function()
|
|
||||||
local player = GetActivePlayer()
|
|
||||||
uuid = player.UUID
|
|
||||||
for i = 1, #playerList do
|
|
||||||
if playerList[i].UUID == uuid then
|
|
||||||
table.remove(playerList,i)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for i = 1, #playerStaticList do
|
|
||||||
if playerStaticList[i].UUID == uuid then
|
|
||||||
table.remove(playerStaticList,i)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
scoreboard:RenderPlayer(playerList)
|
|
||||||
player.Ref.Frame:destroy()
|
|
||||||
end)
|
|
||||||
|
|
||||||
embedTextEdit(add_player, "Player Name", "Add", function(self)
|
|
||||||
scoreboard:AddPlayer(self.text, "0")
|
|
||||||
end)
|
|
||||||
|
|
||||||
embedTextEdit(edit_player, "Modify Score", "Edit", function(self)
|
|
||||||
local player = GetActivePlayer()
|
|
||||||
if player then
|
|
||||||
player.Score = self.text
|
|
||||||
scoreboard:RenderPlayer(playerList)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
function scoreboard:RenderPlayer(list)
|
|
||||||
for index, player in ipairs(list) do
|
|
||||||
if player.Ref then
|
|
||||||
player.Ref[1].text = player.Name or ""
|
|
||||||
player.Ref[2].text = player.Score or ""
|
|
||||||
player.Ref[3].text = tostring(index)
|
|
||||||
player.Ref.Frame:setDualDim(nil,5*index,nil,nil,nil,BASE_HEIGHT + (index-1) * PLAYER_HEIGHT)
|
|
||||||
player.Ref.Frame.link = player
|
|
||||||
|
|
||||||
gui.apply({
|
|
||||||
visibility = 0,
|
|
||||||
drawBorder = false,
|
|
||||||
textColor = MapColor(index)
|
|
||||||
}, unpack(player.Ref))
|
|
||||||
|
|
||||||
if activePlayer == nil then
|
|
||||||
activePlayer = player.Ref.Frame
|
|
||||||
end
|
|
||||||
|
|
||||||
if player.Ref.Frame == activePlayer then
|
|
||||||
player.Ref.Frame.borderColor = C_BORDER_NRM
|
|
||||||
player.Ref.Frame.color = C_ROW_NORM
|
|
||||||
else
|
|
||||||
player.Ref.Frame.borderColor = C_BORDER_TOP
|
|
||||||
player.Ref.Frame.color = C_ROW_TOP
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local playernum, playerName, playerIcon, playerScore, playerLine
|
|
||||||
local playerFrame = leaderboard:newFrame(5,5*index,-10,0,0,BASE_HEIGHT + (index-1) * PLAYER_HEIGHT,1,PLAYER_HEIGHT)
|
|
||||||
|
|
||||||
playerFrame:OnReleased(function(self)
|
|
||||||
activePlayer = self
|
|
||||||
scoreboard:RenderPlayer(playerList)
|
|
||||||
end)
|
|
||||||
|
|
||||||
playerFrame:respectHierarchy(false)
|
|
||||||
|
|
||||||
playerFrame.borderColor = C_BORDER_TOP
|
|
||||||
playerFrame.color = C_ROW_TOP
|
|
||||||
|
|
||||||
playernum = playerFrame:newTextLabel(index,0,0,0,0,.015,.1,1/8,.8)
|
|
||||||
playernum.align = gui.ALIGN_CENTER
|
|
||||||
|
|
||||||
if player.Icon ~= nil then
|
|
||||||
playerIcon = playerFrame:newImageLabel(player.Icon,0,0,0,0,.16,.1,.1,.8)
|
|
||||||
playerIcon.square = "h" -- When working with scales squaring is trickier. (h/w) to switch on width or height
|
|
||||||
|
|
||||||
playerName = playerFrame:newTextLabel(player.Name,0,0,0,0,.3,0,2/5,.8)
|
|
||||||
playerName.align = gui.ALIGN_LEFT
|
|
||||||
|
|
||||||
playerLine = playerFrame:newFrame(0,0,0,0,.3,.8,.69,.07)
|
|
||||||
playerLine.color = C_GOLD
|
|
||||||
else
|
|
||||||
playerName = playerFrame:newTextLabel(player.Name,0,0,0,0,.16,0,7/13,.8)
|
|
||||||
playerName.align = gui.ALIGN_LEFT
|
|
||||||
|
|
||||||
playerLine = playerFrame:newFrame(0,0,0,0,.16,.8,7/13 + 2/7,.07)
|
|
||||||
playerLine.color = C_GOLD
|
|
||||||
end
|
|
||||||
|
|
||||||
playerScore = playerFrame:newTextLabel(player.Score,0,0,0,0,.71,0,2/7,.8)
|
|
||||||
playerScore.align = gui.ALIGN_CENTER
|
|
||||||
playerLine.drawBorder = false
|
|
||||||
|
|
||||||
gui.apply({
|
|
||||||
visibility = 0,
|
|
||||||
drawBorder = false,
|
|
||||||
textColor = MapColor(index)
|
|
||||||
},playernum, playerName, playerScore, playerIcon, playerLine)
|
|
||||||
|
|
||||||
player.Ref = {playerName, playerScore, playernum, playerIcon, playerLine, Frame = playerFrame}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
gui.Events.OnResized(ScoreResize)
|
|
||||||
ScoreResize()
|
|
||||||
return scoreboard
|
|
||||||
end
|
|
||||||
|
|
||||||
function LandingPage(bg)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function StartGame(bg)
|
|
||||||
local qframe = bg:newFrame(0, 0, 0, 0, .2, .05, .75, .9)
|
|
||||||
qframe.color = color.new("#060ee9")
|
|
||||||
local scoreboard = ScoreBoard(bg, 0, 0, 0, 0, .015, .05, .170, .9)
|
|
||||||
board.buildBoard(qframe, "anime")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.update(dt)
|
function love.update(dt)
|
||||||
|
|||||||
592
menus/board.lua
Normal file
@ -0,0 +1,592 @@
|
|||||||
|
local gui = require("gui")
|
||||||
|
local color = require("gui.core.color")
|
||||||
|
local loader = require("loader")
|
||||||
|
local theme = require("gui.core.theme")
|
||||||
|
local fmt = require("fmt")
|
||||||
|
local timer = require("utils")
|
||||||
|
local multi, thread = require("multi"):init()
|
||||||
|
local menu = require("menus.menus")
|
||||||
|
|
||||||
|
local timesup = love.audio.newSource("assets/sounds/timesup.mp3", "static")
|
||||||
|
local double = love.audio.newSource("assets/sounds/double.mp3", "static")
|
||||||
|
|
||||||
|
local boardUpdater = gui:getProcessor():newProcessor("board-updater")
|
||||||
|
boardUpdater.Start()
|
||||||
|
|
||||||
|
local activePlayer
|
||||||
|
local playerList = {}
|
||||||
|
local playerStaticList = {}
|
||||||
|
local scoreboard = {}
|
||||||
|
|
||||||
|
-- Create a table to manage GUI elements
|
||||||
|
local manage = {}
|
||||||
|
|
||||||
|
-- Function to resize fonts for all managed elements
|
||||||
|
local function resizeFonts()
|
||||||
|
-- Use multi-threading to improve performance
|
||||||
|
multi:newThread(function()
|
||||||
|
-- Introduce a small delay to avoid too many iterations at once
|
||||||
|
thread.skip(2)
|
||||||
|
-- Iterate over each element in the 'manage' table
|
||||||
|
for i = 1, #manage do
|
||||||
|
local elem = manage[i]
|
||||||
|
|
||||||
|
-- Check if the current element has a centerFont property
|
||||||
|
if elem.centerFont then
|
||||||
|
-- Adjust font size and re-center the text
|
||||||
|
elem:fitFont(nil, nil, {scale = 2/3})
|
||||||
|
elem:centerFont()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
gui.Events.OnResized(resizeFonts)
|
||||||
|
|
||||||
|
local completed_questions = 0
|
||||||
|
local min_questions = 0
|
||||||
|
local dd_count = 0
|
||||||
|
local dd_enabled = false
|
||||||
|
local applied_dd = false
|
||||||
|
local board, question
|
||||||
|
|
||||||
|
function gui:cleanup()
|
||||||
|
for i = #self.children, 1, -1 do
|
||||||
|
self.children[i]:destroy()
|
||||||
|
end
|
||||||
|
self.children = {}
|
||||||
|
completed_questions = completed_questions + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pickUniqueIndices(t, count)
|
||||||
|
assert(#t >= count, "Not enough elements to pick " .. count .. " unique items")
|
||||||
|
|
||||||
|
local indices = {}
|
||||||
|
for i = 1, #t do indices[i] = i end
|
||||||
|
|
||||||
|
-- partial Fisher-Yates shuffle
|
||||||
|
for i = 1, count do
|
||||||
|
local j = math.random(i, #indices)
|
||||||
|
indices[i], indices[j] = indices[j], indices[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
return unpack(indices, 1, count)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pickFiltered(items, count)
|
||||||
|
-- Filter to only elements whose text contains "$"
|
||||||
|
local filtered = {}
|
||||||
|
for _, item in ipairs(items) do
|
||||||
|
if item.text:find("%$") then
|
||||||
|
filtered[#filtered + 1] = item
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Use pickUniqueIndices to select from filtered results
|
||||||
|
local picks = { pickUniqueIndices(filtered, count) }
|
||||||
|
local results = {}
|
||||||
|
for _, idx in ipairs(picks) do
|
||||||
|
results[#results + 1] = filtered[idx]
|
||||||
|
end
|
||||||
|
|
||||||
|
return unpack(results)
|
||||||
|
end
|
||||||
|
|
||||||
|
function applyDD()
|
||||||
|
if not applied_dd and completed_questions > min_questions then
|
||||||
|
local dd = 0
|
||||||
|
local dd_list = {}
|
||||||
|
local dds = {pickFiltered(board.children, dd_count)}
|
||||||
|
for i,v in pairs(dds) do
|
||||||
|
print(i,v)
|
||||||
|
v.isDouble = true
|
||||||
|
end
|
||||||
|
applied_dd = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local qUpdater = gui:getProcessor():newProcessor("question-updater")
|
||||||
|
qUpdater.Start()
|
||||||
|
|
||||||
|
function LoadTemplate(name, path)
|
||||||
|
|
||||||
|
if love.filesystem.getInfo("templates/" .. name .. ".lua") then
|
||||||
|
data = love.filesystem.read("templates/" .. name .. ".lua")
|
||||||
|
elseif love.filesystem.getInfo(path .."/templates/" .. name .. ".lua") then
|
||||||
|
data = love.filesystem.read(path .."/templates/" .. name .. ".lua")
|
||||||
|
end
|
||||||
|
|
||||||
|
local template, err = loadstring(data)
|
||||||
|
|
||||||
|
if err ~= nil then
|
||||||
|
error(err)
|
||||||
|
end
|
||||||
|
|
||||||
|
local timer = function(wait, callback)
|
||||||
|
multi:newAlarm(wait):OnRing(callback)
|
||||||
|
end
|
||||||
|
|
||||||
|
local env = { -- lua built-ins except io/os code execution
|
||||||
|
pairs=pairs,
|
||||||
|
print=print,
|
||||||
|
tostring=tostring,
|
||||||
|
tonumber=tonumber,
|
||||||
|
type=type,
|
||||||
|
assert=assert,
|
||||||
|
ipairs=ipairs,
|
||||||
|
table=table,
|
||||||
|
math=math,
|
||||||
|
string=string,
|
||||||
|
next=next,
|
||||||
|
pcall=pcall,
|
||||||
|
select=select,
|
||||||
|
xpcall=xpcall,
|
||||||
|
utf8=utf8,
|
||||||
|
clock = require("socket").gettime,
|
||||||
|
ALIGN_CENTER = gui.ALIGN_CENTER,
|
||||||
|
ALIGN_LEFT = gui.ALIGN_LEFT,
|
||||||
|
ALIGN_RIGHT = gui.ALIGN_RIGHT,
|
||||||
|
ALIGN_JUSTIFY = gui.ALIGN_JUSTIFY,
|
||||||
|
-- Global vars
|
||||||
|
color = color,
|
||||||
|
error = multi.error,
|
||||||
|
theme = theme,
|
||||||
|
gui = gui,
|
||||||
|
timer = timer,
|
||||||
|
-- love stuff
|
||||||
|
newSource = love.audio.newSource
|
||||||
|
}
|
||||||
|
|
||||||
|
env._G = env
|
||||||
|
local isoTemplate = multi.isolateFunction(template, env)
|
||||||
|
|
||||||
|
return isoTemplate()
|
||||||
|
end
|
||||||
|
|
||||||
|
function Menu(frame, path)
|
||||||
|
local qframe = frame:newFrame(0, 0, 0, 0, .2, .05, .75, .9)
|
||||||
|
qframe.color = color.new("#060ee9")
|
||||||
|
local scoreboard = ScoreBoard(frame, 0, 0, 0, 0, .015, .05, .170, .9)
|
||||||
|
|
||||||
|
local data = loader:new(path)
|
||||||
|
board, question, dailydouble = qframe:newFrame(), qframe:newFrame(), qframe:newImageLabel("assets/images/double.jpg")
|
||||||
|
index = data.index
|
||||||
|
|
||||||
|
board:fullFrame()
|
||||||
|
question:fullFrame()
|
||||||
|
dailydouble:fullFrame()
|
||||||
|
|
||||||
|
dailydouble.visible = false
|
||||||
|
question.visible = false
|
||||||
|
question.color = color.new("#060ce9")
|
||||||
|
|
||||||
|
local tiers = index.settings.tiers or 5
|
||||||
|
local start = index.settings.start or 100
|
||||||
|
local inc = index.settings.increment or 100
|
||||||
|
|
||||||
|
if index.settings.dailyDouble and index.settings.dailyDouble.enabled then
|
||||||
|
local dd = index.settings.dailyDouble
|
||||||
|
dd_enabled = dd.enabled
|
||||||
|
min_questions = dd.minQuestions
|
||||||
|
dd_count = dd.count
|
||||||
|
end
|
||||||
|
for cat,v in pairs(index.categories) do
|
||||||
|
local c
|
||||||
|
if v.image then
|
||||||
|
c = board:newImageLabel(v.image, 0, 0, 0, 0,(1/#index.categories)*(cat-1),0,1/#index.categories,1/(tiers+1))
|
||||||
|
else
|
||||||
|
c = board:newTextLabel(v.displayName or v.name,0,0,0,0,(1/#index.categories)*(cat-1),0,1/#index.categories,1/(tiers+1))
|
||||||
|
c.align = gui.ALIGN_CENTER
|
||||||
|
c.textColor = color.new("#ffffff")
|
||||||
|
c.color = color.new("#060ce9")
|
||||||
|
end
|
||||||
|
|
||||||
|
c.UUID = multi.generate_uuid7() -- Each otpion gets a unique UUID
|
||||||
|
|
||||||
|
img = c:newImageButton("assets/images/placeholder.jpg")
|
||||||
|
img.visibility = 0
|
||||||
|
|
||||||
|
img:OnReleased(function(self)
|
||||||
|
self.visible = false
|
||||||
|
end)
|
||||||
|
|
||||||
|
img:fullFrame()
|
||||||
|
table.insert(manage,c)
|
||||||
|
for tier = 1,tiers do
|
||||||
|
local t = board:newTextButton("$" .. start + inc*(tier-1),0,0,0,0,(1/#index.categories)*(cat-1),1/(tiers+1)*tier,(1/#index.categories),1/(tiers+1))
|
||||||
|
t.textColor = color.new("#9b9024")
|
||||||
|
t.align = gui.ALIGN_CENTER
|
||||||
|
t.color = color.new("#060ce9")
|
||||||
|
t.category = v.name
|
||||||
|
t.index = tier
|
||||||
|
t.price = start + inc*(tier-1)
|
||||||
|
t:OnReleased(boardUpdater:newFunction(function(self)
|
||||||
|
if self.text == "" or GetActivePlayer() == nil then return end
|
||||||
|
if dd_enabled then
|
||||||
|
applyDD() -- check and run DD if conditions meet
|
||||||
|
end
|
||||||
|
if index.categories[cat].questions == nil then fmt.Printf("Question not defined: File: %v Category: %v - %v\n",path,index.categories[cat].name,start + inc*(tier-1)) return end
|
||||||
|
local q = index.categories[cat].questions[self.index]
|
||||||
|
if q == nil then fmt.Printf("Question contains no data: File: %v Category: %v Tier: %v\n",path,index.categories[cat].name,start + inc*(tier-1)) return end
|
||||||
|
self.textVisibility = 0
|
||||||
|
local template = LoadTemplate(q.template, path)
|
||||||
|
question.visible = true
|
||||||
|
local player = GetActivePlayer()
|
||||||
|
local tm
|
||||||
|
local stop
|
||||||
|
fmt.Printf("--------------------\nQuestion: %v \nAnswer: %v\n--------------------\n",q["title"],q["answer"])
|
||||||
|
local mul = 1
|
||||||
|
boardUpdater:newThread(function()
|
||||||
|
if self.isDouble then
|
||||||
|
mul = 2
|
||||||
|
double:play()
|
||||||
|
dailydouble.visible = true
|
||||||
|
thread.hold(function()
|
||||||
|
return not double:isPlaying()
|
||||||
|
end)
|
||||||
|
dailydouble.visible = false
|
||||||
|
end
|
||||||
|
if q["time-limit"] then
|
||||||
|
tm = timer.startTimer({duration = q["time-limit"]})
|
||||||
|
tm.OnStop(function()
|
||||||
|
-- Make sound? Subtract if daily double
|
||||||
|
if stop then return end
|
||||||
|
timesup:play()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
local finished = false
|
||||||
|
template.index(question, q, function(ans)
|
||||||
|
if finished then return end
|
||||||
|
player = GetActivePlayer()
|
||||||
|
if tm then
|
||||||
|
tm:Cleanup()
|
||||||
|
end
|
||||||
|
stop = true
|
||||||
|
if ans then
|
||||||
|
player:Add(self.price*mul)
|
||||||
|
finished = true
|
||||||
|
question.visible = false
|
||||||
|
question:cleanup()
|
||||||
|
elseif ans == false then
|
||||||
|
player:Add(-self.price*mul)
|
||||||
|
player = GetNextPlayer()
|
||||||
|
else
|
||||||
|
finished = true
|
||||||
|
question.visible = false
|
||||||
|
question:cleanup()
|
||||||
|
end -- nil is a valid option where you weren't right or wrong, you just skipped
|
||||||
|
self.text = ""
|
||||||
|
end)
|
||||||
|
boardUpdater:newThread("QuestionUpdater",function()
|
||||||
|
while true do
|
||||||
|
template.update(dt)
|
||||||
|
thread.yield()
|
||||||
|
if self.text == "" then return end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end))
|
||||||
|
table.insert(manage,t)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
resizeFonts()
|
||||||
|
resizeFonts()
|
||||||
|
|
||||||
|
return background
|
||||||
|
end
|
||||||
|
|
||||||
|
scoreUpdater = gui:getProcessor():newProcessor("score-updater")
|
||||||
|
scoreUpdater.Start()
|
||||||
|
|
||||||
|
function GetActivePlayer()
|
||||||
|
if not activePlayer then return end
|
||||||
|
return activePlayer.link
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GetPlayerPos()
|
||||||
|
for i,v in pairs(playerStaticList) do
|
||||||
|
if v == GetActivePlayer() then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function GetNextPlayer()
|
||||||
|
local pos = GetPlayerPos()
|
||||||
|
|
||||||
|
if pos >= #playerStaticList then
|
||||||
|
activePlayer = playerStaticList[1].Ref.Frame
|
||||||
|
else
|
||||||
|
activePlayer = playerStaticList[pos + 1].Ref.Frame
|
||||||
|
end
|
||||||
|
scoreboard:RenderPlayer(playerList)
|
||||||
|
return GetActivePlayer()
|
||||||
|
end
|
||||||
|
|
||||||
|
function love.filedropped(file)
|
||||||
|
file:open("r")
|
||||||
|
local data = file:read()
|
||||||
|
print("Load file? " .. file:getFilename())
|
||||||
|
end
|
||||||
|
|
||||||
|
function ScoreBoard(frame, x, y, w, h, sx, sy, sw, sh)
|
||||||
|
-- Colors
|
||||||
|
local C_BG_PANEL = color.new("#1a1a2e")
|
||||||
|
local C_BG_HEADER = color.new("#16213e")
|
||||||
|
local C_ACCENT = color.new("#e94560")
|
||||||
|
local C_ROW_TOP = color.new("#1c2641")
|
||||||
|
local C_ROW_NORM = color.new("#121226")
|
||||||
|
local C_BORDER_TOP = color.new("#323c6e")
|
||||||
|
local C_BORDER_NRM = color.new("#1c1c37")
|
||||||
|
local C_BAR_EMPTY = color.new("#232341")
|
||||||
|
local C_TEXT_MUTED = color.new("#786e96")
|
||||||
|
local C_WHITE = color.new("#ffffff")
|
||||||
|
local C_GOLD = color.new("#ffd700")
|
||||||
|
local C_SILVER = color.new("#C0C0C0")
|
||||||
|
local C_BRONZE = color.new("#cd7f32")
|
||||||
|
|
||||||
|
-- Config stuff
|
||||||
|
local LEADER_HEIGHT_SCALE = .06
|
||||||
|
local HEIGHT_SCALE = .03
|
||||||
|
local PLAYER_HEIGHT = .05
|
||||||
|
--
|
||||||
|
|
||||||
|
local rankColors = { C_GOLD, C_SILVER, C_BRONZE }
|
||||||
|
|
||||||
|
local leaderboard = frame:newFrame(x, y, w, h, sx, sy, sw, sh)
|
||||||
|
leaderboard.color = C_BORDER_NRM
|
||||||
|
|
||||||
|
local headernum = leaderboard:newTextLabel("#",0,0,0,0,0,LEADER_HEIGHT_SCALE,1/6,HEIGHT_SCALE)
|
||||||
|
headernum.align = gui.ALIGN_CENTER
|
||||||
|
|
||||||
|
local headerplayer = leaderboard:newTextLabel("PLAYER",0,0,0,0,1/6,LEADER_HEIGHT_SCALE,3/6,HEIGHT_SCALE)
|
||||||
|
headerplayer.align = gui.ALIGN_LEFT
|
||||||
|
|
||||||
|
local headerscore = leaderboard:newTextLabel("SCORE",0,0,0,0,4/6,LEADER_HEIGHT_SCALE,2/6,HEIGHT_SCALE)
|
||||||
|
headerscore.align = gui.ALIGN_RIGHT
|
||||||
|
|
||||||
|
local header = leaderboard:newTextLabel("LEADERBOARD",0,0,0,0,0,0,1,LEADER_HEIGHT_SCALE)
|
||||||
|
header.borderColor = C_ACCENT
|
||||||
|
header.textColor = C_ACCENT
|
||||||
|
header.color = C_BG_HEADER
|
||||||
|
header.align = gui.ALIGN_CENTER
|
||||||
|
|
||||||
|
local BASE_HEIGHT = LEADER_HEIGHT_SCALE + HEIGHT_SCALE
|
||||||
|
|
||||||
|
gui.apply({
|
||||||
|
drawBorder = false,
|
||||||
|
color = color.new("#0f2a60"),
|
||||||
|
textColor = C_TEXT_MUTED,
|
||||||
|
}, headernum, headerplayer, headerscore)
|
||||||
|
|
||||||
|
local updateList = {header, headernum, headerplayer, headerscore}
|
||||||
|
|
||||||
|
local function ScoreResize()
|
||||||
|
scoreUpdater:newThread(function()
|
||||||
|
thread.skip(2)
|
||||||
|
|
||||||
|
for _,object in pairs(updateList) do
|
||||||
|
object:fitFont(nil, nil, {scale = 5/6})
|
||||||
|
object:centerFont()
|
||||||
|
end
|
||||||
|
|
||||||
|
for _,object in pairs(playerList) do
|
||||||
|
if type(object) == "table" and object.Ref then
|
||||||
|
for i, player in pairs(object.Ref) do
|
||||||
|
if player:hasType(gui.TYPE_TEXT) then
|
||||||
|
player:fitFont(nil, nil, {scale = 5/6})
|
||||||
|
player:centerFont()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function scoreboard:AddPlayer(name, score, icon)
|
||||||
|
local player = {
|
||||||
|
Name = name,
|
||||||
|
Score = score,
|
||||||
|
Icon = icon,
|
||||||
|
UUID = multi.generate_uuid7(),
|
||||||
|
Add = function(self, amt)
|
||||||
|
self.Score = tostring(tonumber(self.Score) + amt)
|
||||||
|
table.sort(playerList, function(a, b)
|
||||||
|
if a.Score == b.Score then
|
||||||
|
return a.Name < b.Name
|
||||||
|
end
|
||||||
|
return tonumber(a.Score) > tonumber(b.Score)
|
||||||
|
end)
|
||||||
|
scoreboard:RenderPlayer(playerList)
|
||||||
|
ScoreResize()
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
table.insert(playerList, player)
|
||||||
|
table.insert(playerStaticList, player)
|
||||||
|
scoreboard:RenderPlayer(playerList)
|
||||||
|
ScoreResize()
|
||||||
|
return player
|
||||||
|
end
|
||||||
|
|
||||||
|
local colors = {C_GOLD, C_SILVER, C_BRONZE}
|
||||||
|
local function MapColor(index)
|
||||||
|
if index <=3 and index > 0 then
|
||||||
|
return colors[index]
|
||||||
|
else
|
||||||
|
return C_WHITE
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
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}
|
||||||
|
scoreUpdater:newThread(function()
|
||||||
|
while true do
|
||||||
|
thread.sleep(.01)
|
||||||
|
for i,v in pairs(embededWatch) do
|
||||||
|
v:centerFont()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function embedTextEdit(reference, default, but_text, callback)
|
||||||
|
reference.color = C_BORDER_NRM
|
||||||
|
local textbox = reference:newTextBox(default,0,0,0,0,.015,.1,.8,.8)
|
||||||
|
textbox.textColor = C_GOLD
|
||||||
|
textbox.blink = false
|
||||||
|
textbox.color = C_BORDER_TOP
|
||||||
|
textbox.textColor = C_WHITE
|
||||||
|
textbox:OnPressed(function()
|
||||||
|
textbox.text = ""
|
||||||
|
end)
|
||||||
|
|
||||||
|
local button = reference:newTextButton(but_text,5,0,-10,0,.815,.1,.185,.8)
|
||||||
|
button.color = color.new("#7eae5b")
|
||||||
|
button:OnReleased(function()
|
||||||
|
callback(textbox)
|
||||||
|
end)
|
||||||
|
gui.apply({
|
||||||
|
setFont = {20},
|
||||||
|
align = gui.ALIGN_CENTER
|
||||||
|
},textbox,button,reference)
|
||||||
|
table.insert(embededWatch,textbox)
|
||||||
|
table.insert(embededWatch,button)
|
||||||
|
end
|
||||||
|
|
||||||
|
remove_player.color = color.new("#a13a3a")
|
||||||
|
remove_player:OnReleased(function()
|
||||||
|
local player = GetActivePlayer()
|
||||||
|
uuid = player.UUID
|
||||||
|
for i = 1, #playerList do
|
||||||
|
if playerList[i].UUID == uuid then
|
||||||
|
table.remove(playerList,i)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i = 1, #playerStaticList do
|
||||||
|
if playerStaticList[i].UUID == uuid then
|
||||||
|
table.remove(playerStaticList,i)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
scoreboard:RenderPlayer(playerList)
|
||||||
|
player.Ref.Frame:destroy()
|
||||||
|
end)
|
||||||
|
|
||||||
|
embedTextEdit(add_player, "Player Name", "Add", function(self)
|
||||||
|
scoreboard:AddPlayer(self.text, "0")
|
||||||
|
end)
|
||||||
|
|
||||||
|
embedTextEdit(edit_player, "Modify Score", "Edit", function(self)
|
||||||
|
local player = GetActivePlayer()
|
||||||
|
if player then
|
||||||
|
player.Score = self.text
|
||||||
|
scoreboard:RenderPlayer(playerList)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
function scoreboard:RenderPlayer(list)
|
||||||
|
for index, player in ipairs(list) do
|
||||||
|
if player.Ref then
|
||||||
|
player.Ref[1].text = player.Name or ""
|
||||||
|
player.Ref[2].text = player.Score or ""
|
||||||
|
player.Ref[3].text = tostring(index)
|
||||||
|
player.Ref.Frame:setDualDim(nil,5*index,nil,nil,nil,BASE_HEIGHT + (index-1) * PLAYER_HEIGHT)
|
||||||
|
player.Ref.Frame.link = player
|
||||||
|
|
||||||
|
gui.apply({
|
||||||
|
visibility = 0,
|
||||||
|
drawBorder = false,
|
||||||
|
textColor = MapColor(index)
|
||||||
|
}, unpack(player.Ref))
|
||||||
|
|
||||||
|
if activePlayer == nil then
|
||||||
|
activePlayer = player.Ref.Frame
|
||||||
|
end
|
||||||
|
|
||||||
|
if player.Ref.Frame == activePlayer then
|
||||||
|
player.Ref.Frame.borderColor = C_BORDER_NRM
|
||||||
|
player.Ref.Frame.color = C_ROW_NORM
|
||||||
|
else
|
||||||
|
player.Ref.Frame.borderColor = C_BORDER_TOP
|
||||||
|
player.Ref.Frame.color = C_ROW_TOP
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local playernum, playerName, playerIcon, playerScore, playerLine
|
||||||
|
local playerFrame = leaderboard:newFrame(5,5*index,-10,0,0,BASE_HEIGHT + (index-1) * PLAYER_HEIGHT,1,PLAYER_HEIGHT)
|
||||||
|
|
||||||
|
playerFrame:OnReleased(function(self)
|
||||||
|
activePlayer = self
|
||||||
|
scoreboard:RenderPlayer(playerList)
|
||||||
|
end)
|
||||||
|
|
||||||
|
playerFrame:respectHierarchy(false)
|
||||||
|
|
||||||
|
playerFrame.borderColor = C_BORDER_TOP
|
||||||
|
playerFrame.color = C_ROW_TOP
|
||||||
|
|
||||||
|
playernum = playerFrame:newTextLabel(index,0,0,0,0,.015,.1,1/8,.8)
|
||||||
|
playernum.align = gui.ALIGN_CENTER
|
||||||
|
|
||||||
|
if player.Icon ~= nil then
|
||||||
|
playerIcon = playerFrame:newImageLabel(player.Icon,0,0,0,0,.16,.1,.1,.8)
|
||||||
|
playerIcon.square = "h" -- When working with scales squaring is trickier. (h/w) to switch on width or height
|
||||||
|
|
||||||
|
playerName = playerFrame:newTextLabel(player.Name,0,0,0,0,.3,0,2/5,.8)
|
||||||
|
playerName.align = gui.ALIGN_LEFT
|
||||||
|
|
||||||
|
playerLine = playerFrame:newFrame(0,0,0,0,.3,.8,.69,.07)
|
||||||
|
playerLine.color = C_GOLD
|
||||||
|
else
|
||||||
|
playerName = playerFrame:newTextLabel(player.Name,0,0,0,0,.16,0,7/13,.8)
|
||||||
|
playerName.align = gui.ALIGN_LEFT
|
||||||
|
|
||||||
|
playerLine = playerFrame:newFrame(0,0,0,0,.16,.8,7/13 + 2/7,.07)
|
||||||
|
playerLine.color = C_GOLD
|
||||||
|
end
|
||||||
|
|
||||||
|
playerScore = playerFrame:newTextLabel(player.Score,0,0,0,0,.71,0,2/7,.8)
|
||||||
|
playerScore.align = gui.ALIGN_CENTER
|
||||||
|
playerLine.drawBorder = false
|
||||||
|
|
||||||
|
gui.apply({
|
||||||
|
visibility = 0,
|
||||||
|
drawBorder = false,
|
||||||
|
textColor = MapColor(index)
|
||||||
|
},playernum, playerName, playerScore, playerIcon, playerLine)
|
||||||
|
|
||||||
|
player.Ref = {playerName, playerScore, playernum, playerIcon, playerLine, Frame = playerFrame}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
gui.Events.OnResized(ScoreResize)
|
||||||
|
ScoreResize()
|
||||||
|
return scoreboard
|
||||||
|
end
|
||||||
|
|
||||||
|
return menu.registerMenu("board", Menu)
|
||||||
54
menus/menus.lua
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
local gui = require("gui")
|
||||||
|
local menu = {}
|
||||||
|
local menus = {}
|
||||||
|
local frame
|
||||||
|
local menuRef = {}
|
||||||
|
local mt = {
|
||||||
|
__index = menuRef
|
||||||
|
}
|
||||||
|
|
||||||
|
function menu.registerMenu(name, menu, delete)
|
||||||
|
local c = {}
|
||||||
|
c.MenuFunc = menu
|
||||||
|
c.Delete = delete
|
||||||
|
setmetatable(c, mt)
|
||||||
|
menus[name] = c
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
function menu.getMenu(name)
|
||||||
|
return menus[name] or nil, "Menu ".. name .. " not found."
|
||||||
|
end
|
||||||
|
|
||||||
|
function menu.init(f)
|
||||||
|
frame = f
|
||||||
|
end
|
||||||
|
|
||||||
|
function menu.hideMenus()
|
||||||
|
for k,v in pairs(menus) do
|
||||||
|
if v.frame then
|
||||||
|
if v.Delete then
|
||||||
|
v.frame:destroy()
|
||||||
|
menus[k] = nil
|
||||||
|
else
|
||||||
|
v.frame.visible = false
|
||||||
|
v.frame.active = false
|
||||||
|
v.frame:setParent(gui.virtual)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function menuRef:visible(value, ...)
|
||||||
|
menu.hideMenus()
|
||||||
|
if self.__menuConfigured and self.frame then
|
||||||
|
self.frame.visible = true
|
||||||
|
self.frame.active = true
|
||||||
|
self.frame:setParent(frame)
|
||||||
|
else
|
||||||
|
self.__menuConfigured = true
|
||||||
|
self.frame = self.MenuFunc(frame, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return menu
|
||||||
9
menus/settings.lua
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
local gui = require("gui")
|
||||||
|
local color = require("gui.core.color")
|
||||||
|
local menu = require("menus.menus")
|
||||||
|
-- local proc = gui:getProcessor():newProcessor("settings")
|
||||||
|
|
||||||
|
function Menu(frame)
|
||||||
|
local background = frame:newImageLabel("assets/images/background.jpg")
|
||||||
|
background:fullFrame()
|
||||||
|
end
|
||||||
72
menus/title.lua
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
local gui = require("gui")
|
||||||
|
local color = require("gui.core.color")
|
||||||
|
local menu = require("menus.menus")
|
||||||
|
local proc = gui:getProcessor():newProcessor("main-title")
|
||||||
|
|
||||||
|
local board = require("menus.board")
|
||||||
|
|
||||||
|
function Menu(frame)
|
||||||
|
local background = frame:newImageLabel("assets/images/background.jpg")
|
||||||
|
background:fullFrame()
|
||||||
|
local title = frame:newTextLabel("Jeopardy",0,0,0,0,0,.1,1,.25)
|
||||||
|
title:setFont("assets/fonts/gyparody.ttf",300)
|
||||||
|
|
||||||
|
title:setShader(gui.SHADERS.vignette,{
|
||||||
|
intensity = .5,
|
||||||
|
smoothness = .8
|
||||||
|
})
|
||||||
|
|
||||||
|
title.align = gui.ALIGN_CENTER
|
||||||
|
title.visibility = 0
|
||||||
|
title.textColor = color.new("#b16d24")
|
||||||
|
title.drawBorder = false
|
||||||
|
|
||||||
|
proc:newThread(function()
|
||||||
|
local function enabled()
|
||||||
|
return background.visible
|
||||||
|
end
|
||||||
|
while true do
|
||||||
|
thread.hold(enabled)
|
||||||
|
title:centerFont()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local items = 0
|
||||||
|
local MenuOption = function(str)
|
||||||
|
local item = background:newImageLabel("assets/images/CLOUD.png",-150,-63+(items*130),300,125,.5,.6)
|
||||||
|
local text = item:newTextLabel(str)
|
||||||
|
text:fullFrame()
|
||||||
|
text.align = gui.ALIGN_CENTER
|
||||||
|
thread:newThread(function()
|
||||||
|
thread.skip(2)
|
||||||
|
text:fitFont(nil,nil,{scale = 1/2})
|
||||||
|
text:centerFont()
|
||||||
|
text.visibility = 0
|
||||||
|
text.textColor = color.new("#24269a")
|
||||||
|
end)
|
||||||
|
items = items + 1
|
||||||
|
return item, text
|
||||||
|
end
|
||||||
|
local play = MenuOption("PLAY")
|
||||||
|
local settings = MenuOption("SETTINGS")
|
||||||
|
local quit = MenuOption("QUIT")
|
||||||
|
|
||||||
|
gui.apply({
|
||||||
|
OnEnter = function(self)
|
||||||
|
self:setShader(gui.SHADERS.glow)
|
||||||
|
end,
|
||||||
|
OnExit = function(self)
|
||||||
|
self:setShader()
|
||||||
|
end,
|
||||||
|
shaderTime = {true}
|
||||||
|
},play,settings,quit)
|
||||||
|
|
||||||
|
play:OnReleased(function()
|
||||||
|
background.visible = false
|
||||||
|
menu.getMenu("board"):visible(true,"anime")
|
||||||
|
end)
|
||||||
|
|
||||||
|
return background
|
||||||
|
end
|
||||||
|
|
||||||
|
return menu.registerMenu("title", Menu)
|
||||||
2
multi
@ -1 +1 @@
|
|||||||
Subproject commit c86413351c8e2fdd3b595d3df1ba0b9ac7d1f9b1
|
Subproject commit ee5e3bde7f9ea255ebcacb52e8e5333b6d3ac62a
|
||||||
@ -26,7 +26,7 @@ local function index(window, q, callback)
|
|||||||
imageHolder:setDualDim(0, 0, 0, 0, 0, 0, .4, 1)
|
imageHolder:setDualDim(0, 0, 0, 0, 0, 0, .4, 1)
|
||||||
|
|
||||||
-- Plus sign: centered between images at 0.42 to 0.58
|
-- Plus sign: centered between images at 0.42 to 0.58
|
||||||
plusLabel = frame:newImageLabel("assets/plus.png", 0, 0, 0, 0, .4125, .4, .175)
|
plusLabel = frame:newImageLabel("assets/images/plus.png", 0, 0, 0, 0, .4125, .4, .175)
|
||||||
plusLabel.square = "w"
|
plusLabel.square = "w"
|
||||||
plusLabel.align = ALIGN_CENTER
|
plusLabel.align = ALIGN_CENTER
|
||||||
plusLabel.textColor = color.white
|
plusLabel.textColor = color.white
|
||||||
|
|||||||
@ -29,17 +29,17 @@ local function index(window, q, callback)
|
|||||||
function choices:newChoice(choice, i)
|
function choices:newChoice(choice, i)
|
||||||
local c = choices:newFrame(noOf(.25,(i-1)/#q.choices,.5,1/#q.choices))
|
local c = choices:newFrame(noOf(.25,(i-1)/#q.choices,.5,1/#q.choices))
|
||||||
c.visibility = 0
|
c.visibility = 0
|
||||||
local box = c:newImageButton("assets/unchecked.png",noOf(.024*(#q.choices/4),.1,0,.8))
|
local box = c:newImageButton("assets/images/unchecked.png",noOf(.024*(#q.choices/4),.1,0,.8))
|
||||||
box.checked = false
|
box.checked = false
|
||||||
box:OnReleased(function()
|
box:OnReleased(function()
|
||||||
if box.checked then
|
if box.checked then
|
||||||
box:setImage("assets/unchecked.png")
|
box:setImage("assets/images/unchecked.png")
|
||||||
else
|
else
|
||||||
for _, other in pairs(allBoxes) do
|
for _, other in pairs(allBoxes) do
|
||||||
other.checked = false
|
other.checked = false
|
||||||
other:setImage("assets/unchecked.png")
|
other:setImage("assets/images/unchecked.png")
|
||||||
end
|
end
|
||||||
box:setImage("assets/checked.png")
|
box:setImage("assets/images/checked.png")
|
||||||
selected = i
|
selected = i
|
||||||
end
|
end
|
||||||
box.checked = not checked
|
box.checked = not checked
|
||||||
|
|||||||
@ -21,7 +21,7 @@ local function index(window, q, callback)
|
|||||||
label.align = ALIGN_CENTER
|
label.align = ALIGN_CENTER
|
||||||
label.textColor = color.white
|
label.textColor = color.white
|
||||||
label.color = color.new("#060ce9")
|
label.color = color.new("#060ce9")
|
||||||
imageHolder = frame:newImageButton("assets/speaker.png",0,0,0,0,0,0,.3,.4)
|
imageHolder = frame:newImageButton("assets/images/speaker.png",0,0,0,0,0,0,.3,.4)
|
||||||
imageHolder:setAspectSize(imageHolder.imageWidth,imageHolder.imageHeight)
|
imageHolder:setAspectSize(imageHolder.imageWidth,imageHolder.imageHeight)
|
||||||
imageHolder:centerX(true)
|
imageHolder:centerX(true)
|
||||||
imageHolder:centerY(true)
|
imageHolder:centerY(true)
|
||||||
|
|||||||