fixed package so it contains templates, updated config for more control
@@ -0,0 +1,3 @@
|
|||||||
|
bin/*
|
||||||
|
love/*
|
||||||
|
game.love
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
settings:
|
|
||||||
increment: 100
|
|
||||||
start: 100
|
|
||||||
tiers: 5
|
|
||||||
dailyDouble:
|
|
||||||
enabled: true
|
|
||||||
minQuestions: 7
|
|
||||||
count: 2
|
|
||||||
|
|
||||||
categories:
|
|
||||||
- name: shounen
|
|
||||||
displayName: "Shounen"
|
|
||||||
- name: villains
|
|
||||||
displayName: "Villains"
|
|
||||||
- name: openings
|
|
||||||
displayName: "Openings"
|
|
||||||
- name: studios
|
|
||||||
displayName: "Studios & Staff"
|
|
||||||
- name: plot-twists
|
|
||||||
displayName: "Plot Twists"
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
questions:
|
|
||||||
- title: "The iconic opening 'Guren no Yumiya' by Linked Horizon belongs to this anime."
|
|
||||||
time-limit: 15
|
|
||||||
answer: "Attack on Titan"
|
|
||||||
template: "whatis"
|
|
||||||
|
|
||||||
- title: "Which anime features the opening 'Unravel' by TK from Ling Tosite Sigure?"
|
|
||||||
answer: 2
|
|
||||||
choices:
|
|
||||||
- "Parasyte"
|
|
||||||
- "Tokyo Ghoul"
|
|
||||||
- "Deadman Wonderland"
|
|
||||||
- "Elfen Lied"
|
|
||||||
template: "multiplechoice"
|
|
||||||
|
|
||||||
- title: "'Cruel Angel's Thesis' is the legendary opening theme of this 1995 mecha anime."
|
|
||||||
time-limit: 20
|
|
||||||
answer: "Neon Genesis Evangelion"
|
|
||||||
template: "whatis"
|
|
||||||
|
|
||||||
- title: "Which of these bands performed 'Again', the first opening of Fullmetal Alchemist: Brotherhood?"
|
|
||||||
answer: 4
|
|
||||||
choices:
|
|
||||||
- "Asian Kung-Fu Generation"
|
|
||||||
- "Flow"
|
|
||||||
- "Scandal"
|
|
||||||
- "YUI"
|
|
||||||
template: "multiplechoice"
|
|
||||||
|
|
||||||
- title: "This artist performed 'Gurenge', the first opening of Demon Slayer: Kimetsu no Yaiba, which became a massive hit in Japan."
|
|
||||||
time-limit: 25
|
|
||||||
answer: "LiSA"
|
|
||||||
template: "whatis"
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
questions:
|
|
||||||
- title: "In Code Geass, Lelouch's Geass ability compels anyone who makes direct eye contact with him to do this."
|
|
||||||
time-limit: 20
|
|
||||||
answer: "Obey any one order he gives them"
|
|
||||||
template: "whatis"
|
|
||||||
|
|
||||||
- title: "At the end of Madoka Magica, Madoka's wish rewrites the laws of the universe to do what?"
|
|
||||||
answer: 2
|
|
||||||
choices:
|
|
||||||
- "Destroy all witches that have ever existed and will ever exist"
|
|
||||||
- "Erase all witches before they are born, taking herself out of existence"
|
|
||||||
- "Turn every magical girl back into a normal human"
|
|
||||||
- "Destroy Kyubey and the incubator race"
|
|
||||||
template: "multiplechoice"
|
|
||||||
|
|
||||||
- title: "In Fullmetal Alchemist: Brotherhood, Edward and Alphonse discover their mother was not actually revived — what they created during their human transmutation was this."
|
|
||||||
time-limit: 30
|
|
||||||
answer: "A soulless body / failed homunculus (not their mother)"
|
|
||||||
template: "whatis"
|
|
||||||
|
|
||||||
- title: "Which of these correctly describes the twist at the end of Assassination Classroom?"
|
|
||||||
answer: 3
|
|
||||||
choices:
|
|
||||||
- "Koro-sensei was always a government weapon and willingly lets himself be killed"
|
|
||||||
- "The students refuse to kill Koro-sensei and he escapes to space"
|
|
||||||
- "Koro-sensei asks his students to be the ones to kill him as his final wish"
|
|
||||||
- "Nagisa kills the minister of defense and Koro-sensei is freed"
|
|
||||||
template: "multiplechoice"
|
|
||||||
|
|
||||||
- title: "In Gurren Lagann, Simon discovers that the key to piloting Lagann is not a special device but actually this."
|
|
||||||
time-limit: 25
|
|
||||||
answer: "His own drill / fighting spirit (spiral power)"
|
|
||||||
template: "whatis"
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
questions:
|
|
||||||
- title: "This is the name of the signature technique Naruto Uzumaki uses to create physical copies of himself."
|
|
||||||
time-limit: 15
|
|
||||||
answer: "Shadow Clone Jutsu"
|
|
||||||
template: "whatis"
|
|
||||||
|
|
||||||
- title: "In Dragon Ball Z, Goku achieved this transformation for the first time during his battle against Frieza on Namek."
|
|
||||||
time-limit: 20
|
|
||||||
answer: "Super Saiyan"
|
|
||||||
template: "whatis"
|
|
||||||
|
|
||||||
- title: "Which of these is the name of Ichigo Kurosaki's Zanpakuto in Bleach?"
|
|
||||||
answer: 3
|
|
||||||
choices:
|
|
||||||
- "Zangetsu"
|
|
||||||
- "Senbonzakura"
|
|
||||||
- "Tensa Zangetsu"
|
|
||||||
- "Ryujin Jakka"
|
|
||||||
template: "multiplechoice"
|
|
||||||
|
|
||||||
- title: "In Hunter x Hunter, this is the name of the system of power that allows users to manipulate their life energy."
|
|
||||||
time-limit: 25
|
|
||||||
answer: "Nen"
|
|
||||||
template: "whatis"
|
|
||||||
|
|
||||||
- title: "Which of these Devil Fruits did Monkey D. Luffy eat, giving him his rubber powers?"
|
|
||||||
answer: 2
|
|
||||||
choices:
|
|
||||||
- "Mera Mera no Mi"
|
|
||||||
- "Gomu Gomu no Mi"
|
|
||||||
- "Hana Hana no Mi"
|
|
||||||
- "Bara Bara no Mi"
|
|
||||||
template: "multiplechoice"
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
questions:
|
|
||||||
- title: "This animation studio, co-founded by Hayao Miyazaki, produced Spirited Away, My Neighbor Totoro, and Princess Mononoke."
|
|
||||||
time-limit: 15
|
|
||||||
answer: "Studio Ghibli"
|
|
||||||
template: "whatis"
|
|
||||||
|
|
||||||
- title: "Which studio produced Fullmetal Alchemist: Brotherhood, Sword of the Stranger, and Mob Psycho 100?"
|
|
||||||
answer: 1
|
|
||||||
choices:
|
|
||||||
- "Bones"
|
|
||||||
- "Madhouse"
|
|
||||||
- "White Fox"
|
|
||||||
- "A-1 Pictures"
|
|
||||||
template: "multiplechoice"
|
|
||||||
|
|
||||||
- title: "This director is known for helming Cowboy Bebop, Samurai Champloo, and Space Dandy."
|
|
||||||
time-limit: 25
|
|
||||||
answer: "Shinichiro Watanabe"
|
|
||||||
template: "whatis"
|
|
||||||
|
|
||||||
- title: "Which studio is responsible for the long-running adaptations of One Piece and Dragon Ball Super?"
|
|
||||||
answer: 3
|
|
||||||
choices:
|
|
||||||
- "Pierrot"
|
|
||||||
- "Sunrise"
|
|
||||||
- "Toei Animation"
|
|
||||||
- "TMS Entertainment"
|
|
||||||
template: "multiplechoice"
|
|
||||||
|
|
||||||
- title: "This legendary animator, known as 'the god of manga', created Astro Boy and is considered the father of modern anime and manga."
|
|
||||||
time-limit: 20
|
|
||||||
answer: "Osamu Tezuka"
|
|
||||||
template: "whatis"
|
|
||||||
|
Before Width: | Height: | Size: 961 KiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 256 KiB |
|
Before Width: | Height: | Size: 1.8 MiB |
@@ -1,24 +0,0 @@
|
|||||||
settings:
|
|
||||||
increment: 100 # how much each tier increases by
|
|
||||||
start: 100 # starting amount see tier's comment
|
|
||||||
tiers: 5 # 5 tiers 100, 200, 300, 400, 500 based on above settings
|
|
||||||
dailyDouble:
|
|
||||||
enabled: true # should daily double be enabled?
|
|
||||||
minQuestions: 7 # how many questions need to be answered before a daily double can appear?
|
|
||||||
count: 2 # how many daily doubles should there be?
|
|
||||||
categories: # the name of each category should correspond to a yaml file with the same name
|
|
||||||
- name: shounen # name must be alphanumeric, cannot start with a number or contain special characters "-" and "." are ok if they are not at the beginning
|
|
||||||
displayName: "Shounen" # if blank will use name
|
|
||||||
image: "anime/assets/14018-3193093789.gif" # if set will display image instead of name, categories are referenced by name which is required
|
|
||||||
- name: openings
|
|
||||||
displayName: "Openings" # if blank will use name
|
|
||||||
- name: sadness
|
|
||||||
displayName: "Sadness" # if blank will use name
|
|
||||||
- name: random
|
|
||||||
displayName: Random # if blank will use name
|
|
||||||
- name: you-would-have-though
|
|
||||||
displayName: "You would have\nthought" # if blank will use name
|
|
||||||
- name: wtf-is-that
|
|
||||||
displayName: "Wtf is that!?" # if blank will use name
|
|
||||||
- name: owo
|
|
||||||
displayName: "owo" # if blank will use name
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
questions: # expects a list equal to the tier
|
|
||||||
- title: "Name at least 10 of the characters here"
|
|
||||||
time-limit: 60 # If omitted there is no time limit
|
|
||||||
answer: 10
|
|
||||||
image: "anime/assets/shounen_name_characters.png"
|
|
||||||
template: "one-image" # template to use
|
|
||||||
display-answer: true # displays the correct answer before returning to the main screen
|
|
||||||
- title: "What anime is this?"
|
|
||||||
time-limit: 30 # If omitted there is no time limit
|
|
||||||
answer: "steins;gate"
|
|
||||||
imageA: "anime/assets/beer.jpg"
|
|
||||||
imageB: "anime/assets/gate.jpg"
|
|
||||||
display-answer: true # displays the correct answer before returning to the main screen
|
|
||||||
template: "imageword" # template to use
|
|
||||||
- title: "What is 2+2"
|
|
||||||
answer: 2 # positon of correct answer
|
|
||||||
choices:
|
|
||||||
- "22"
|
|
||||||
- "4" # this is 2
|
|
||||||
- "9000"
|
|
||||||
- "-4"
|
|
||||||
- "wack"
|
|
||||||
template: "multiplechoice"
|
|
||||||
- title: "Who directed the groundbreaking film 'Akira',\nwhich helped introduce anime to Western audiences?"
|
|
||||||
time-limit: 10 # If omitted there is no time limit
|
|
||||||
answer: "Katsuhiro Otomo"
|
|
||||||
template: "whatis" # template to use
|
|
||||||
display-answer: true # displays the correct answer before returning to the main screen
|
|
||||||
- title: "What is this?"
|
|
||||||
answer: "Bunny shit"
|
|
||||||
video: "anime/assets/bunny.ogv"
|
|
||||||
start: 4
|
|
||||||
playFor: 3
|
|
||||||
template: "whatvideo" # template to use
|
|
||||||
display-answer: true # displays the correct answer before returning to the main screen
|
|
||||||
|
After Width: | Height: | Size: 613 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
@@ -1,290 +0,0 @@
|
|||||||
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 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 function buildBoard(frame, path)
|
|
||||||
local data = loader:new(path)
|
|
||||||
board, question, dailydouble = frame:newFrame(), frame:newFrame(), frame: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()
|
|
||||||
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
|
|
||||||
|
|
||||||
return {
|
|
||||||
buildBoard = buildBoard
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
function love.conf(t)
|
function love.conf(t)
|
||||||
t.identity = nil -- The name of the save directory (string)
|
t.identity = "Jeopardy"
|
||||||
t.version = "11.5" -- The LOVE version this game was made for (string)
|
t.version = "11.5" -- The LOVE version this game was made for (string)
|
||||||
t.console = true -- Attach a console (boolean, Windows only)
|
t.console = true -- Attach a console (boolean, Windows only)
|
||||||
|
|
||||||
t.window.title = "GuiManagerTest" -- The window title (string)
|
t.window.title = "Jeopardy" -- The window title (string)
|
||||||
t.window.icon = nil -- Filepath to an image to use as the window's icon (string)
|
t.window.icon = nil -- Filepath to an image to use as the window's icon (string)
|
||||||
t.window.width = 1920 -- The window width (number)
|
t.window.width = 1920 -- The window width (number)
|
||||||
t.window.height = 1080 -- The window height (number)
|
t.window.height = 1080 -- The window height (number)
|
||||||
@@ -13,7 +13,7 @@ function love.conf(t)
|
|||||||
t.window.minheight = 1 -- Minimum window height if the window is resizable (number)
|
t.window.minheight = 1 -- Minimum window height if the window is resizable (number)
|
||||||
t.window.fullscreen = false -- Enable fullscreen (boolean)
|
t.window.fullscreen = false -- Enable fullscreen (boolean)
|
||||||
t.window.fullscreentype = "desktop" -- Standard fullscreen or desktop fullscreen mode (string)
|
t.window.fullscreentype = "desktop" -- Standard fullscreen or desktop fullscreen mode (string)
|
||||||
t.window.vsync = false -- Enable vertical sync (boolean)
|
t.window.vsync = true -- Enable vertical sync (boolean)
|
||||||
t.window.fsaa = 4 -- The number of samples to use with multi-sampled antialiasing (number)
|
t.window.fsaa = 4 -- The number of samples to use with multi-sampled antialiasing (number)
|
||||||
t.window.display = 1 -- Index of the monitor to show the window in (number)
|
t.window.display = 1 -- Index of the monitor to show the window in (number)
|
||||||
t.window.highdpi = true -- Enable high-dpi mode for the window on a Retina display (boolean)
|
t.window.highdpi = true -- Enable high-dpi mode for the window on a Retina display (boolean)
|
||||||
@@ -29,7 +29,7 @@ function love.conf(t)
|
|||||||
t.modules.keyboard = true -- Enable the keyboard module (boolean)
|
t.modules.keyboard = true -- Enable the keyboard module (boolean)
|
||||||
t.modules.math = true -- Enable the math module (boolean)
|
t.modules.math = true -- Enable the math module (boolean)
|
||||||
t.modules.mouse = true -- Enable the mouse module (boolean)
|
t.modules.mouse = true -- Enable the mouse module (boolean)
|
||||||
t.modules.physics = true -- Enable the physics module (boolean)
|
t.modules.physics = false -- Enable the physics module (boolean)
|
||||||
t.modules.sound = true -- Enable the sound module (boolean)
|
t.modules.sound = true -- Enable the sound module (boolean)
|
||||||
t.modules.system = true -- Enable the system module (boolean)
|
t.modules.system = true -- Enable the system module (boolean)
|
||||||
t.modules.timer = true -- Enable the timer module (boolean)
|
t.modules.timer = true -- Enable the timer module (boolean)
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ function loader:new(path_or_file)
|
|||||||
else
|
else
|
||||||
local category = yaml.parse(link)
|
local category = yaml.parse(link)
|
||||||
c.index.categories[i].questions = category.questions
|
c.index.categories[i].questions = category.questions
|
||||||
|
c.index.categories[i].global = category.global or {}
|
||||||
|
c.index.categories[i].cosmetics = category.cosmetics or {}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return c
|
return c
|
||||||
|
|||||||
@@ -1,40 +1,48 @@
|
|||||||
local gui, color, theme, utils, board, yaml, loader, scoreUpdater
|
|
||||||
|
|
||||||
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
|
||||||
GLOBAL, THREAD = require("multi.integration.loveManager"):init()
|
GLOBAL, THREAD = require("multi.integration.loveManager"):init()
|
||||||
|
|
||||||
gui = require("gui")
|
local gui = require("gui")
|
||||||
color = require("gui.core.color")
|
local color = require("gui.core.color")
|
||||||
theme = require("gui.core.theme")
|
local title = require("menus.title")
|
||||||
utils = require("utils")
|
local menu = require("gui.core.menus")
|
||||||
board = require("board")
|
|
||||||
yaml = require("yaml")
|
color.indexColor("bg","#2b348b")
|
||||||
loader = require("loader")
|
color.indexColor("tile_bg","#5459e4")
|
||||||
|
color.indexColor("header_tile","#2a2e91")
|
||||||
|
color.indexColor("status_font", "#e4b82a")
|
||||||
|
color.indexColor("title_font","#b16d24")
|
||||||
|
color.indexColor("question_bg","#363ac8")
|
||||||
|
color.indexColor("tile_font","#ffffff")
|
||||||
|
color.indexColor("header_font","#fef6eeda")
|
||||||
|
|
||||||
require("gui.addons")
|
require("gui.addons")
|
||||||
|
|
||||||
title = require("menus.title")
|
gui:setHotKey({"f11"})(function()
|
||||||
|
fullscreen, fstype = love.window.getFullscreen()
|
||||||
|
love.window.setFullscreen(not fullscreen, "desktop")
|
||||||
|
end)
|
||||||
|
|
||||||
|
local old = multi.error
|
||||||
|
|
||||||
|
multi.error = function(...)
|
||||||
|
old(...)
|
||||||
|
os.exit()
|
||||||
|
end
|
||||||
|
|
||||||
function love.load()
|
function love.load()
|
||||||
|
love.filesystem.setIdentity("jeopardy")
|
||||||
|
success = love.filesystem.createDirectory("")
|
||||||
gui:cacheImage({"assets/images/checked.png","assets/images/unchecked.png","assets/images/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
|
||||||
|
|
||||||
local bg = gui:newFrame()
|
local bg = gui:newImageLabel("assets/images/background.png")
|
||||||
bg:fullFrame()
|
bg:fullFrame()
|
||||||
bg.color = color.new("#242f9b")
|
|
||||||
|
|
||||||
require("menus.menus").init(bg)
|
menu.init(bg)
|
||||||
|
|
||||||
title:visible(true)
|
title:visible(true)
|
||||||
|
|
||||||
bg:OnUpdate(function(self, dt)
|
|
||||||
if self.__blur then
|
|
||||||
-- pulse the blur between 2 and 12
|
|
||||||
local t = love.timer.getTime()
|
|
||||||
self:setBlurRadius(7 + 5 * math.sin(t * 2))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.update(dt)
|
function love.update(dt)
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ local theme = require("gui.core.theme")
|
|||||||
local fmt = require("fmt")
|
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 menu = require("menus.menus")
|
local menu = require("gui.core.menus")
|
||||||
|
|
||||||
local timesup = love.audio.newSource("assets/sounds/timesup.mp3", "static")
|
local timesup = love.audio.newSource("assets/sounds/timesup.mp3", "static")
|
||||||
local double = love.audio.newSource("assets/sounds/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()
|
local scoreUpdater = gui:getProcessor():newProcessor("score-updater")
|
||||||
|
local qUpdater = gui:getProcessor():newProcessor("question-updater")
|
||||||
|
|
||||||
local activePlayer
|
local activePlayer
|
||||||
local playerList = {}
|
local playerList = {}
|
||||||
@@ -50,14 +51,6 @@ local dd_enabled = false
|
|||||||
local applied_dd = false
|
local applied_dd = false
|
||||||
local board, question
|
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)
|
local function pickUniqueIndices(t, count)
|
||||||
assert(#t >= count, "Not enough elements to pick " .. count .. " unique items")
|
assert(#t >= count, "Not enough elements to pick " .. count .. " unique items")
|
||||||
|
|
||||||
@@ -98,22 +91,32 @@ function applyDD()
|
|||||||
local dd_list = {}
|
local dd_list = {}
|
||||||
local dds = {pickFiltered(board.children, dd_count)}
|
local dds = {pickFiltered(board.children, dd_count)}
|
||||||
for i,v in pairs(dds) do
|
for i,v in pairs(dds) do
|
||||||
print(i,v)
|
|
||||||
v.isDouble = true
|
v.isDouble = true
|
||||||
end
|
end
|
||||||
applied_dd = true
|
applied_dd = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local qUpdater = gui:getProcessor():newProcessor("question-updater")
|
|
||||||
qUpdater.Start()
|
|
||||||
|
|
||||||
function LoadTemplate(name, path)
|
function LoadTemplate(name, path)
|
||||||
|
if love.filesystem.getInfo(path .."/templates/" .. name .. ".lua") then
|
||||||
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")
|
data = love.filesystem.read(path .."/templates/" .. name .. ".lua")
|
||||||
|
elseif love.filesystem.getInfo("templates/" .. name .. ".lua") then
|
||||||
|
data = love.filesystem.read("templates/" .. name .. ".lua")
|
||||||
|
else
|
||||||
|
print("Error Loading Template: " .. name, path)
|
||||||
|
gui:newMessageBox({
|
||||||
|
title = "Error!",
|
||||||
|
message = "Unable to load template: " .. name,
|
||||||
|
buttons = { "Yes", "No" },
|
||||||
|
onChoice = function(label, idx)
|
||||||
|
if label == "Yes" then
|
||||||
|
doCallback(selected)
|
||||||
|
pickerWindow.visible = false
|
||||||
|
pickerWindow:setTag("visual")
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local template, err = loadstring(data)
|
local template, err = loadstring(data)
|
||||||
@@ -163,22 +166,96 @@ function LoadTemplate(name, path)
|
|||||||
return isoTemplate()
|
return isoTemplate()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function manageCosmetics(frame, cosmetics)
|
||||||
|
if cosmetics["bg-img"] then
|
||||||
|
frame:setImage(cosmetics["bg-img"])
|
||||||
|
else
|
||||||
|
frame:setImage("assets/images/background.png")
|
||||||
|
end
|
||||||
|
if type(cosmetics.colors) == "table" then
|
||||||
|
for i,v in pairs(cosmetics.colors) do
|
||||||
|
color.reindexColor((i:gsub("-","_")),v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function gui:cleanup()
|
||||||
|
for i = #self.children, 1, -1 do
|
||||||
|
self.children[i]:destroy()
|
||||||
|
end
|
||||||
|
self.children = {}
|
||||||
|
completed_questions = completed_questions + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local reset = boardUpdater:newConnection()
|
||||||
|
|
||||||
|
local default_text = "Pick a Category"
|
||||||
|
|
||||||
function Menu(frame, path)
|
function Menu(frame, path)
|
||||||
local qframe = frame:newFrame(0, 0, 0, 0, .2, .05, .75, .9)
|
if path:match(".zip") then
|
||||||
qframe.color = color.new("#060ee9")
|
-- local basename = path:match("([^/\\]+)$")
|
||||||
local scoreboard = ScoreBoard(frame, 0, 0, 0, 0, .015, .05, .170, .9)
|
print(path)
|
||||||
|
local success = love.filesystem.mount(path, "quiz", true)
|
||||||
|
if not success then
|
||||||
|
gui:newMessageBox({
|
||||||
|
title = "Return to the main menu?",
|
||||||
|
message = "Couldn't load file: " .. path,
|
||||||
|
buttons = { "Return", "Quit" },
|
||||||
|
onChoice = function(label, idx)
|
||||||
|
if label == "Return" then
|
||||||
|
return menu.getMenu("title"):visible(true)
|
||||||
|
else
|
||||||
|
os.exit()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
path = "quiz"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Start the processors now
|
||||||
|
boardUpdater.Start()
|
||||||
|
qUpdater.Start()
|
||||||
|
scoreUpdater.Start()
|
||||||
|
|
||||||
|
local scoreboard = ScoreBoard(frame, 0, 0, 0, 0, .06, .1, .170, .8)
|
||||||
|
|
||||||
|
local qframe = frame:newFrame(0, 0, 0, 0, .24, .1, .70, .8)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
boardUpdater:newThread(function()
|
||||||
|
local test = function()
|
||||||
|
return label.text ~= ""
|
||||||
|
end
|
||||||
|
while true do
|
||||||
|
thread.hold(test)
|
||||||
|
label:centerFont()
|
||||||
|
label:fitFont(nil, nil, {scale = 2/3})
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
local data = loader:new(path)
|
local data = loader:new(path)
|
||||||
board, question, dailydouble = qframe:newFrame(), qframe:newFrame(), qframe:newImageLabel("assets/images/double.jpg")
|
board, question, dailydouble = qframe:newFrame(), qframe:newFrame(), qframe:newImageLabel("assets/images/double.jpg")
|
||||||
index = data.index
|
index = data.index
|
||||||
|
|
||||||
|
local cosmetics = index.cosmetics or {}
|
||||||
|
manageCosmetics(frame, cosmetics)
|
||||||
|
|
||||||
board:fullFrame()
|
board:fullFrame()
|
||||||
question:fullFrame()
|
question:fullFrame()
|
||||||
dailydouble:fullFrame()
|
dailydouble:fullFrame()
|
||||||
|
|
||||||
dailydouble.visible = false
|
dailydouble.visible = false
|
||||||
question.visible = false
|
question.visible = false
|
||||||
question.color = color.new("#060ce9")
|
question.color = color.question_bg
|
||||||
|
|
||||||
local tiers = index.settings.tiers or 5
|
local tiers = index.settings.tiers or 5
|
||||||
local start = index.settings.start or 100
|
local start = index.settings.start or 100
|
||||||
@@ -190,6 +267,29 @@ function Menu(frame, path)
|
|||||||
min_questions = dd.minQuestions
|
min_questions = dd.minQuestions
|
||||||
dd_count = dd.count
|
dd_count = dd.count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local autoreveal = false
|
||||||
|
if index.dev and index.dev.enabled then
|
||||||
|
if index.dev["auto-reveal"] then
|
||||||
|
autoreveal = true
|
||||||
|
end
|
||||||
|
if type(index.dev.players) == "table" then
|
||||||
|
for i,v in ipairs(index.dev.players) do
|
||||||
|
if type(v) == "string" then
|
||||||
|
scoreboard:AddPlayer(v, 0)
|
||||||
|
elseif type(v) == "table" then
|
||||||
|
scoreboard:AddPlayer(v.name, v.score, v.icon)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
reset(function()
|
||||||
|
question:cleanup()
|
||||||
|
manageCosmetics(frame, cosmetics, true)
|
||||||
|
label.text = default_text
|
||||||
|
end)
|
||||||
|
|
||||||
for cat,v in pairs(index.categories) do
|
for cat,v in pairs(index.categories) do
|
||||||
local c
|
local c
|
||||||
if v.image then
|
if v.image then
|
||||||
@@ -197,26 +297,30 @@ function Menu(frame, path)
|
|||||||
else
|
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 = 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.align = gui.ALIGN_CENTER
|
||||||
c.textColor = color.new("#ffffff")
|
c.textColor = color.header_font
|
||||||
c.color = color.new("#060ce9")
|
c.color = color.header_tile
|
||||||
end
|
end
|
||||||
|
|
||||||
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/images/placeholder.jpg")
|
if not autoreveal then
|
||||||
img.visibility = 0
|
img = c:newImageButton("assets/images/placeholder.jpg")
|
||||||
|
img.visibility = 0
|
||||||
|
|
||||||
img:OnReleased(function(self)
|
img:OnReleased(function(self)
|
||||||
self.visible = false
|
self.visible = false
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
img:fullFrame()
|
||||||
|
end
|
||||||
|
|
||||||
img:fullFrame()
|
|
||||||
table.insert(manage,c)
|
table.insert(manage,c)
|
||||||
|
|
||||||
for tier = 1,tiers do
|
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))
|
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.textColor = color.tile_font
|
||||||
t.align = gui.ALIGN_CENTER
|
t.align = gui.ALIGN_CENTER
|
||||||
t.color = color.new("#060ce9")
|
t.color = color.tile_bg
|
||||||
t.category = v.name
|
t.category = v.name
|
||||||
t.index = tier
|
t.index = tier
|
||||||
t.price = start + inc*(tier-1)
|
t.price = start + inc*(tier-1)
|
||||||
@@ -226,8 +330,22 @@ function Menu(frame, path)
|
|||||||
applyDD() -- check and run DD if conditions meet
|
applyDD() -- check and run DD if conditions meet
|
||||||
end
|
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
|
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 globals = index.categories[cat].global
|
||||||
|
if not globals then
|
||||||
|
globals = {}
|
||||||
|
end
|
||||||
local q = index.categories[cat].questions[self.index]
|
local q = index.categories[cat].questions[self.index]
|
||||||
|
if not q then return end
|
||||||
|
label.text = t.category .. ": " .. t.price
|
||||||
|
local mt = debug.getmetatable(q)
|
||||||
|
if mt then
|
||||||
|
mt.__metatable = nil
|
||||||
|
end
|
||||||
|
setmetatable(q, {__index = globals})
|
||||||
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
|
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
|
||||||
|
if q.cosmetics then
|
||||||
|
manageCosmetics(frame, q.cosmetics)
|
||||||
|
end
|
||||||
self.textVisibility = 0
|
self.textVisibility = 0
|
||||||
local template = LoadTemplate(q.template, path)
|
local template = LoadTemplate(q.template, path)
|
||||||
question.visible = true
|
question.visible = true
|
||||||
@@ -255,7 +373,8 @@ function Menu(frame, path)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
local finished = false
|
local finished = false
|
||||||
template.index(question, q, function(ans)
|
template.index(question, q, function(ans, m)
|
||||||
|
local m = m or 1
|
||||||
if finished then return end
|
if finished then return end
|
||||||
player = GetActivePlayer()
|
player = GetActivePlayer()
|
||||||
if tm then
|
if tm then
|
||||||
@@ -263,17 +382,17 @@ function Menu(frame, path)
|
|||||||
end
|
end
|
||||||
stop = true
|
stop = true
|
||||||
if ans then
|
if ans then
|
||||||
player:Add(self.price*mul)
|
player:Add((self.price*mul)*m)
|
||||||
finished = true
|
finished = true
|
||||||
question.visible = false
|
question.visible = false
|
||||||
question:cleanup()
|
reset:Fire()
|
||||||
elseif ans == false then
|
elseif ans == false then
|
||||||
player:Add(-self.price*mul)
|
player:Add(-self.price*mul)
|
||||||
player = GetNextPlayer()
|
player = GetNextPlayer()
|
||||||
else
|
else
|
||||||
finished = true
|
finished = true
|
||||||
question.visible = false
|
question.visible = false
|
||||||
question:cleanup()
|
reset:Fire()
|
||||||
end -- nil is a valid option where you weren't right or wrong, you just skipped
|
end -- nil is a valid option where you weren't right or wrong, you just skipped
|
||||||
self.text = ""
|
self.text = ""
|
||||||
end)
|
end)
|
||||||
@@ -296,8 +415,7 @@ function Menu(frame, path)
|
|||||||
return background
|
return background
|
||||||
end
|
end
|
||||||
|
|
||||||
scoreUpdater = gui:getProcessor():newProcessor("score-updater")
|
|
||||||
scoreUpdater.Start()
|
|
||||||
|
|
||||||
function GetActivePlayer()
|
function GetActivePlayer()
|
||||||
if not activePlayer then return end
|
if not activePlayer then return end
|
||||||
@@ -407,7 +525,7 @@ function ScoreBoard(frame, x, y, w, h, sx, sy, sw, sh)
|
|||||||
function scoreboard:AddPlayer(name, score, icon)
|
function scoreboard:AddPlayer(name, score, icon)
|
||||||
local player = {
|
local player = {
|
||||||
Name = name,
|
Name = name,
|
||||||
Score = score,
|
Score = score or 0,
|
||||||
Icon = icon,
|
Icon = icon,
|
||||||
UUID = multi.generate_uuid7(),
|
UUID = multi.generate_uuid7(),
|
||||||
Add = function(self, amt)
|
Add = function(self, amt)
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
local gui = require("gui")
|
local gui = require("gui")
|
||||||
local color = require("gui.core.color")
|
local color = require("gui.core.color")
|
||||||
local menu = require("menus.menus")
|
local menu = require("gui.core.menus")
|
||||||
-- local proc = gui:getProcessor():newProcessor("settings")
|
-- local proc = gui:getProcessor():newProcessor("settings")
|
||||||
|
|
||||||
function Menu(frame)
|
function Menu(frame)
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
local gui = require("gui")
|
local gui = require("gui")
|
||||||
local color = require("gui.core.color")
|
local color = require("gui.core.color")
|
||||||
local menu = require("menus.menus")
|
local menu = require("gui.core.menus")
|
||||||
local proc = gui:getProcessor():newProcessor("main-title")
|
local proc = gui:getProcessor():newProcessor("main-title")
|
||||||
|
|
||||||
|
local APP_VERSION = love.filesystem.read("version.txt")
|
||||||
|
|
||||||
local board = require("menus.board")
|
local board = require("menus.board")
|
||||||
|
|
||||||
function Menu(frame)
|
function Menu(frame)
|
||||||
local background = frame:newImageLabel("assets/images/background.jpg")
|
local background = frame:newImageLabel("assets/images/background.jpg")
|
||||||
background:fullFrame()
|
background:fullFrame()
|
||||||
local title = frame:newTextLabel("Jeopardy",0,0,0,0,0,.1,1,.25)
|
local title = background:newTextLabel("Jeopardy",0,0,0,0,0,.1,1,.25)
|
||||||
title:setFont("assets/fonts/gyparody.ttf",300)
|
title:setFont("assets/fonts/gyparody.ttf",300)
|
||||||
|
|
||||||
title:setShader(gui.SHADERS.vignette,{
|
title:setShader(gui.SHADERS.vignette,{
|
||||||
@@ -18,7 +20,7 @@ function Menu(frame)
|
|||||||
|
|
||||||
title.align = gui.ALIGN_CENTER
|
title.align = gui.ALIGN_CENTER
|
||||||
title.visibility = 0
|
title.visibility = 0
|
||||||
title.textColor = color.new("#b16d24")
|
title.textColor = color.title_font
|
||||||
title.drawBorder = false
|
title.drawBorder = false
|
||||||
|
|
||||||
proc:newThread(function()
|
proc:newThread(function()
|
||||||
@@ -62,10 +64,44 @@ function Menu(frame)
|
|||||||
},play,settings,quit)
|
},play,settings,quit)
|
||||||
|
|
||||||
play:OnReleased(function()
|
play:OnReleased(function()
|
||||||
background.visible = false
|
if love.filesystem.getInfo("quiz") then
|
||||||
menu.getMenu("board"):visible(true,"anime")
|
menu.getMenu("board"):visible(true, "quiz")
|
||||||
|
return
|
||||||
|
else
|
||||||
|
gui:newFilePicker("File picker test",nil, {".zip"}, function(file)
|
||||||
|
menu.getMenu("board"):visible(true, file:gsub("\\","/"):gsub(love.filesystem.getSaveDirectory(),""):sub(2,-1))
|
||||||
|
end)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
quit:OnReleased(function()
|
||||||
|
local f = frame:newFrame()
|
||||||
|
f:fullFrame()
|
||||||
|
f.visibility = .8
|
||||||
|
f.color = color.black
|
||||||
|
local cm = menu.getCurrentMenu()
|
||||||
|
cm:setTag("visual")
|
||||||
|
quit:setShader()
|
||||||
|
gui:newMessageBox({
|
||||||
|
title = "Confirm",
|
||||||
|
message = "Are you sure you want to exit the game?",
|
||||||
|
buttons = { "Yes", "No" },
|
||||||
|
onChoice = function(label, idx)
|
||||||
|
if label == "Yes" then os.exit() end
|
||||||
|
cm:removeTag("visual")
|
||||||
|
f:destroy()
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
|
||||||
|
local version = frame:newTextLabel("Version: " .. APP_VERSION, -150,-30, 150, 30, 1, 1)
|
||||||
|
thread:newThread(function()
|
||||||
|
thread.skip(2)
|
||||||
|
version:fitFont()
|
||||||
|
end)
|
||||||
|
version.textColor = color.new("#b16d24")
|
||||||
|
version.visibility = 0
|
||||||
|
|
||||||
return background
|
return background
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
:: Read the first line of version.txt and assign it to the MY_VERSION variable
|
||||||
|
for /f "usebackq delims=" %%i in ("version.txt") do (
|
||||||
|
set "userInput=%%i"
|
||||||
|
goto :done
|
||||||
|
)
|
||||||
|
|
||||||
|
:done
|
||||||
|
"C:\Program Files\7-Zip\7z.exe" a -tzip game.love templates version.txt assets multi\integration\loveManager multi\integration\sharedExtensions multi\init.lua gui menus conf.lua fmt.lua loader.lua main.lua utils.lua yaml.lua
|
||||||
|
rd /s /q "bin\%userInput%"
|
||||||
|
if not exist "bin\%userInput%" mkdir "bin\%userInput%"
|
||||||
|
copy /b love\love.exe + game.love "bin\%userInput%\Jeopardy.exe"
|
||||||
|
copy /b love\love.dll "bin\%userInput%\love.dll"
|
||||||
|
copy /b lovel\lua51.dll "bin\%userInput%\lua51.dll"
|
||||||
|
copy /b love\mpg123.dll "bin\%userInput%\mpg123.dll"
|
||||||
|
copy /b love\msvcp120.dll "bin\%userInput%\msvcp120.dll"
|
||||||
|
copy /b love\msvcr120.dll "bin\%userInput%\msvcr120.dll"
|
||||||
|
copy /b love\OpenAL32.dll "bin\%userInput%\OpenAL32.dll"
|
||||||
|
copy /b love\SDL2.dll "bin\%userInput%\SDL2.dll"
|
||||||
|
copy /b love\license.txt "bin\%userInput%\license.txt"
|
||||||
|
Before Width: | Height: | Size: 29 KiB |
@@ -9,8 +9,8 @@ local function index(window, q, callback)
|
|||||||
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
||||||
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("#363ac8")
|
||||||
label.borderColor = color.new("#060ce9")
|
label.borderColor = color.new("#363ac8")
|
||||||
|
|
||||||
if not q.imageA or q.imageA == "" then
|
if not q.imageA or q.imageA == "" then
|
||||||
error("Missing 'imageA' field for question!")
|
error("Missing 'imageA' field for question!")
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ local function index(window, q, callback)
|
|||||||
label = window:newTextLabel(" " ..q.title.. " ",noOf(0,0,1,.3))
|
label = window:newTextLabel(" " ..q.title.. " ",noOf(0,0,1,.3))
|
||||||
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("#363ac8")
|
||||||
label:setFont(50)
|
label:setFont(50)
|
||||||
choices = window:newFrame(noOf(0,.3,1,.7))
|
choices = window:newFrame(noOf(0,.3,1,.7))
|
||||||
choices.color = color.new("#060ce9")
|
choices.color = color.new("#363ac8")
|
||||||
|
|
||||||
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))
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ local function index(window, q, callback)
|
|||||||
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
||||||
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("#363ac8")
|
||||||
if not q.image or q.image == "" then
|
if not q.image or q.image == "" then
|
||||||
error("Missing 'image' field for question!")
|
error("Missing 'image' field for question!")
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ local function index(window, q, callback)
|
|||||||
label.align = ALIGN_CENTER
|
label.align = ALIGN_CENTER
|
||||||
label:fullFrame()
|
label:fullFrame()
|
||||||
label.textColor = color.white
|
label.textColor = color.white
|
||||||
label.color = color.new("#060ce9")
|
label.color = color.new("#363ac8")
|
||||||
local correct = window:newTextButton("Correct",0,-200,0,100,0,1,.5)
|
local correct = window:newTextButton("Correct",0,-200,0,100,0,1,.5)
|
||||||
correct.color = color.new("#52b11b")
|
correct.color = color.new("#52b11b")
|
||||||
local wrong = window:newTextButton("Wrong",0,-200,0,100,.5,1,.5)
|
local wrong = window:newTextButton("Wrong",0,-200,0,100,.5,1,.5)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ local function index(window, q, callback)
|
|||||||
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
||||||
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("#363ac8")
|
||||||
imageHolder = frame:newImageButton("assets/images/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)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ local function index(window, q, callback)
|
|||||||
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
||||||
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("#363ac8")
|
||||||
local holder = frame:newFrame(-300, -200, 600, 400, .5, .5)
|
local holder = frame:newFrame(-300, -200, 600, 400, .5, .5)
|
||||||
holder:centerX(true)
|
holder:centerX(true)
|
||||||
holder:centerY(true)
|
holder:centerY(true)
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
1.0.1
|
||||||