mirror of
https://github.com/SashLilac/cambridge.git
synced 2025-04-19 13:32:56 -05:00
Hopefully this is the folder support
it better be
This commit is contained in:
parent
d72f05d0de
commit
2384ceb3bf
41
load/bgm.lua
41
load/bgm.lua
@ -2,38 +2,46 @@ bgm = {
|
|||||||
credit_roll = {
|
credit_roll = {
|
||||||
gm3 = love.audio.newSource("res/bgm/tgm_credit_roll.mp3", "stream"),
|
gm3 = love.audio.newSource("res/bgm/tgm_credit_roll.mp3", "stream"),
|
||||||
},
|
},
|
||||||
pacer_test = love.audio.newSource("res/bgm/pacer_test.mp3", "stream"),
|
pacer_test = love.audio.newSource("res/bgm/pacer_test.mp3", "stream")
|
||||||
}
|
}
|
||||||
|
|
||||||
local current_bgm = nil
|
local current_bgm = nil
|
||||||
local bgm_locked = false
|
local bgm_locked = false
|
||||||
|
local unfocused = false
|
||||||
|
|
||||||
function switchBGM(sound, subsound)
|
function switchBGM(sound, subsound)
|
||||||
if bgm_locked then return end
|
|
||||||
if current_bgm ~= nil then
|
if current_bgm ~= nil then
|
||||||
current_bgm:stop()
|
current_bgm:stop()
|
||||||
end
|
end
|
||||||
if subsound ~= nil then
|
if bgm_locked or config.bgm_volume <= 0 then
|
||||||
current_bgm = bgm[sound][subsound]
|
current_bgm = nil
|
||||||
resetBGMFadeout()
|
|
||||||
elseif sound ~= nil then
|
elseif sound ~= nil then
|
||||||
current_bgm = bgm[sound]
|
if subsound ~= nil then
|
||||||
resetBGMFadeout()
|
current_bgm = bgm[sound][subsound]
|
||||||
|
else
|
||||||
|
current_bgm = bgm[sound]
|
||||||
|
end
|
||||||
else
|
else
|
||||||
current_bgm = nil
|
current_bgm = nil
|
||||||
end
|
end
|
||||||
|
if current_bgm ~= nil then
|
||||||
|
resetBGMFadeout()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function switchBGMLoop(sound, subsound)
|
function switchBGMLoop(sound, subsound)
|
||||||
if bgm_locked then return end
|
|
||||||
switchBGM(sound, subsound)
|
switchBGM(sound, subsound)
|
||||||
current_bgm:setLooping(true)
|
if current_bgm then current_bgm:setLooping(true) end
|
||||||
end
|
end
|
||||||
|
|
||||||
function lockBGM()
|
function lockBGM()
|
||||||
bgm_locked = true
|
bgm_locked = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function unlockBGM()
|
||||||
|
bgm_locked = false
|
||||||
|
end
|
||||||
|
|
||||||
local fading_bgm = false
|
local fading_bgm = false
|
||||||
local fadeout_time = 0
|
local fadeout_time = 0
|
||||||
local total_fadeout_time = 0
|
local total_fadeout_time = 0
|
||||||
@ -49,11 +57,11 @@ end
|
|||||||
function resetBGMFadeout(time)
|
function resetBGMFadeout(time)
|
||||||
current_bgm:setVolume(config.bgm_volume)
|
current_bgm:setVolume(config.bgm_volume)
|
||||||
fading_bgm = false
|
fading_bgm = false
|
||||||
current_bgm:play()
|
resumeBGM()
|
||||||
end
|
end
|
||||||
|
|
||||||
function processBGMFadeout(dt)
|
function processBGMFadeout(dt)
|
||||||
if fading_bgm then
|
if current_bgm and fading_bgm then
|
||||||
fadeout_time = fadeout_time - dt
|
fadeout_time = fadeout_time - dt
|
||||||
if fadeout_time < 0 then
|
if fadeout_time < 0 then
|
||||||
fadeout_time = 0
|
fadeout_time = 0
|
||||||
@ -63,13 +71,20 @@ function processBGMFadeout(dt)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function pauseBGM()
|
function pauseBGM(f)
|
||||||
|
if f then
|
||||||
|
unfocused = true
|
||||||
|
end
|
||||||
if current_bgm ~= nil then
|
if current_bgm ~= nil then
|
||||||
current_bgm:pause()
|
current_bgm:pause()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function resumeBGM()
|
function resumeBGM(f)
|
||||||
|
if f and scene.paused and unfocused then
|
||||||
|
unfocused = false
|
||||||
|
return
|
||||||
|
end
|
||||||
if current_bgm ~= nil then
|
if current_bgm ~= nil then
|
||||||
current_bgm:play()
|
current_bgm:play()
|
||||||
end
|
end
|
||||||
|
@ -25,6 +25,15 @@ backgrounds = {
|
|||||||
game_config = love.graphics.newImage("res/backgrounds/options-game.png"),
|
game_config = love.graphics.newImage("res/backgrounds/options-game.png"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- in order, the colors are:
|
||||||
|
-- red, orange, yellow, green, cyan, blue
|
||||||
|
-- magenta (or purple), white, black
|
||||||
|
-- the next three don't have colors tied to them
|
||||||
|
-- F is used for lock flash
|
||||||
|
-- A is a garbage block
|
||||||
|
-- X is an invisible "block"
|
||||||
|
-- don't use these for piece colors when making a ruleset
|
||||||
|
-- all the others are fine to use
|
||||||
blocks = {
|
blocks = {
|
||||||
["2tie"] = {
|
["2tie"] = {
|
||||||
R = love.graphics.newImage("res/img/s1.png"),
|
R = love.graphics.newImage("res/img/s1.png"),
|
||||||
@ -34,6 +43,8 @@ blocks = {
|
|||||||
C = love.graphics.newImage("res/img/s2.png"),
|
C = love.graphics.newImage("res/img/s2.png"),
|
||||||
B = love.graphics.newImage("res/img/s4.png"),
|
B = love.graphics.newImage("res/img/s4.png"),
|
||||||
M = love.graphics.newImage("res/img/s5.png"),
|
M = love.graphics.newImage("res/img/s5.png"),
|
||||||
|
W = love.graphics.newImage("res/img/s9.png"),
|
||||||
|
D = love.graphics.newImage("res/img/s8.png"),
|
||||||
F = love.graphics.newImage("res/img/s9.png"),
|
F = love.graphics.newImage("res/img/s9.png"),
|
||||||
A = love.graphics.newImage("res/img/s8.png"),
|
A = love.graphics.newImage("res/img/s8.png"),
|
||||||
X = love.graphics.newImage("res/img/s9.png"),
|
X = love.graphics.newImage("res/img/s9.png"),
|
||||||
@ -46,6 +57,8 @@ blocks = {
|
|||||||
C = love.graphics.newImage("res/img/bone.png"),
|
C = love.graphics.newImage("res/img/bone.png"),
|
||||||
B = love.graphics.newImage("res/img/bone.png"),
|
B = love.graphics.newImage("res/img/bone.png"),
|
||||||
M = love.graphics.newImage("res/img/bone.png"),
|
M = love.graphics.newImage("res/img/bone.png"),
|
||||||
|
W = love.graphics.newImage("res/img/bone.png"),
|
||||||
|
D = love.graphics.newImage("res/img/bone.png"),
|
||||||
F = love.graphics.newImage("res/img/bone.png"),
|
F = love.graphics.newImage("res/img/bone.png"),
|
||||||
A = love.graphics.newImage("res/img/bone.png"),
|
A = love.graphics.newImage("res/img/bone.png"),
|
||||||
X = love.graphics.newImage("res/img/bone.png"),
|
X = love.graphics.newImage("res/img/bone.png"),
|
||||||
@ -58,13 +71,16 @@ blocks = {
|
|||||||
C = love.graphics.newImage("res/img/gem2.png"),
|
C = love.graphics.newImage("res/img/gem2.png"),
|
||||||
B = love.graphics.newImage("res/img/gem4.png"),
|
B = love.graphics.newImage("res/img/gem4.png"),
|
||||||
M = love.graphics.newImage("res/img/gem5.png"),
|
M = love.graphics.newImage("res/img/gem5.png"),
|
||||||
|
W = love.graphics.newImage("res/img/gem9.png"),
|
||||||
|
D = love.graphics.newImage("res/img/gem9.png"),
|
||||||
F = love.graphics.newImage("res/img/gem9.png"),
|
F = love.graphics.newImage("res/img/gem9.png"),
|
||||||
A = love.graphics.newImage("res/img/gem9.png"),
|
A = love.graphics.newImage("res/img/gem9.png"),
|
||||||
X = love.graphics.newImage("res/img/gem9.png"),
|
X = love.graphics.newImage("res/img/gem9.png"),
|
||||||
},
|
},
|
||||||
["square"] = {
|
["square"] = {
|
||||||
F = love.graphics.newImage("res/img/squares.png"),
|
W = love.graphics.newImage("res/img/squares.png"),
|
||||||
Y = love.graphics.newImage("res/img/squareg.png"),
|
Y = love.graphics.newImage("res/img/squareg.png"),
|
||||||
|
F = love.graphics.newImage("res/img/squares.png"),
|
||||||
X = love.graphics.newImage("res/img/squares.png"),
|
X = love.graphics.newImage("res/img/squares.png"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,7 +103,7 @@ ColourSchemes = {
|
|||||||
Z = "R",
|
Z = "R",
|
||||||
O = "Y",
|
O = "Y",
|
||||||
T = "M",
|
T = "M",
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, blockset in pairs(blocks) do
|
for name, blockset in pairs(blocks) do
|
||||||
|
@ -6,19 +6,53 @@ function loadSave()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function loadFromFile(filename)
|
function loadFromFile(filename)
|
||||||
local save_data, len = binser.readFile(filename)
|
local file_data = love.filesystem.read(filename)
|
||||||
|
if file_data == nil then
|
||||||
|
return {} -- new object
|
||||||
|
end
|
||||||
|
local save_data = binser.deserialize(file_data)
|
||||||
if save_data == nil then
|
if save_data == nil then
|
||||||
return {} -- new object
|
return {} -- new object
|
||||||
end
|
end
|
||||||
return save_data[1]
|
return save_data[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function initConfig()
|
||||||
|
if not config.das then config.das = 10 end
|
||||||
|
if not config.arr then config.arr = 2 end
|
||||||
|
if not config.dcd then config.dcd = 0 end
|
||||||
|
if not config.sfx_volume then config.sfx_volume = 0.5 end
|
||||||
|
if not config.bgm_volume then config.bgm_volume = 0.5 end
|
||||||
|
|
||||||
|
if config.fullscreen == nil then config.fullscreen = false end
|
||||||
|
if config.secret == nil then config.secret = false end
|
||||||
|
|
||||||
|
if not config.gamesettings then config.gamesettings = {} end
|
||||||
|
for _, option in ipairs(GameConfigScene.options) do
|
||||||
|
if not config.gamesettings[option[1]] then
|
||||||
|
config.gamesettings[option[1]] = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not config.input then
|
||||||
|
scene = InputConfigScene()
|
||||||
|
else
|
||||||
|
if config.current_mode then current_mode = config.current_mode end
|
||||||
|
if config.current_ruleset then current_ruleset = config.current_ruleset end
|
||||||
|
if not config.mode_path then config.mode_path = {} end
|
||||||
|
if not config.rule_path then config.rule_path = {} end
|
||||||
|
scene = TitleScene()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function saveConfig()
|
function saveConfig()
|
||||||
binser.writeFile('config.sav', config)
|
love.filesystem.write(
|
||||||
|
'config.sav', binser.serialize(config)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function saveHighscores()
|
function saveHighscores()
|
||||||
binser.writeFile('highscores.sav', highscores)
|
love.filesystem.write(
|
||||||
|
'highscores.sav', binser.serialize(highscores)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
@ -22,38 +22,48 @@ sounds = {
|
|||||||
go = love.audio.newSource("res/se/go.wav", "static"),
|
go = love.audio.newSource("res/se/go.wav", "static"),
|
||||||
irs = love.audio.newSource("res/se/irs.wav", "static"),
|
irs = love.audio.newSource("res/se/irs.wav", "static"),
|
||||||
ihs = love.audio.newSource("res/se/ihs.wav", "static"),
|
ihs = love.audio.newSource("res/se/ihs.wav", "static"),
|
||||||
|
clears = {
|
||||||
|
single = love.audio.newSource("res/se/single.wav", "static"),
|
||||||
|
double = love.audio.newSource("res/se/double.wav", "static"),
|
||||||
|
triple = love.audio.newSource("res/se/triple.wav", "static"),
|
||||||
|
quad = love.audio.newSource("res/se/quad.wav", "static")
|
||||||
|
},
|
||||||
-- a secret sound!
|
-- a secret sound!
|
||||||
welcome = love.audio.newSource("res/se/welcomeToCambridge.wav", "static"),
|
welcome = love.audio.newSource("res/se/welcomeToCambridge.wav", "static"),
|
||||||
}
|
}
|
||||||
|
|
||||||
function playSE(sound, subsound)
|
function playSE(sound, subsound)
|
||||||
if subsound == nil then
|
if sound ~= nil then
|
||||||
sounds[sound]:setVolume(config.sfx_volume)
|
if subsound ~= nil then
|
||||||
if sounds[sound]:isPlaying() then
|
sounds[sound][subsound]:setVolume(config.sfx_volume)
|
||||||
sounds[sound]:stop()
|
if sounds[sound][subsound]:isPlaying() then
|
||||||
|
sounds[sound][subsound]:stop()
|
||||||
|
end
|
||||||
|
sounds[sound][subsound]:play()
|
||||||
|
else
|
||||||
|
sounds[sound]:setVolume(config.sfx_volume)
|
||||||
|
if sounds[sound]:isPlaying() then
|
||||||
|
sounds[sound]:stop()
|
||||||
|
end
|
||||||
|
sounds[sound]:play()
|
||||||
end
|
end
|
||||||
sounds[sound]:play()
|
|
||||||
else
|
|
||||||
sounds[sound][subsound]:setVolume(config.sfx_volume)
|
|
||||||
if sounds[sound][subsound]:isPlaying() then
|
|
||||||
sounds[sound][subsound]:stop()
|
|
||||||
end
|
|
||||||
sounds[sound][subsound]:play()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function playSEOnce(sound, subsound)
|
function playSEOnce(sound, subsound)
|
||||||
if subsound == nil then
|
if sound ~= nil then
|
||||||
sounds[sound]:setVolume(config.sfx_volume)
|
if subsound ~= nil then
|
||||||
if sounds[sound]:isPlaying() then
|
sounds[sound][subsound]:setVolume(config.sfx_volume)
|
||||||
return
|
if sounds[sound][subsound]:isPlaying() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
sounds[sound][subsound]:play()
|
||||||
|
else
|
||||||
|
sounds[sound]:setVolume(config.sfx_volume)
|
||||||
|
if sounds[sound]:isPlaying() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
sounds[sound]:play()
|
||||||
end
|
end
|
||||||
sounds[sound]:play()
|
|
||||||
else
|
|
||||||
sounds[sound][subsound]:setVolume(config.sfx_volume)
|
|
||||||
if sounds[sound][subsound]:isPlaying() then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
sounds[sound][subsound]:play()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
1
load/version.lua
Normal file
1
load/version.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
version = "v0.3-beta7"
|
281
main.lua
281
main.lua
@ -8,106 +8,115 @@ function love.load()
|
|||||||
require "load.bgm"
|
require "load.bgm"
|
||||||
require "load.save"
|
require "load.save"
|
||||||
require "load.bigint"
|
require "load.bigint"
|
||||||
|
require "load.version"
|
||||||
loadSave()
|
loadSave()
|
||||||
|
require "funcs"
|
||||||
require "scene"
|
require "scene"
|
||||||
|
|
||||||
--config["side_next"] = false
|
--config["side_next"] = false
|
||||||
--config["reverse_rotate"] = true
|
--config["reverse_rotate"] = true
|
||||||
config["fullscreen"] = false
|
--config["das_last_key"] = false
|
||||||
|
--config["fullscreen"] = false
|
||||||
|
|
||||||
love.window.setMode(love.graphics.getWidth(), love.graphics.getHeight(), {resizable = true});
|
love.window.setMode(love.graphics.getWidth(), love.graphics.getHeight(), {resizable = true});
|
||||||
|
|
||||||
|
-- used for screenshots
|
||||||
|
GLOBAL_CANVAS = love.graphics.newCanvas()
|
||||||
|
|
||||||
-- init config
|
-- init config
|
||||||
if not config.das then config.das = 10 end
|
initConfig()
|
||||||
if not config.arr then config.arr = 2 end
|
|
||||||
if not config.dcd then config.dcd = 0 end
|
|
||||||
if not config.sfx_volume then config.sfx_volume = 0.5 end
|
|
||||||
if not config.bgm_volume then config.bgm_volume = 0.5 end
|
|
||||||
|
|
||||||
if config.secret == nil then config.secret = false
|
love.window.setFullscreen(config["fullscreen"])
|
||||||
elseif config.secret == true then playSE("welcome") end
|
if config.secret then playSE("welcome") end
|
||||||
|
|
||||||
if not config.gamesettings then
|
-- import custom modules
|
||||||
config.gamesettings = {}
|
initModules()
|
||||||
config["das_last_key"] = false
|
end
|
||||||
|
|
||||||
|
function loadFiles(path,name)
|
||||||
|
local file = love.filesystem.getInfo(path)
|
||||||
|
if(file.type == "directory") then
|
||||||
|
local files_in = {}
|
||||||
|
local file_list = love.filesystem.getDirectoryItems(path)
|
||||||
|
--print("Encountered directory "..path)
|
||||||
|
table.insert(files_in,{type="back",name="(..)"})
|
||||||
|
for i,v in ipairs(file_list) do
|
||||||
|
if(v ~= "gamemode.lua") then table.insert(files_in, loadFiles(path.."/"..v,v)) end -- gamemode.lua is the base, not a mode
|
||||||
|
end
|
||||||
|
return {type="directory",name=name,content=files_in}
|
||||||
else
|
else
|
||||||
config["das_last_key"] = config.gamesettings.das_last_key == 2
|
--print("Loaded file "..path)
|
||||||
|
return {type="file",content=require(string.gsub(string.gsub(path,"/","."),"%.lua",""))}
|
||||||
end
|
end
|
||||||
for _, option in ipairs(GameConfigScene.options) do
|
end
|
||||||
if not config.gamesettings[option[1]] then
|
|
||||||
config.gamesettings[option[1]] = 1
|
function sort_folder_algo(a,b)
|
||||||
|
local function padnum(d) return ("%03d%s"):format(#d, d) end
|
||||||
|
if(a.type == "back" or b.type == "back") then
|
||||||
|
-- back always goes first
|
||||||
|
return a.type == "back"
|
||||||
|
elseif(a.type == "directory" and b.type == "directory") then
|
||||||
|
-- if both are directories, sort by name
|
||||||
|
return tostring(a.name) < tostring(b.name)
|
||||||
|
elseif(a.type == "directory" or b.type == "directory") then
|
||||||
|
-- if one is a directory and the other's a file, then the directory always goes first
|
||||||
|
return a.type == "directory"
|
||||||
|
end
|
||||||
|
-- otherwise, they're both files, sort them by name
|
||||||
|
return tostring(a.content.name):gsub("%d+",padnum) < tostring(b.content.name):gsub("%d+",padnum)
|
||||||
|
end
|
||||||
|
|
||||||
|
function sortFolder(folder)
|
||||||
|
-- step 1, sort the main level
|
||||||
|
table.sort(folder, sort_folder_algo)
|
||||||
|
|
||||||
|
-- step 2, recursively do it
|
||||||
|
for i,v in ipairs(folder) do
|
||||||
|
if(v.type == "directory") then
|
||||||
|
sortFolder(v.content)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if not config.input then
|
function initModules()
|
||||||
scene = InputConfigScene()
|
|
||||||
else
|
|
||||||
if config.current_mode then current_mode = config.current_mode end
|
|
||||||
if config.current_ruleset then current_ruleset = config.current_ruleset end
|
|
||||||
scene = TitleScene()
|
|
||||||
end
|
|
||||||
|
|
||||||
game_modes = {}
|
game_modes = {}
|
||||||
mode_list = love.filesystem.getDirectoryItems("tetris/modes")
|
mode_list = love.filesystem.getDirectoryItems("tetris/modes")
|
||||||
|
for i,v in ipairs(mode_list) do
|
||||||
|
if(v ~= "gamemode.lua") then table.insert(game_modes, loadFiles("tetris/modes/"..v,v)) end
|
||||||
|
end
|
||||||
|
--[[
|
||||||
|
mode_list = love.filesystem.getDirectoryItems("tetris/modes")
|
||||||
for i=1,#mode_list do
|
for i=1,#mode_list do
|
||||||
if(mode_list[i] ~= "gamemode.lua" and mode_list[i] ~= "unrefactored_modes") then
|
|
||||||
|
if(mode_list[i] ~= "gamemode.lua" and string.sub(mode_list[i], -4) == ".lua") then
|
||||||
game_modes[#game_modes+1] = require ("tetris.modes."..string.sub(mode_list[i],1,-5))
|
game_modes[#game_modes+1] = require ("tetris.modes."..string.sub(mode_list[i],1,-5))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
--]]
|
||||||
rulesets = {}
|
rulesets = {}
|
||||||
rule_list = love.filesystem.getDirectoryItems("tetris/rulesets")
|
rule_list = love.filesystem.getDirectoryItems("tetris/rulesets")
|
||||||
|
for i,v in ipairs(rule_list) do
|
||||||
|
if(v ~= "ruleset.lua") then table.insert(rulesets, loadFiles("tetris/rulesets/"..v,v)) end
|
||||||
|
end
|
||||||
|
--[[
|
||||||
for i=1,#rule_list do
|
for i=1,#rule_list do
|
||||||
if(rule_list[i] ~= "ruleset.lua" and rule_list[i] ~= "unrefactored_rulesets") then
|
if(rule_list[i] ~= "ruleset.lua" and string.sub(rule_list[i], -4) == ".lua") then
|
||||||
rulesets[#rulesets+1] = require ("tetris.rulesets."..string.sub(rule_list[i],1,-5))
|
rulesets[#rulesets+1] = require ("tetris.rulesets."..string.sub(rule_list[i],1,-5))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
]]
|
||||||
--sort mode/rule lists
|
--sort mode/rule lists
|
||||||
|
|
||||||
local function padnum(d) return ("%03d%s"):format(#d, d) end
|
local function padnum(d) return ("%03d%s"):format(#d, d) end
|
||||||
table.sort(game_modes, function(a,b)
|
|
||||||
return tostring(a.name):gsub("%d+",padnum) < tostring(b.name):gsub("%d+",padnum) end)
|
|
||||||
table.sort(rulesets, function(a,b)
|
|
||||||
return tostring(a.name):gsub("%d+",padnum) < tostring(b.name):gsub("%d+",padnum) end)
|
|
||||||
|
|
||||||
end
|
sortFolder(game_modes)
|
||||||
|
sortFolder(rulesets)
|
||||||
local TARGET_FPS = 60
|
|
||||||
local SAMPLE_SIZE = 60
|
|
||||||
|
|
||||||
local rolling_samples = {}
|
|
||||||
local rolling_total = 0
|
|
||||||
local average_n = 0
|
|
||||||
local frame = 0
|
|
||||||
|
|
||||||
function getSmoothedDt(dt)
|
|
||||||
rolling_total = rolling_total + dt
|
|
||||||
frame = frame + 1
|
|
||||||
if frame > SAMPLE_SIZE then frame = frame - SAMPLE_SIZE end
|
|
||||||
if average_n == SAMPLE_SIZE then
|
|
||||||
rolling_total = rolling_total - rolling_samples[frame]
|
|
||||||
else
|
|
||||||
average_n = average_n + 1
|
|
||||||
end
|
|
||||||
rolling_samples[frame] = dt
|
|
||||||
return rolling_total / average_n
|
|
||||||
end
|
|
||||||
|
|
||||||
local update_time = 0.52
|
|
||||||
|
|
||||||
function love.update(dt)
|
|
||||||
processBGMFadeout(dt)
|
|
||||||
local old_update_time = update_time
|
|
||||||
update_time = update_time + getSmoothedDt(dt) * TARGET_FPS
|
|
||||||
updates = 0
|
|
||||||
while (update_time >= 1.02) do
|
|
||||||
scene:update()
|
|
||||||
updates = updates + 1
|
|
||||||
update_time = update_time - 1
|
|
||||||
end
|
|
||||||
if math.abs(update_time - old_update_time) < 0.02 then
|
|
||||||
update_time = old_update_time
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.draw()
|
function love.draw()
|
||||||
|
love.graphics.setCanvas(GLOBAL_CANVAS)
|
||||||
|
love.graphics.clear()
|
||||||
|
|
||||||
love.graphics.push()
|
love.graphics.push()
|
||||||
|
|
||||||
-- get offset matrix
|
-- get offset matrix
|
||||||
@ -122,13 +131,23 @@ function love.draw()
|
|||||||
love.graphics.scale(scale_factor)
|
love.graphics.scale(scale_factor)
|
||||||
|
|
||||||
scene:render()
|
scene:render()
|
||||||
|
|
||||||
|
love.graphics.setFont(font_3x5_2)
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
love.graphics.printf(version, 0, 460, 635, "right")
|
||||||
|
|
||||||
love.graphics.pop()
|
love.graphics.pop()
|
||||||
|
|
||||||
|
love.graphics.setCanvas()
|
||||||
|
love.graphics.setColor(1,1,1,1)
|
||||||
|
love.graphics.draw(GLOBAL_CANVAS)
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.keypressed(key, scancode)
|
function love.keypressed(key, scancode)
|
||||||
-- global hotkeys
|
-- global hotkeys
|
||||||
if scancode == "f4" then
|
if scancode == "f11" then
|
||||||
config["fullscreen"] = not config["fullscreen"]
|
config["fullscreen"] = not config["fullscreen"]
|
||||||
|
saveConfig()
|
||||||
love.window.setFullscreen(config["fullscreen"])
|
love.window.setFullscreen(config["fullscreen"])
|
||||||
elseif scancode == "f2" and scene.title ~= "Input Config" and scene.title ~= "Game" then
|
elseif scancode == "f2" and scene.title ~= "Input Config" and scene.title ~= "Game" then
|
||||||
scene = InputConfigScene()
|
scene = InputConfigScene()
|
||||||
@ -140,6 +159,16 @@ function love.keypressed(key, scancode)
|
|||||||
scene.restart_message = true
|
scene.restart_message = true
|
||||||
if config.secret then playSE("mode_decide")
|
if config.secret then playSE("mode_decide")
|
||||||
else playSE("erase") end
|
else playSE("erase") end
|
||||||
|
-- f12 is reserved for saving screenshots
|
||||||
|
elseif scancode == "f12" then
|
||||||
|
local ss_name = os.date("ss/%Y-%m-%d_%H-%M-%S.png")
|
||||||
|
local info = love.filesystem.getInfo("ss", "directory")
|
||||||
|
if not info then
|
||||||
|
love.filesystem.remove("ss")
|
||||||
|
love.filesystem.createDirectory("ss")
|
||||||
|
end
|
||||||
|
print("Saving screenshot as "..ss_name)
|
||||||
|
GLOBAL_CANVAS:newImageData():encode("png", ss_name)
|
||||||
-- function keys are reserved
|
-- function keys are reserved
|
||||||
elseif string.match(scancode, "^f[1-9]$") or string.match(scancode, "^f[1-9][0-9]+$") then
|
elseif string.match(scancode, "^f[1-9]$") or string.match(scancode, "^f[1-9][0-9]+$") then
|
||||||
return
|
return
|
||||||
@ -210,13 +239,13 @@ function love.joystickaxis(joystick, axis, value)
|
|||||||
config.input.joysticks[joystick:getName()].axes and
|
config.input.joysticks[joystick:getName()].axes and
|
||||||
config.input.joysticks[joystick:getName()].axes[axis]
|
config.input.joysticks[joystick:getName()].axes[axis]
|
||||||
then
|
then
|
||||||
if math.abs(value) >= 0.5 then
|
if math.abs(value) >= 1 then
|
||||||
input_pressed = config.input.joysticks[joystick:getName()].axes[axis][value >= 0.5 and "positive" or "negative"]
|
input_pressed = config.input.joysticks[joystick:getName()].axes[axis][value >= 1 and "positive" or "negative"]
|
||||||
end
|
end
|
||||||
positive_released = config.input.joysticks[joystick:getName()].axes[axis].positive
|
positive_released = config.input.joysticks[joystick:getName()].axes[axis].positive
|
||||||
negative_released = config.input.joysticks[joystick:getName()].axes[axis].negative
|
negative_released = config.input.joysticks[joystick:getName()].axes[axis].negative
|
||||||
end
|
end
|
||||||
if math.abs(value) >= 0.5 then
|
if math.abs(value) >= 1 then
|
||||||
scene:onInputPress({input=input_pressed, type="joyaxis", name=joystick:getName(), axis=axis, value=value})
|
scene:onInputPress({input=input_pressed, type="joyaxis", name=joystick:getName(), axis=axis, value=value})
|
||||||
else
|
else
|
||||||
scene:onInputRelease({input=positive_released, type="joyaxis", name=joystick:getName(), axis=axis, value=value})
|
scene:onInputRelease({input=positive_released, type="joyaxis", name=joystick:getName(), axis=axis, value=value})
|
||||||
@ -224,6 +253,14 @@ function love.joystickaxis(joystick, axis, value)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local last_hat_direction = ""
|
||||||
|
local directions = {
|
||||||
|
["u"] = "up",
|
||||||
|
["d"] = "down",
|
||||||
|
["l"] = "left",
|
||||||
|
["r"] = "right",
|
||||||
|
}
|
||||||
|
|
||||||
function love.joystickhat(joystick, hat, direction)
|
function love.joystickhat(joystick, hat, direction)
|
||||||
local input_pressed = nil
|
local input_pressed = nil
|
||||||
local has_hat = false
|
local has_hat = false
|
||||||
@ -240,24 +277,116 @@ function love.joystickhat(joystick, hat, direction)
|
|||||||
has_hat = true
|
has_hat = true
|
||||||
end
|
end
|
||||||
if input_pressed then
|
if input_pressed then
|
||||||
scene:onInputPress({input=input_pressed, type="joyhat", name=joystick:getName(), hat=hat, direction=direction})
|
for i = 1, #direction do
|
||||||
|
local char = direction:sub(i, i)
|
||||||
|
local _, count = last_hat_direction:gsub(char, char)
|
||||||
|
if count == 0 then
|
||||||
|
scene:onInputPress({input=config.input.joysticks[joystick:getName()].hats[hat][char], type="joyhat", name=joystick:getName(), hat=hat, direction=char})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i = 1, #last_hat_direction do
|
||||||
|
local char = last_hat_direction:sub(i, i)
|
||||||
|
local _, count = direction:gsub(char, char)
|
||||||
|
if count == 0 then
|
||||||
|
scene:onInputRelease({input=config.input.joysticks[joystick:getName()].hats[hat][char], type="joyhat", name=joystick:getName(), hat=hat, direction=char})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
last_hat_direction = direction
|
||||||
elseif has_hat then
|
elseif has_hat then
|
||||||
for i, direction in ipairs{"d", "l", "ld", "lu", "r", "rd", "ru", "u"} do
|
for i, direction in ipairs{"d", "l", "ld", "lu", "r", "rd", "ru", "u"} do
|
||||||
scene:onInputRelease({input=config.input.joysticks[joystick:getName()].hats[hat][direction], type="joyhat", name=joystick:getName(), hat=hat, direction=direction})
|
scene:onInputRelease({input=config.input.joysticks[joystick:getName()].hats[hat][direction], type="joyhat", name=joystick:getName(), hat=hat, direction=direction})
|
||||||
end
|
end
|
||||||
|
last_hat_direction = ""
|
||||||
elseif direction ~= "c" then
|
elseif direction ~= "c" then
|
||||||
scene:onInputPress({input=nil, type="joyhat", name=joystick:getName(), hat=hat, direction=direction})
|
for i = 1, #direction do
|
||||||
|
local char = direction:sub(i, i)
|
||||||
|
local _, count = last_hat_direction:gsub(char, char)
|
||||||
|
if count == 0 then
|
||||||
|
scene:onInputPress({input=directions[char], type="joyhat", name=joystick:getName(), hat=hat, direction=char})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i = 1, #last_hat_direction do
|
||||||
|
local char = last_hat_direction:sub(i, i)
|
||||||
|
local _, count = direction:gsub(char, char)
|
||||||
|
if count == 0 then
|
||||||
|
scene:onInputRelease({input=directions[char], type="joyhat", name=joystick:getName(), hat=hat, direction=char})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
last_hat_direction = direction
|
||||||
else
|
else
|
||||||
for i, direction in ipairs{"d", "l", "ld", "lu", "r", "rd", "ru", "u"} do
|
for i, direction in ipairs{"d", "l", "ld", "lu", "r", "rd", "ru", "u"} do
|
||||||
scene:onInputRelease({input=nil, type="joyhat", name=joystick:getName(), hat=hat, direction=direction})
|
scene:onInputRelease({input=nil, type="joyhat", name=joystick:getName(), hat=hat, direction=direction})
|
||||||
end
|
end
|
||||||
|
last_hat_direction = ""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function love.wheelmoved(x, y)
|
||||||
|
scene:onInputPress({input=nil, type="wheel", x=x, y=y})
|
||||||
|
end
|
||||||
|
|
||||||
function love.focus(f)
|
function love.focus(f)
|
||||||
if f and (scene.title ~= "Game" or not scene.paused) then
|
if f then
|
||||||
resumeBGM()
|
resumeBGM(true)
|
||||||
else
|
else
|
||||||
pauseBGM()
|
pauseBGM(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function love.resize(w, h)
|
||||||
|
GLOBAL_CANVAS:release()
|
||||||
|
GLOBAL_CANVAS = love.graphics.newCanvas(w, h)
|
||||||
|
end
|
||||||
|
|
||||||
|
local TARGET_FPS = 60
|
||||||
|
|
||||||
|
function love.run()
|
||||||
|
if love.load then love.load(love.arg.parseGameArguments(arg), arg) end
|
||||||
|
|
||||||
|
if love.timer then love.timer.step() end
|
||||||
|
|
||||||
|
local dt = 0
|
||||||
|
|
||||||
|
local last_time = love.timer.getTime()
|
||||||
|
local time_accumulator = 0
|
||||||
|
return function()
|
||||||
|
if love.event then
|
||||||
|
love.event.pump()
|
||||||
|
for name, a,b,c,d,e,f in love.event.poll() do
|
||||||
|
if name == "quit" then
|
||||||
|
if not love.quit or not love.quit() then
|
||||||
|
return a or 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
love.handlers[name](a,b,c,d,e,f)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if love.timer then
|
||||||
|
processBGMFadeout(love.timer.step())
|
||||||
|
end
|
||||||
|
|
||||||
|
if scene and scene.update and love.timer then
|
||||||
|
scene:update()
|
||||||
|
|
||||||
|
local frame_duration = 1.0 / TARGET_FPS
|
||||||
|
if time_accumulator < frame_duration then
|
||||||
|
if love.graphics and love.graphics.isActive() and love.draw then
|
||||||
|
love.graphics.origin()
|
||||||
|
love.graphics.clear(love.graphics.getBackgroundColor())
|
||||||
|
love.draw()
|
||||||
|
love.graphics.present()
|
||||||
|
end
|
||||||
|
local end_time = last_time + frame_duration
|
||||||
|
local time = love.timer.getTime()
|
||||||
|
while time < end_time do
|
||||||
|
love.timer.sleep(0.001)
|
||||||
|
time = love.timer.getTime()
|
||||||
|
end
|
||||||
|
time_accumulator = time_accumulator + time - last_time
|
||||||
|
end
|
||||||
|
time_accumulator = time_accumulator - frame_duration
|
||||||
|
end
|
||||||
|
last_time = love.timer.getTime()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -11,6 +11,8 @@ function Scene:onInputRelease() end
|
|||||||
ExitScene = require "scene.exit"
|
ExitScene = require "scene.exit"
|
||||||
GameScene = require "scene.game"
|
GameScene = require "scene.game"
|
||||||
ModeSelectScene = require "scene.mode_select"
|
ModeSelectScene = require "scene.mode_select"
|
||||||
|
KeyConfigScene = require "scene.key_config"
|
||||||
|
StickConfigScene = require "scene.stick_config"
|
||||||
InputConfigScene = require "scene.input_config"
|
InputConfigScene = require "scene.input_config"
|
||||||
GameConfigScene = require "scene.game_config"
|
GameConfigScene = require "scene.game_config"
|
||||||
TuningScene = require "scene.tuning"
|
TuningScene = require "scene.tuning"
|
||||||
|
@ -4,23 +4,33 @@ CreditsScene.title = "Credits"
|
|||||||
|
|
||||||
function CreditsScene:new()
|
function CreditsScene:new()
|
||||||
self.frames = 0
|
self.frames = 0
|
||||||
|
-- higher = slower
|
||||||
|
self.scroll_speed = 1.85
|
||||||
switchBGM("credit_roll", "gm3")
|
switchBGM("credit_roll", "gm3")
|
||||||
|
|
||||||
|
DiscordRPC:update({
|
||||||
|
details = "Watching the credits",
|
||||||
|
state = "Thanks for playing the game!",
|
||||||
|
largeImageKey = "ingame-1900",
|
||||||
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreditsScene:update()
|
function CreditsScene:update()
|
||||||
if love.window.hasFocus() then
|
if love.window.hasFocus() then
|
||||||
self.frames = self.frames + 1
|
self.frames = self.frames + 1
|
||||||
end
|
end
|
||||||
if self.frames >= 4200 then
|
if self.frames >= 2100 * self.scroll_speed then
|
||||||
playSE("mode_decide")
|
playSE("mode_decide")
|
||||||
scene = TitleScene()
|
scene = TitleScene()
|
||||||
switchBGM(nil)
|
switchBGM(nil)
|
||||||
elseif self.frames == 3600 then
|
elseif self.frames == math.floor(1950 * self.scroll_speed) then
|
||||||
fadeoutBGM(2)
|
fadeoutBGM(2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreditsScene:render()
|
function CreditsScene:render()
|
||||||
|
local offset = self.frames / self.scroll_speed
|
||||||
|
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
love.graphics.draw(
|
love.graphics.draw(
|
||||||
backgrounds[19],
|
backgrounds[19],
|
||||||
@ -29,27 +39,43 @@ function CreditsScene:render()
|
|||||||
)
|
)
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_4)
|
love.graphics.setFont(font_3x5_4)
|
||||||
love.graphics.print("Cambridge Credits", 320, 500 - self.frames / 2)
|
love.graphics.print("Cambridge Credits", 320, 500 - offset)
|
||||||
love.graphics.print("THANK YOU\nFOR PLAYING!", 320, math.max(1500 - self.frames / 2, 240))
|
love.graphics.print("THANK YOU\nFOR PLAYING!", 320, math.max(2050 - offset, 240))
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_3)
|
love.graphics.setFont(font_3x5_3)
|
||||||
love.graphics.print("Game Developers", 320, 550 - self.frames / 2)
|
love.graphics.print("Game Developers", 320, 550 - offset)
|
||||||
love.graphics.print("Project Heads", 320, 640 - self.frames / 2)
|
love.graphics.print("Project Heads", 320, 640 - offset)
|
||||||
love.graphics.print("Other Game Developers", 320, 730 - self.frames / 2)
|
love.graphics.print("Notable Game Developers", 320, 750 - offset)
|
||||||
love.graphics.print("Special Thanks", 320, 900 - self.frames / 2)
|
love.graphics.print("Special Thanks", 320, 1020 - offset)
|
||||||
love.graphics.print("- SashLilac / SpinTriple", 320, math.max(2000 - self.frames / 2, 320))
|
love.graphics.print("- Milla", 320, math.max(2130 - offset, 320))
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_2)
|
love.graphics.setFont(font_3x5_2)
|
||||||
love.graphics.print("Oshisaure\nJoe Zeng", 320, 590 - self.frames / 2)
|
love.graphics.print("Oshisaure\nJoe Zeng", 320, 590 - offset)
|
||||||
love.graphics.print("Mizu\nHailey", 320, 680 - self.frames / 2)
|
love.graphics.print("Mizu\nMarkGamed\nHailey", 320, 680 - offset)
|
||||||
love.graphics.print("Axel Fox - Multimino\nMine - Tetra Online\nDr Ocelot - Tetra Legends\nFelicity / nightmareci - Shiromino\n2Tie - TGMsim\nPhoenix Flare - Master of Blocks", 320, 770 - self.frames / 2)
|
|
||||||
love.graphics.print(
|
love.graphics.print(
|
||||||
"RocketLanterns\nCylinderKnot\nHammrTime\nKirby703\nMattMayuga\nMyPasswordIsWeak\n" ..
|
"2Tie - TGMsim\nAxel Fox - Multimino\nDr Ocelot - Tetra Legends\n" ..
|
||||||
"Nikki Karissa\noffwo\nsinefuse\nTetro48\nTimmSkiller\nuser74003\nAgentBasey\n" ..
|
"Electra - ZTrix\nFelicity/nightmareci/kdex - Shiromino\n" ..
|
||||||
"CheeZed_Fish\neightsixfivezero\nEricICX\ngizmo4487\nM1ssing0\nMarkGamed7794\n" ..
|
"Mine - Tetra Online\nMrZ - Techmino\nosk - TETR.IO\n" ..
|
||||||
"pokemonfan1937\nSimon\nstratus\nZaptorZap\nThe Absolute PLUS Discord\nTetra Legends Discord\n" ..
|
"Phoenix Flare - Master of Blocks\nRayRay26 - Spirit Drop\n" ..
|
||||||
"Tetra Online Discord\nMultimino Discord\nCambridge Discord\nAnd to you, the player!",
|
"Rin - Puzzle Trial\nsinefuse - stackfuse",
|
||||||
320, 940 - self.frames / 2
|
320, 790 - offset
|
||||||
|
)
|
||||||
|
love.graphics.print(
|
||||||
|
"321MrHaatz\nAdventium\nAgentBasey\nArchina\nAurora\n" ..
|
||||||
|
"Caithness\nCheez\ncolour_thief\nCommando\nCublex\n" ..
|
||||||
|
"CylinderKnot\neightsixfivezero\nEricICX\nGesomaru\n" ..
|
||||||
|
"gizmo4487\nJBroms\nKirby703\nKitaru\n" ..
|
||||||
|
"M1ssing0\nMattMayuga\nMyPasswordIsWeak\n" ..
|
||||||
|
"Nikki Karissa\noffwo\nOliver\nPineapple\npokemonfan1937\n" ..
|
||||||
|
"Pyra Neoxi\nRDST64\nRocketLanterns\nRustyFoxxo\n" ..
|
||||||
|
"saphie\nShelleloch\nSimon\nstratus\nSuper302\n" ..
|
||||||
|
"switchpalacecorner\nterpyderp\nTetrian22\nTetro48\nThatCookie\n" ..
|
||||||
|
"TimmSkiller\nTrixciel\nuser74003\nZaptorZap\nZircean\n" ..
|
||||||
|
"All other contributors and friends!\nThe Absolute PLUS Discord\n" ..
|
||||||
|
"Tetra Legends Discord\nTetra Online Discord\nMultimino Discord\n" ..
|
||||||
|
"Hard Drop Discord\nRusty's Systemspace\nCambridge Discord\n" ..
|
||||||
|
"And to you, the player!",
|
||||||
|
320, 1060 - offset
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -7,10 +7,10 @@ require 'load.save'
|
|||||||
function GameScene:new(game_mode, ruleset, inputs)
|
function GameScene:new(game_mode, ruleset, inputs)
|
||||||
self.retry_mode = game_mode
|
self.retry_mode = game_mode
|
||||||
self.retry_ruleset = ruleset
|
self.retry_ruleset = ruleset
|
||||||
self.secret_inputs = copy(inputs)
|
self.secret_inputs = inputs
|
||||||
self.game = game_mode(self.secret_inputs)
|
self.game = game_mode(self.secret_inputs)
|
||||||
self.ruleset = ruleset()
|
self.ruleset = ruleset(self.game)
|
||||||
self.game:initialize(self.ruleset, self.secret_inputs)
|
self.game:initialize(self.ruleset)
|
||||||
self.inputs = {
|
self.inputs = {
|
||||||
left=false,
|
left=false,
|
||||||
right=false,
|
right=false,
|
||||||
@ -27,6 +27,7 @@ function GameScene:new(game_mode, ruleset, inputs)
|
|||||||
DiscordRPC:update({
|
DiscordRPC:update({
|
||||||
details = self.game.rpc_details,
|
details = self.game.rpc_details,
|
||||||
state = self.game.name,
|
state = self.game.name,
|
||||||
|
largeImageKey = "ingame-"..self.game:getBackground().."00"
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -38,94 +39,39 @@ function GameScene:update()
|
|||||||
end
|
end
|
||||||
self.game:update(inputs, self.ruleset)
|
self.game:update(inputs, self.ruleset)
|
||||||
self.game.grid:update()
|
self.game.grid:update()
|
||||||
|
DiscordRPC:update({
|
||||||
|
largeImageKey = "ingame-"..self.game:getBackground().."00"
|
||||||
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function GameScene:render()
|
function GameScene:render()
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
self.game:draw(self.paused)
|
||||||
love.graphics.draw(
|
|
||||||
backgrounds[self.game:getBackground()],
|
|
||||||
0, 0, 0,
|
|
||||||
0.5, 0.5
|
|
||||||
)
|
|
||||||
|
|
||||||
-- game frame
|
|
||||||
if self.game.grid.width == 10 and self.game.grid.height == 24 then
|
|
||||||
love.graphics.draw(misc_graphics["frame"], 48, 64)
|
|
||||||
end
|
|
||||||
|
|
||||||
love.graphics.setColor(0, 0, 0, 200)
|
|
||||||
love.graphics.rectangle(
|
|
||||||
"fill", 64, 80,
|
|
||||||
16 * self.game.grid.width, 16 * (self.game.grid.height - 4)
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.game.grid.width ~= 10 or self.game.grid.height ~= 24 then
|
|
||||||
love.graphics.setColor(174/255, 83/255, 76/255, 1)
|
|
||||||
love.graphics.setLineWidth(8)
|
|
||||||
love.graphics.line(
|
|
||||||
60,76,
|
|
||||||
68+16*self.game.grid.width,76,
|
|
||||||
68+16*self.game.grid.width,84+16*(self.game.grid.height-4),
|
|
||||||
60,84+16*(self.game.grid.height-4),
|
|
||||||
60,76
|
|
||||||
)
|
|
||||||
love.graphics.setColor(203/255, 137/255, 111/255, 1)
|
|
||||||
love.graphics.setLineWidth(4)
|
|
||||||
love.graphics.line(
|
|
||||||
60,76,
|
|
||||||
68+16*self.game.grid.width,76,
|
|
||||||
68+16*self.game.grid.width,84+16*(self.game.grid.height-4),
|
|
||||||
60,84+16*(self.game.grid.height-4),
|
|
||||||
60,76
|
|
||||||
)
|
|
||||||
love.graphics.setLineWidth(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.game:drawGrid()
|
|
||||||
self.game:drawPiece()
|
|
||||||
self.game:drawNextQueue(self.ruleset)
|
|
||||||
self.game:drawScoringInfo()
|
|
||||||
|
|
||||||
-- ready/go graphics
|
|
||||||
|
|
||||||
if self.game.ready_frames <= 100 and self.game.ready_frames > 52 then
|
|
||||||
love.graphics.draw(misc_graphics["ready"], 144 - 50, 240 - 14)
|
|
||||||
elseif self.game.ready_frames <= 50 and self.game.ready_frames > 2 then
|
|
||||||
love.graphics.draw(misc_graphics["go"], 144 - 27, 240 - 14)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.game:drawCustom()
|
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_2)
|
|
||||||
if config.gamesettings.display_gamemode == 1 then
|
|
||||||
love.graphics.printf(self.game.name .. " - " .. self.ruleset.name, 0, 460, 640, "left")
|
|
||||||
end
|
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_3)
|
|
||||||
if self.paused then love.graphics.print("PAUSED!", 80, 100) end
|
|
||||||
|
|
||||||
if self.game.completed then
|
|
||||||
self.game:onGameComplete()
|
|
||||||
elseif self.game.game_over then
|
|
||||||
self.game:onGameOver()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function GameScene:onInputPress(e)
|
function GameScene:onInputPress(e)
|
||||||
if (self.game.game_over or self.game.completed) and (e.input == "menu_decide" or e.input == "menu_back" or e.input == "retry") then
|
if (
|
||||||
|
self.game.game_over or self.game.completed
|
||||||
|
) and (
|
||||||
|
e.input == "menu_decide" or
|
||||||
|
e.input == "menu_back" or
|
||||||
|
e.input == "retry"
|
||||||
|
) then
|
||||||
highscore_entry = self.game:getHighscoreData()
|
highscore_entry = self.game:getHighscoreData()
|
||||||
highscore_hash = self.game.hash .. "-" .. self.ruleset.hash
|
highscore_hash = self.game.hash .. "-" .. self.ruleset.hash
|
||||||
submitHighscore(highscore_hash, highscore_entry)
|
submitHighscore(highscore_hash, highscore_entry)
|
||||||
|
self.game:onExit()
|
||||||
scene = e.input == "retry" and GameScene(self.retry_mode, self.retry_ruleset, self.secret_inputs) or ModeSelectScene()
|
scene = e.input == "retry" and GameScene(self.retry_mode, self.retry_ruleset, self.secret_inputs) or ModeSelectScene()
|
||||||
elseif e.input == "retry" then
|
elseif e.input == "retry" then
|
||||||
switchBGM(nil)
|
switchBGM(nil)
|
||||||
|
self.game:onExit()
|
||||||
scene = GameScene(self.retry_mode, self.retry_ruleset, self.secret_inputs)
|
scene = GameScene(self.retry_mode, self.retry_ruleset, self.secret_inputs)
|
||||||
elseif e.input == "pause" and not (self.game.game_over or self.game.completed) then
|
elseif e.input == "pause" and not (self.game.game_over or self.game.completed) then
|
||||||
self.paused = not self.paused
|
self.paused = not self.paused
|
||||||
if self.paused then pauseBGM()
|
if self.paused then pauseBGM()
|
||||||
else resumeBGM() end
|
else resumeBGM() end
|
||||||
elseif e.input == "menu_back" then
|
elseif e.input == "menu_back" then
|
||||||
|
self.game:onExit()
|
||||||
scene = ModeSelectScene()
|
scene = ModeSelectScene()
|
||||||
elseif e.input and string.sub(e.input, 1, 5) ~= "menu_" then
|
elseif e.input and string.sub(e.input, 1, 5) ~= "menu_" then
|
||||||
self.inputs[e.input] = true
|
self.inputs[e.input] = true
|
||||||
|
@ -11,13 +11,13 @@ ConfigScene.options = {
|
|||||||
{"manlock", "Manual Locking", false, {"Per ruleset", "Per gamemode", "Harddrop", "Softdrop"}},
|
{"manlock", "Manual Locking", false, {"Per ruleset", "Per gamemode", "Harddrop", "Softdrop"}},
|
||||||
{"piece_colour", "Piece Colours", false, {"Per ruleset", "Arika", "TTC"}},
|
{"piece_colour", "Piece Colours", false, {"Per ruleset", "Arika", "TTC"}},
|
||||||
{"world_reverse", "A Button Rotation", false, {"Left", "Auto", "Right"}},
|
{"world_reverse", "A Button Rotation", false, {"Left", "Auto", "Right"}},
|
||||||
{"spawn_positions", "Spawn Positions", false, {"In field", "Out of field"}},
|
{"spawn_positions", "Spawn Positions", false, {"Per ruleset", "In field", "Out of field"}},
|
||||||
{"display_gamemode", "Display Gamemode", false, {"On", "Off"}},
|
{"display_gamemode", "Display Gamemode", false, {"On", "Off"}},
|
||||||
{"das_last_key", "DAS Switch", false, {"Default", "Instant"}},
|
{"das_last_key", "DAS Last Key", false, {"Off", "On"}},
|
||||||
{"smooth_movement", "Smooth Piece Drop", false, {"On", "Off"}},
|
{"smooth_movement", "Smooth Piece Drop", false, {"On", "Off"}},
|
||||||
{"synchroes_allowed", "Synchroes", false, {"Per ruleset", "On", "Off"}},
|
{"synchroes_allowed", "Synchroes", false, {"Per ruleset", "On", "Off"}},
|
||||||
{"diagonal_input", "Diagonal Input", false, {"On", "Off"}},
|
{"diagonal_input", "Diagonal Input", false, {"On", "Off"}},
|
||||||
{"buffer_lock", "Buffer Lock Inputs", false, {"On", "Off"}},
|
{"buffer_lock", "Buffer Drop Type", false, {"Off", "Hold", "Tap"}},
|
||||||
{"sfx_volume", "SFX", true, "sfxSlider"},
|
{"sfx_volume", "SFX", true, "sfxSlider"},
|
||||||
{"bgm_volume", "BGM", true, "bgmSlider"},
|
{"bgm_volume", "BGM", true, "bgmSlider"},
|
||||||
}
|
}
|
||||||
@ -29,7 +29,7 @@ function ConfigScene:new()
|
|||||||
self.highlight = 1
|
self.highlight = 1
|
||||||
|
|
||||||
DiscordRPC:update({
|
DiscordRPC:update({
|
||||||
details = "In menus",
|
details = "In settings",
|
||||||
state = "Changing game settings",
|
state = "Changing game settings",
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -38,7 +38,6 @@ function ConfigScene:new()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function ConfigScene:update()
|
function ConfigScene:update()
|
||||||
config["das_last_key"] = config.gamesettings.das_last_key == 2
|
|
||||||
self.sfxSlider:update()
|
self.sfxSlider:update()
|
||||||
self.bgmSlider:update()
|
self.bgmSlider:update()
|
||||||
end
|
end
|
||||||
@ -101,9 +100,10 @@ function ConfigScene:onInputPress(e)
|
|||||||
local option = ConfigScene.options[self.highlight]
|
local option = ConfigScene.options[self.highlight]
|
||||||
config.gamesettings[option[1]] = Mod1(config.gamesettings[option[1]]-1, #option[4])
|
config.gamesettings[option[1]] = Mod1(config.gamesettings[option[1]]-1, #option[4])
|
||||||
else
|
else
|
||||||
|
local sld = self[self.options[self.highlight][4]]
|
||||||
|
sld.value = math.max(sld.min, math.min(sld.max, (sld:getValue() - 5) / (sld.max - sld.min)))
|
||||||
|
sld:update()
|
||||||
playSE("cursor")
|
playSE("cursor")
|
||||||
sld = self[self.options[self.highlight][4]]
|
|
||||||
sld.value = math.max(sld.min, math.min(sld.max, (sld:getValue() - 3) / (sld.max - sld.min)))
|
|
||||||
end
|
end
|
||||||
elseif e.input == "right" or e.scancode == "right" then
|
elseif e.input == "right" or e.scancode == "right" then
|
||||||
if not self.options[self.highlight][3] then
|
if not self.options[self.highlight][3] then
|
||||||
@ -111,9 +111,10 @@ function ConfigScene:onInputPress(e)
|
|||||||
local option = ConfigScene.options[self.highlight]
|
local option = ConfigScene.options[self.highlight]
|
||||||
config.gamesettings[option[1]] = Mod1(config.gamesettings[option[1]]+1, #option[4])
|
config.gamesettings[option[1]] = Mod1(config.gamesettings[option[1]]+1, #option[4])
|
||||||
else
|
else
|
||||||
playSE("cursor")
|
|
||||||
sld = self[self.options[self.highlight][4]]
|
sld = self[self.options[self.highlight][4]]
|
||||||
sld.value = math.max(sld.min, math.min(sld.max, (sld:getValue() + 3) / (sld.max - sld.min)))--math.max(0, (math.floor(sld:getValue())+2)/(sld.max-sld.min))
|
sld.value = math.max(sld.min, math.min(sld.max, (sld:getValue() + 5) / (sld.max - sld.min)))
|
||||||
|
sld:update()
|
||||||
|
playSE("cursor")
|
||||||
end
|
end
|
||||||
elseif e.input == "menu_back" or e.scancode == "delete" or e.scancode == "backspace" then
|
elseif e.input == "menu_back" or e.scancode == "delete" or e.scancode == "backspace" then
|
||||||
loadSave()
|
loadSave()
|
||||||
|
@ -2,161 +2,65 @@ local ConfigScene = Scene:extend()
|
|||||||
|
|
||||||
ConfigScene.title = "Input Config"
|
ConfigScene.title = "Input Config"
|
||||||
|
|
||||||
require 'load.save'
|
local menu_screens = {
|
||||||
|
KeyConfigScene,
|
||||||
local configurable_inputs = {
|
StickConfigScene
|
||||||
"menu_decide",
|
|
||||||
"menu_back",
|
|
||||||
"left",
|
|
||||||
"right",
|
|
||||||
"up",
|
|
||||||
"down",
|
|
||||||
"rotate_left",
|
|
||||||
"rotate_left2",
|
|
||||||
"rotate_right",
|
|
||||||
"rotate_right2",
|
|
||||||
"rotate_180",
|
|
||||||
"hold",
|
|
||||||
"retry",
|
|
||||||
"pause",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local function newSetInputs()
|
|
||||||
local set_inputs = {}
|
|
||||||
for i, input in ipairs(configurable_inputs) do
|
|
||||||
set_inputs[input] = false
|
|
||||||
end
|
|
||||||
return set_inputs
|
|
||||||
end
|
|
||||||
|
|
||||||
function ConfigScene:new()
|
function ConfigScene:new()
|
||||||
self.input_state = 1
|
self.menu_state = 1
|
||||||
self.set_inputs = newSetInputs()
|
DiscordRPC:update({
|
||||||
self.new_input = {}
|
details = "In settings",
|
||||||
self.axis_timer = 0
|
state = "Changing input config",
|
||||||
|
largeImageKey = "settings-input"
|
||||||
DiscordRPC:update({
|
})
|
||||||
details = "In menus",
|
|
||||||
state = "Changing input config",
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfigScene:update()
|
function ConfigScene:update() end
|
||||||
end
|
|
||||||
|
|
||||||
function ConfigScene:render()
|
function ConfigScene:render()
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
love.graphics.draw(
|
love.graphics.draw(
|
||||||
backgrounds["input_config"],
|
backgrounds["input_config"],
|
||||||
0, 0, 0,
|
0, 0, 0,
|
||||||
0.5, 0.5
|
0.5, 0.5
|
||||||
)
|
)
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_2)
|
love.graphics.setFont(font_3x5_4)
|
||||||
for i, input in ipairs(configurable_inputs) do
|
love.graphics.print("INPUT CONFIG", 80, 40)
|
||||||
love.graphics.printf(input, 40, 50 + i * 20, 200, "left")
|
|
||||||
if self.set_inputs[input] then
|
|
||||||
love.graphics.printf(self.set_inputs[input], 240, 50 + i * 20, 300, "left")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if self.input_state > table.getn(configurable_inputs) then
|
|
||||||
love.graphics.print("press enter to confirm, delete/backspace to retry" .. (config.input and ", escape to cancel" or ""))
|
|
||||||
else
|
|
||||||
love.graphics.print("press key or joystick input for " .. configurable_inputs[self.input_state] .. ", tab to skip" .. (config.input and ", escape to cancel" or ""), 0, 0)
|
|
||||||
love.graphics.print("function keys (F1, F2, etc.), escape, and tab can't be changed", 0, 20)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.axis_timer = self.axis_timer + 1
|
love.graphics.setFont(font_3x5_2)
|
||||||
|
love.graphics.print("Which controls do you want to configure?", 80, 90)
|
||||||
|
|
||||||
|
love.graphics.setColor(1, 1, 1, 0.5)
|
||||||
|
love.graphics.rectangle("fill", 75, 118 + 50 * self.menu_state, 200, 33)
|
||||||
|
|
||||||
|
love.graphics.setFont(font_3x5_3)
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
for i, screen in pairs(menu_screens) do
|
||||||
|
love.graphics.printf(screen.title, 80, 120 + 50 * i, 200, "left")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function addJoystick(input, name)
|
function ConfigScene:changeOption(rel)
|
||||||
if not input.joysticks then
|
local len = table.getn(menu_screens)
|
||||||
input.joysticks = {}
|
self.menu_state = (self.menu_state + len + rel - 1) % len + 1
|
||||||
end
|
|
||||||
if not input.joysticks[name] then
|
|
||||||
input.joysticks[name] = {}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function ConfigScene:onInputPress(e)
|
function ConfigScene:onInputPress(e)
|
||||||
if e.type == "key" then
|
if e.input == "menu_decide" or e.scancode == "return" then
|
||||||
-- function keys, escape, and tab are reserved and can't be remapped
|
playSE("main_decide")
|
||||||
if e.scancode == "escape" and config.input then
|
scene = menu_screens[self.menu_state]()
|
||||||
-- cancel only if there was an input config already
|
elseif e.input == "up" or e.scancode == "up" then
|
||||||
scene = SettingsScene()
|
self:changeOption(-1)
|
||||||
elseif self.input_state > table.getn(configurable_inputs) then
|
playSE("cursor")
|
||||||
if e.scancode == "return" then
|
elseif e.input == "down" or e.scancode == "down" then
|
||||||
-- save new input, then load next scene
|
self:changeOption(1)
|
||||||
config.input = self.new_input
|
playSE("cursor")
|
||||||
saveConfig()
|
elseif config.input and (
|
||||||
scene = TitleScene()
|
e.input == "menu_back" or e.scancode == "backspace" or e.scancode == "delete"
|
||||||
elseif e.scancode == "delete" or e.scancode == "backspace" then
|
) then
|
||||||
-- retry
|
scene = SettingsScene()
|
||||||
self.input_state = 1
|
|
||||||
self.set_inputs = newSetInputs()
|
|
||||||
self.new_input = {}
|
|
||||||
end
|
|
||||||
elseif e.scancode == "tab" then
|
|
||||||
self.set_inputs[configurable_inputs[self.input_state]] = "skipped"
|
|
||||||
self.input_state = self.input_state + 1
|
|
||||||
elseif e.scancode ~= "escape" then
|
|
||||||
-- all other keys can be configured
|
|
||||||
if not self.new_input.keys then
|
|
||||||
self.new_input.keys = {}
|
|
||||||
end
|
|
||||||
self.set_inputs[configurable_inputs[self.input_state]] = "key " .. love.keyboard.getKeyFromScancode(e.scancode) .. " (" .. e.scancode .. ")"
|
|
||||||
self.new_input.keys[e.scancode] = configurable_inputs[self.input_state]
|
|
||||||
self.input_state = self.input_state + 1
|
|
||||||
end
|
|
||||||
elseif string.sub(e.type, 1, 3) == "joy" then
|
|
||||||
if self.input_state <= table.getn(configurable_inputs) then
|
|
||||||
if e.type == "joybutton" then
|
|
||||||
addJoystick(self.new_input, e.name)
|
|
||||||
if not self.new_input.joysticks[e.name].buttons then
|
|
||||||
self.new_input.joysticks[e.name].buttons = {}
|
|
||||||
end
|
|
||||||
self.set_inputs[configurable_inputs[self.input_state]] =
|
|
||||||
"jbtn " ..
|
|
||||||
e.button ..
|
|
||||||
" " .. string.sub(e.name, 1, 10) .. (string.len(e.name) > 10 and "..." or "")
|
|
||||||
self.new_input.joysticks[e.name].buttons[e.button] = configurable_inputs[self.input_state]
|
|
||||||
self.input_state = self.input_state + 1
|
|
||||||
elseif e.type == "joyaxis" then
|
|
||||||
if (e.axis ~= self.last_axis or self.axis_timer > 30) and math.abs(e.value) >= 1 then
|
|
||||||
addJoystick(self.new_input, e.name)
|
|
||||||
if not self.new_input.joysticks[e.name].axes then
|
|
||||||
self.new_input.joysticks[e.name].axes = {}
|
|
||||||
end
|
|
||||||
if not self.new_input.joysticks[e.name].axes[e.axis] then
|
|
||||||
self.new_input.joysticks[e.name].axes[e.axis] = {}
|
|
||||||
end
|
|
||||||
self.set_inputs[configurable_inputs[self.input_state]] =
|
|
||||||
"jaxis " ..
|
|
||||||
(e.value >= 1 and "+" or "-") .. e.axis ..
|
|
||||||
" " .. string.sub(e.name, 1, 10) .. (string.len(e.name) > 10 and "..." or "")
|
|
||||||
self.new_input.joysticks[e.name].axes[e.axis][e.value >= 1 and "positive" or "negative"] = configurable_inputs[self.input_state]
|
|
||||||
self.input_state = self.input_state + 1
|
|
||||||
self.last_axis = e.axis
|
|
||||||
self.axis_timer = 0
|
|
||||||
end
|
|
||||||
elseif e.type == "joyhat" then
|
|
||||||
if e.direction ~= "c" then
|
|
||||||
addJoystick(self.new_input, e.name)
|
|
||||||
if not self.new_input.joysticks[e.name].hats then
|
|
||||||
self.new_input.joysticks[e.name].hats = {}
|
|
||||||
end
|
|
||||||
if not self.new_input.joysticks[e.name].hats[e.hat] then
|
|
||||||
self.new_input.joysticks[e.name].hats[e.hat] = {}
|
|
||||||
end
|
|
||||||
self.set_inputs[configurable_inputs[self.input_state]] =
|
|
||||||
"jhat " ..
|
|
||||||
e.hat .. " " .. e.direction ..
|
|
||||||
" " .. string.sub(e.name, 1, 10) .. (string.len(e.name) > 10 and "..." or "")
|
|
||||||
self.new_input.joysticks[e.name].hats[e.hat][e.direction] = configurable_inputs[self.input_state]
|
|
||||||
self.input_state = self.input_state + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
100
scene/key_config.lua
Normal file
100
scene/key_config.lua
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
local KeyConfigScene = Scene:extend()
|
||||||
|
|
||||||
|
KeyConfigScene.title = "Key Config"
|
||||||
|
|
||||||
|
require 'load.save'
|
||||||
|
|
||||||
|
local configurable_inputs = {
|
||||||
|
"menu_decide",
|
||||||
|
"menu_back",
|
||||||
|
"left",
|
||||||
|
"right",
|
||||||
|
"up",
|
||||||
|
"down",
|
||||||
|
"rotate_left",
|
||||||
|
"rotate_left2",
|
||||||
|
"rotate_right",
|
||||||
|
"rotate_right2",
|
||||||
|
"rotate_180",
|
||||||
|
"hold",
|
||||||
|
"retry",
|
||||||
|
"pause",
|
||||||
|
}
|
||||||
|
|
||||||
|
local function newSetInputs()
|
||||||
|
local set_inputs = {}
|
||||||
|
for i, input in ipairs(configurable_inputs) do
|
||||||
|
set_inputs[input] = false
|
||||||
|
end
|
||||||
|
return set_inputs
|
||||||
|
end
|
||||||
|
|
||||||
|
function KeyConfigScene:new()
|
||||||
|
self.input_state = 1
|
||||||
|
self.set_inputs = newSetInputs()
|
||||||
|
self.new_input = {}
|
||||||
|
|
||||||
|
DiscordRPC:update({
|
||||||
|
details = "In settings",
|
||||||
|
state = "Changing key config",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function KeyConfigScene:update()
|
||||||
|
end
|
||||||
|
|
||||||
|
function KeyConfigScene:render()
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
love.graphics.draw(
|
||||||
|
backgrounds["input_config"],
|
||||||
|
0, 0, 0,
|
||||||
|
0.5, 0.5
|
||||||
|
)
|
||||||
|
|
||||||
|
love.graphics.setFont(font_3x5_2)
|
||||||
|
for i, input in ipairs(configurable_inputs) do
|
||||||
|
love.graphics.printf(input, 40, 50 + i * 20, 200, "left")
|
||||||
|
if self.set_inputs[input] then
|
||||||
|
love.graphics.printf(self.set_inputs[input], 240, 50 + i * 20, 300, "left")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if self.input_state > table.getn(configurable_inputs) then
|
||||||
|
love.graphics.print("press enter to confirm, delete/backspace to retry" .. (config.input and ", escape to cancel" or ""))
|
||||||
|
else
|
||||||
|
love.graphics.print("press key input for " .. configurable_inputs[self.input_state] .. ", tab to skip, escape to cancel", 0, 0)
|
||||||
|
love.graphics.print("function keys (F1, F2, etc.), escape, and tab can't be changed", 0, 20)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function KeyConfigScene:onInputPress(e)
|
||||||
|
if e.type == "key" then
|
||||||
|
-- function keys, escape, and tab are reserved and can't be remapped
|
||||||
|
if e.scancode == "escape" then
|
||||||
|
scene = InputConfigScene()
|
||||||
|
elseif self.input_state > table.getn(configurable_inputs) then
|
||||||
|
if e.scancode == "return" then
|
||||||
|
-- save new input, then load next scene
|
||||||
|
local had_config = config.input ~= nil
|
||||||
|
if not config.input then config.input = {} end
|
||||||
|
config.input.keys = self.new_input
|
||||||
|
saveConfig()
|
||||||
|
scene = had_config and InputConfigScene() or TitleScene()
|
||||||
|
elseif e.scancode == "delete" or e.scancode == "backspace" then
|
||||||
|
-- retry
|
||||||
|
self.input_state = 1
|
||||||
|
self.set_inputs = newSetInputs()
|
||||||
|
self.new_input = {}
|
||||||
|
end
|
||||||
|
elseif e.scancode == "tab" then
|
||||||
|
self.set_inputs[configurable_inputs[self.input_state]] = "skipped"
|
||||||
|
self.input_state = self.input_state + 1
|
||||||
|
elseif e.scancode ~= "escape" and not self.new_input[e.scancode] then
|
||||||
|
-- all other keys can be configured
|
||||||
|
self.set_inputs[configurable_inputs[self.input_state]] = "key " .. love.keyboard.getKeyFromScancode(e.scancode) .. " (" .. e.scancode .. ")"
|
||||||
|
self.new_input[e.scancode] = configurable_inputs[self.input_state]
|
||||||
|
self.input_state = self.input_state + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return KeyConfigScene
|
@ -6,27 +6,113 @@ current_mode = 1
|
|||||||
current_ruleset = 1
|
current_ruleset = 1
|
||||||
|
|
||||||
function ModeSelectScene:new()
|
function ModeSelectScene:new()
|
||||||
|
-- reload custom modules
|
||||||
|
initModules()
|
||||||
|
if table.getn(game_modes) == 0 or table.getn(rulesets) == 0 then
|
||||||
|
self.display_warning = true
|
||||||
|
current_mode = 1
|
||||||
|
current_ruleset = 1
|
||||||
|
else
|
||||||
|
self.display_warning = false
|
||||||
|
if current_mode > table.getn(game_modes) then
|
||||||
|
current_mode = 1
|
||||||
|
end
|
||||||
|
if current_ruleset > table.getn(rulesets) then
|
||||||
|
current_ruleset = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
self.menu_state = {
|
self.menu_state = {
|
||||||
mode = current_mode,
|
mode = current_mode,
|
||||||
|
mode_list = game_modes,
|
||||||
|
mode_list_history = {},
|
||||||
|
mode_path = (config.mode_path or {}),
|
||||||
ruleset = current_ruleset,
|
ruleset = current_ruleset,
|
||||||
|
rule_list = rulesets,
|
||||||
|
rule_list_history = {},
|
||||||
|
rule_path = config.rule_path,
|
||||||
select = "mode",
|
select = "mode",
|
||||||
}
|
}
|
||||||
self.secret_inputs = {
|
self.secret_inputs = {}
|
||||||
rotate_left = false,
|
self.das = 0
|
||||||
rotate_left2 = false,
|
|
||||||
rotate_right = false,
|
|
||||||
rotate_right2 = false,
|
|
||||||
rotate_180 = false,
|
|
||||||
hold = false,
|
|
||||||
}
|
|
||||||
DiscordRPC:update({
|
DiscordRPC:update({
|
||||||
details = "In menus",
|
details = "In menus",
|
||||||
state = "Choosing a mode",
|
state = "Choosing a mode",
|
||||||
|
largeImageKey = "ingame-000"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
-- grab the filepaths from config to ensure you're dropped off on the correct mode and ruleset
|
||||||
|
local able_to_find = true
|
||||||
|
for _,looking_for in pairs(self.menu_state.mode_path) do
|
||||||
|
if(able_to_find) then
|
||||||
|
local found = false
|
||||||
|
for idx,file in pairs(self.menu_state.mode_list) do
|
||||||
|
if(not found) then
|
||||||
|
if(file.type == "directory" and file.name == looking_for) then
|
||||||
|
table.insert(self.menu_state.mode_list_history,self.menu_state.mode_list)
|
||||||
|
self.menu_state.mode_list = self.menu_state.mode_list[idx].content
|
||||||
|
found = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
able_to_find = (found and able_to_find)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if(not able_to_find) then
|
||||||
|
--directory doesn't exist, revert to default
|
||||||
|
self.menu_state.mode_list = game_modes
|
||||||
|
self.menu_state.mode_list_history = {}
|
||||||
|
self.menu_state.mode_path = {}
|
||||||
|
self.menu_state.mode = 1
|
||||||
|
current_mode = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- do the same with the ruleset
|
||||||
|
local able_to_find = true
|
||||||
|
for _,looking_for in pairs(self.menu_state.rule_path) do
|
||||||
|
if(able_to_find) then
|
||||||
|
local found = false
|
||||||
|
for idx,file in pairs(self.menu_state.rule_list) do
|
||||||
|
if(not found) then
|
||||||
|
if(file.type == "directory" and file.name == looking_for) then
|
||||||
|
table.insert(self.menu_state.rule_list_history,self.menu_state.rule_list)
|
||||||
|
self.menu_state.rule_list = self.menu_state.rule_list[idx].content
|
||||||
|
found = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
able_to_find = (found and able_to_find)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if(not able_to_find) then
|
||||||
|
--directory doesn't exist, revert to default
|
||||||
|
self.menu_state.rule_list = game_modes
|
||||||
|
self.menu_state.rule_list_history = {}
|
||||||
|
self.menu_state.rule_path = {}
|
||||||
|
self.menu_state.rule = 1
|
||||||
|
current_mode = 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ModeSelectScene:update()
|
function ModeSelectScene:update()
|
||||||
switchBGM(nil) -- experimental
|
switchBGM(nil) -- experimental
|
||||||
|
|
||||||
|
if self.das_up or self.das_down then
|
||||||
|
self.das = self.das + 1
|
||||||
|
else
|
||||||
|
self.das = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.das >= 15 then
|
||||||
|
self:changeOption(self.das_up and -1 or 1)
|
||||||
|
self.das = self.das - 4
|
||||||
|
end
|
||||||
|
|
||||||
|
DiscordRPC:update({
|
||||||
|
details = "In menus",
|
||||||
|
state = "Choosing a " .. self.menu_state.select,
|
||||||
|
largeImageKey = "ingame-000"
|
||||||
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function ModeSelectScene:render()
|
function ModeSelectScene:render()
|
||||||
@ -36,6 +122,23 @@ function ModeSelectScene:render()
|
|||||||
0.5, 0.5
|
0.5, 0.5
|
||||||
)
|
)
|
||||||
|
|
||||||
|
love.graphics.draw(misc_graphics["select_mode"], 20, 40)
|
||||||
|
|
||||||
|
if self.display_warning then
|
||||||
|
love.graphics.setFont(font_3x5_3)
|
||||||
|
love.graphics.printf(
|
||||||
|
"You have no modes or rulesets.",
|
||||||
|
80, 200, 480, "center"
|
||||||
|
)
|
||||||
|
love.graphics.setFont(font_3x5_2)
|
||||||
|
love.graphics.printf(
|
||||||
|
"Come back to this menu after getting more modes or rulesets. " ..
|
||||||
|
"Press any button to return to the main menu.",
|
||||||
|
80, 250, 480, "center"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if self.menu_state.select == "mode" then
|
if self.menu_state.select == "mode" then
|
||||||
love.graphics.setColor(1, 1, 1, 0.5)
|
love.graphics.setColor(1, 1, 1, 0.5)
|
||||||
elseif self.menu_state.select == "ruleset" then
|
elseif self.menu_state.select == "ruleset" then
|
||||||
@ -52,39 +155,87 @@ function ModeSelectScene:render()
|
|||||||
|
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
|
||||||
love.graphics.draw(misc_graphics["select_mode"], 20, 40)
|
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_2)
|
love.graphics.setFont(font_3x5_2)
|
||||||
for idx, mode in pairs(game_modes) do
|
for idx, mode in pairs(self.menu_state.mode_list) do
|
||||||
if(idx >= self.menu_state.mode-9 and idx <= self.menu_state.mode+9) then
|
if(idx >= self.menu_state.mode-9 and idx <= self.menu_state.mode+9) then
|
||||||
love.graphics.printf(mode.name, 40, (260 - 20*(self.menu_state.mode)) + 20 * idx, 200, "left")
|
if(mode.type == "directory") then
|
||||||
|
love.graphics.setColor(1,0.5,0,1)
|
||||||
|
elseif(mode.type == "back") then
|
||||||
|
love.graphics.setColor(1,1,0,1)
|
||||||
|
else
|
||||||
|
love.graphics.setColor(1,1,1,1)
|
||||||
|
end
|
||||||
|
love.graphics.printf((mode.type == "file" and mode.content.name or mode.name), 40, (260 - 20*(self.menu_state.mode)) + 20 * idx, 200, "left")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for idx, ruleset in pairs(rulesets) do
|
for idx, ruleset in pairs(self.menu_state.rule_list) do
|
||||||
if(idx >= self.menu_state.ruleset-9 and idx <= self.menu_state.ruleset+9) then
|
if(idx >= self.menu_state.ruleset-9 and idx <= self.menu_state.ruleset+9) then
|
||||||
love.graphics.printf(ruleset.name, 360, (260 - 20*(self.menu_state.ruleset)) + 20 * idx, 160, "left")
|
if(ruleset.type == "directory") then
|
||||||
|
love.graphics.setColor(1,0.5,0,1)
|
||||||
|
elseif(ruleset.type == "back") then
|
||||||
|
love.graphics.setColor(1,1,0,1)
|
||||||
|
else
|
||||||
|
love.graphics.setColor(1,1,1,1)
|
||||||
|
end
|
||||||
|
love.graphics.printf((ruleset.type == "file" and ruleset.content.name or ruleset.name), 360, (260 - 20*(self.menu_state.ruleset)) + 20 * idx, 200, "left")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ModeSelectScene:onInputPress(e)
|
function ModeSelectScene:onInputPress(e)
|
||||||
if e.input == "menu_decide" or e.scancode == "return" then
|
if self.display_warning and e.input then
|
||||||
current_mode = self.menu_state.mode
|
scene = TitleScene()
|
||||||
current_ruleset = self.menu_state.ruleset
|
elseif e.type == "wheel" then
|
||||||
config.current_mode = current_mode
|
if e.x % 2 == 1 then
|
||||||
config.current_ruleset = current_ruleset
|
self:switchSelect()
|
||||||
playSE("mode_decide")
|
end
|
||||||
saveConfig()
|
if e.y ~= 0 then
|
||||||
scene = GameScene(game_modes[self.menu_state.mode], rulesets[self.menu_state.ruleset], self.secret_inputs)
|
self:changeOption(-e.y)
|
||||||
|
end
|
||||||
|
elseif e.input == "menu_decide" or e.scancode == "return" then
|
||||||
|
if self.menu_state.mode_list[self.menu_state.mode].type == "directory" and self.menu_state.select == "mode" then
|
||||||
|
table.insert(self.menu_state.mode_list_history,self.menu_state.mode_list)
|
||||||
|
table.insert(self.menu_state.mode_path,self.menu_state.mode_list[self.menu_state.mode].name)
|
||||||
|
self.menu_state.mode_list = self.menu_state.mode_list[self.menu_state.mode].content
|
||||||
|
self.menu_state.mode = 1
|
||||||
|
elseif self.menu_state.mode_list[self.menu_state.mode].type == "back" and self.menu_state.select == "mode" then
|
||||||
|
table.remove(self.menu_state.mode_path)
|
||||||
|
self.menu_state.mode_list = table.remove(self.menu_state.mode_list_history)
|
||||||
|
self.menu_state.mode = 1
|
||||||
|
elseif self.menu_state.rule_list[self.menu_state.ruleset].type == "directory" and self.menu_state.select == "ruleset" then
|
||||||
|
table.insert(self.menu_state.rule_list_history,self.menu_state.rule_list)
|
||||||
|
table.insert(self.menu_state.rule_path,self.menu_state.rule_list[self.menu_state.ruleset].name)
|
||||||
|
self.menu_state.rule_list = self.menu_state.rule_list[self.menu_state.ruleset].content
|
||||||
|
self.menu_state.ruleset = 1
|
||||||
|
elseif self.menu_state.rule_list[self.menu_state.ruleset].type == "back" and self.menu_state.select == "ruleset" then
|
||||||
|
table.remove(self.menu_state.rule_path)
|
||||||
|
self.menu_state.rule_list = table.remove(self.menu_state.rule_list_history)
|
||||||
|
self.menu_state.ruleset = 1
|
||||||
|
elseif(self.menu_state.mode_list[self.menu_state.mode].type == "file" and self.menu_state.rule_list[self.menu_state.ruleset].type == "file") then -- make sure neither option is on a folder
|
||||||
|
current_mode = self.menu_state.mode
|
||||||
|
current_ruleset = self.menu_state.ruleset
|
||||||
|
config.current_mode = current_mode
|
||||||
|
config.mode_path = self.menu_state.mode_path
|
||||||
|
config.current_ruleset = current_ruleset
|
||||||
|
config.rule_path = self.menu_state.rule_path
|
||||||
|
playSE("mode_decide")
|
||||||
|
saveConfig()
|
||||||
|
scene = GameScene(
|
||||||
|
self.menu_state.mode_list[self.menu_state.mode].content,
|
||||||
|
self.menu_state.rule_list[self.menu_state.ruleset].content,
|
||||||
|
self.secret_inputs
|
||||||
|
)
|
||||||
|
end
|
||||||
elseif e.input == "up" or e.scancode == "up" then
|
elseif e.input == "up" or e.scancode == "up" then
|
||||||
self:changeOption(-1)
|
self:changeOption(-1)
|
||||||
playSE("cursor")
|
self.das_up = true
|
||||||
|
self.das_down = nil
|
||||||
elseif e.input == "down" or e.scancode == "down" then
|
elseif e.input == "down" or e.scancode == "down" then
|
||||||
self:changeOption(1)
|
self:changeOption(1)
|
||||||
playSE("cursor")
|
self.das_down = true
|
||||||
|
self.das_up = nil
|
||||||
elseif e.input == "left" or e.input == "right" or e.scancode == "left" or e.scancode == "right" then
|
elseif e.input == "left" or e.input == "right" or e.scancode == "left" or e.scancode == "right" then
|
||||||
self:switchSelect()
|
self:switchSelect()
|
||||||
playSE("cursor_lr")
|
|
||||||
elseif e.input == "menu_back" or e.scancode == "delete" or e.scancode == "backspace" then
|
elseif e.input == "menu_back" or e.scancode == "delete" or e.scancode == "backspace" then
|
||||||
scene = TitleScene()
|
scene = TitleScene()
|
||||||
elseif e.input then
|
elseif e.input then
|
||||||
@ -93,7 +244,11 @@ function ModeSelectScene:onInputPress(e)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function ModeSelectScene:onInputRelease(e)
|
function ModeSelectScene:onInputRelease(e)
|
||||||
if e.input == "hold" or (e.input and string.sub(e.input, 1, 7) == "rotate_") then
|
if e.input == "up" or e.scancode == "up" then
|
||||||
|
self.das_up = nil
|
||||||
|
elseif e.input == "down" or e.scancode == "down" then
|
||||||
|
self.das_down = nil
|
||||||
|
elseif e.input then
|
||||||
self.secret_inputs[e.input] = false
|
self.secret_inputs[e.input] = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -104,24 +259,26 @@ function ModeSelectScene:changeOption(rel)
|
|||||||
elseif self.menu_state.select == "ruleset" then
|
elseif self.menu_state.select == "ruleset" then
|
||||||
self:changeRuleset(rel)
|
self:changeRuleset(rel)
|
||||||
end
|
end
|
||||||
|
playSE("cursor")
|
||||||
end
|
end
|
||||||
|
|
||||||
function ModeSelectScene:switchSelect(rel)
|
function ModeSelectScene:switchSelect()
|
||||||
if self.menu_state.select == "mode" then
|
if self.menu_state.select == "mode" then
|
||||||
self.menu_state.select = "ruleset"
|
self.menu_state.select = "ruleset"
|
||||||
elseif self.menu_state.select == "ruleset" then
|
elseif self.menu_state.select == "ruleset" then
|
||||||
self.menu_state.select = "mode"
|
self.menu_state.select = "mode"
|
||||||
end
|
end
|
||||||
|
playSE("cursor_lr")
|
||||||
end
|
end
|
||||||
|
|
||||||
function ModeSelectScene:changeMode(rel)
|
function ModeSelectScene:changeMode(rel)
|
||||||
local len = table.getn(game_modes)
|
local len = table.getn(self.menu_state.mode_list)
|
||||||
self.menu_state.mode = (self.menu_state.mode + len + rel - 1) % len + 1
|
self.menu_state.mode = Mod1(self.menu_state.mode + rel, len)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ModeSelectScene:changeRuleset(rel)
|
function ModeSelectScene:changeRuleset(rel)
|
||||||
local len = table.getn(rulesets)
|
local len = table.getn(self.menu_state.rule_list)
|
||||||
self.menu_state.ruleset = (self.menu_state.ruleset + len + rel - 1) % len + 1
|
self.menu_state.ruleset = Mod1(self.menu_state.ruleset + rel, len)
|
||||||
end
|
end
|
||||||
|
|
||||||
return ModeSelectScene
|
return ModeSelectScene
|
||||||
|
@ -8,11 +8,20 @@ local menu_screens = {
|
|||||||
TuningScene
|
TuningScene
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local settingsidle = {
|
||||||
|
"Tweaking some knobs",
|
||||||
|
"Tuning up",
|
||||||
|
"Adjusting options",
|
||||||
|
"Setting up",
|
||||||
|
"Setting the settings"
|
||||||
|
}
|
||||||
|
|
||||||
function SettingsScene:new()
|
function SettingsScene:new()
|
||||||
self.menu_state = 1
|
self.menu_state = 1
|
||||||
DiscordRPC:update({
|
DiscordRPC:update({
|
||||||
details = "In menus",
|
details = "In settings",
|
||||||
state = "Changing settings",
|
state = settingsidle[math.random(#settingsidle)],
|
||||||
|
largeImageKey = "settings",
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
159
scene/stick_config.lua
Normal file
159
scene/stick_config.lua
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
local StickConfigScene = Scene:extend()
|
||||||
|
|
||||||
|
StickConfigScene.title = "Joystick Config"
|
||||||
|
|
||||||
|
require 'load.save'
|
||||||
|
|
||||||
|
local configurable_inputs = {
|
||||||
|
"menu_decide",
|
||||||
|
"menu_back",
|
||||||
|
"left",
|
||||||
|
"right",
|
||||||
|
"up",
|
||||||
|
"down",
|
||||||
|
"rotate_left",
|
||||||
|
"rotate_left2",
|
||||||
|
"rotate_right",
|
||||||
|
"rotate_right2",
|
||||||
|
"rotate_180",
|
||||||
|
"hold",
|
||||||
|
"retry",
|
||||||
|
"pause",
|
||||||
|
}
|
||||||
|
|
||||||
|
local function newSetInputs()
|
||||||
|
local set_inputs = {}
|
||||||
|
for i, input in ipairs(configurable_inputs) do
|
||||||
|
set_inputs[input] = false
|
||||||
|
end
|
||||||
|
return set_inputs
|
||||||
|
end
|
||||||
|
|
||||||
|
function StickConfigScene:new()
|
||||||
|
self.input_state = 1
|
||||||
|
self.set_inputs = newSetInputs()
|
||||||
|
self.new_input = {}
|
||||||
|
self.axis_timer = 0
|
||||||
|
|
||||||
|
DiscordRPC:update({
|
||||||
|
details = "In settings",
|
||||||
|
state = "Changing joystick config",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function StickConfigScene:update()
|
||||||
|
end
|
||||||
|
|
||||||
|
function StickConfigScene:render()
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
love.graphics.draw(
|
||||||
|
backgrounds["input_config"],
|
||||||
|
0, 0, 0,
|
||||||
|
0.5, 0.5
|
||||||
|
)
|
||||||
|
|
||||||
|
love.graphics.setFont(font_3x5_2)
|
||||||
|
for i, input in ipairs(configurable_inputs) do
|
||||||
|
love.graphics.printf(input, 40, 50 + i * 20, 200, "left")
|
||||||
|
if self.set_inputs[input] then
|
||||||
|
love.graphics.printf(self.set_inputs[input], 240, 50 + i * 20, 300, "left")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if self.input_state > table.getn(configurable_inputs) then
|
||||||
|
love.graphics.print("press enter to confirm, delete/backspace to retry" .. (config.input and ", escape to cancel" or ""))
|
||||||
|
else
|
||||||
|
love.graphics.print("press joystick input for " .. configurable_inputs[self.input_state] .. ", tab to skip, escape to cancel", 0, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.axis_timer = self.axis_timer + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local function addJoystick(input, name)
|
||||||
|
if not input[name] then
|
||||||
|
input[name] = {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function StickConfigScene:onInputPress(e)
|
||||||
|
if e.type == "key" then
|
||||||
|
-- function keys, escape, and tab are reserved and can't be remapped
|
||||||
|
if e.scancode == "escape" then
|
||||||
|
scene = InputConfigScene()
|
||||||
|
elseif self.input_state > table.getn(configurable_inputs) then
|
||||||
|
if e.scancode == "return" then
|
||||||
|
-- save new input, then load next scene
|
||||||
|
local had_config = config.input ~= nil
|
||||||
|
if not config.input then config.input = {} end
|
||||||
|
config.input.joysticks = self.new_input
|
||||||
|
saveConfig()
|
||||||
|
scene = had_config and InputConfigScene() or TitleScene()
|
||||||
|
elseif e.scancode == "delete" or e.scancode == "backspace" then
|
||||||
|
-- retry
|
||||||
|
self.input_state = 1
|
||||||
|
self.set_inputs = newSetInputs()
|
||||||
|
self.new_input = {}
|
||||||
|
end
|
||||||
|
elseif e.scancode == "tab" then
|
||||||
|
self.set_inputs[configurable_inputs[self.input_state]] = "skipped"
|
||||||
|
self.input_state = self.input_state + 1
|
||||||
|
end
|
||||||
|
elseif string.sub(e.type, 1, 3) == "joy" then
|
||||||
|
if self.input_state <= table.getn(configurable_inputs) then
|
||||||
|
if e.type == "joybutton" then
|
||||||
|
addJoystick(self.new_input, e.name)
|
||||||
|
if not self.new_input[e.name].buttons then
|
||||||
|
self.new_input[e.name].buttons = {}
|
||||||
|
end
|
||||||
|
if self.new_input[e.name].buttons[e.button] then return end
|
||||||
|
self.set_inputs[configurable_inputs[self.input_state]] =
|
||||||
|
"jbtn " ..
|
||||||
|
e.button ..
|
||||||
|
" " .. string.sub(e.name, 1, 10) .. (string.len(e.name) > 10 and "..." or "")
|
||||||
|
self.new_input[e.name].buttons[e.button] = configurable_inputs[self.input_state]
|
||||||
|
self.input_state = self.input_state + 1
|
||||||
|
elseif e.type == "joyaxis" then
|
||||||
|
if (e.axis ~= self.last_axis or self.axis_timer > 30) and math.abs(e.value) >= 1 then
|
||||||
|
addJoystick(self.new_input, e.name)
|
||||||
|
if not self.new_input[e.name].axes then
|
||||||
|
self.new_input[e.name].axes = {}
|
||||||
|
end
|
||||||
|
if not self.new_input[e.name].axes[e.axis] then
|
||||||
|
self.new_input[e.name].axes[e.axis] = {}
|
||||||
|
end
|
||||||
|
if (
|
||||||
|
self.new_input[e.name].axes[e.axis][e.value >= 1 and "positive" or "negative"]
|
||||||
|
) then return end
|
||||||
|
self.set_inputs[configurable_inputs[self.input_state]] =
|
||||||
|
"jaxis " ..
|
||||||
|
(e.value >= 1 and "+" or "-") .. e.axis ..
|
||||||
|
" " .. string.sub(e.name, 1, 10) .. (string.len(e.name) > 10 and "..." or "")
|
||||||
|
self.new_input[e.name].axes[e.axis][e.value >= 1 and "positive" or "negative"] = configurable_inputs[self.input_state]
|
||||||
|
self.input_state = self.input_state + 1
|
||||||
|
self.last_axis = e.axis
|
||||||
|
self.axis_timer = 0
|
||||||
|
end
|
||||||
|
elseif e.type == "joyhat" then
|
||||||
|
if e.direction ~= "c" then
|
||||||
|
addJoystick(self.new_input, e.name)
|
||||||
|
if not self.new_input[e.name].hats then
|
||||||
|
self.new_input[e.name].hats = {}
|
||||||
|
end
|
||||||
|
if not self.new_input[e.name].hats[e.hat] then
|
||||||
|
self.new_input[e.name].hats[e.hat] = {}
|
||||||
|
end
|
||||||
|
if self.new_input[e.name].hats[e.hat][e.direction] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.set_inputs[configurable_inputs[self.input_state]] =
|
||||||
|
"jhat " ..
|
||||||
|
e.hat .. " " .. e.direction ..
|
||||||
|
" " .. string.sub(e.name, 1, 10) .. (string.len(e.name) > 10 and "..." or "")
|
||||||
|
self.new_input[e.name].hats[e.hat][e.direction] = configurable_inputs[self.input_state]
|
||||||
|
self.input_state = self.input_state + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return StickConfigScene
|
@ -23,6 +23,15 @@ local mainmenuidle = {
|
|||||||
"Having a nap",
|
"Having a nap",
|
||||||
"In menus",
|
"In menus",
|
||||||
"Bottom text",
|
"Bottom text",
|
||||||
|
"Trying to see all the funny rpc messages (maybe)",
|
||||||
|
"Not not not playing",
|
||||||
|
"AFK",
|
||||||
|
"Preparing for their next game",
|
||||||
|
"Who are those people on that boat?",
|
||||||
|
"Welcome to Cambridge!",
|
||||||
|
"who even reads these",
|
||||||
|
"Made with love in LOVE!",
|
||||||
|
"This is probably the longest RPC string out of every possible RPC string that can be displayed."
|
||||||
}
|
}
|
||||||
|
|
||||||
function TitleScene:new()
|
function TitleScene:new()
|
||||||
@ -35,6 +44,8 @@ function TitleScene:new()
|
|||||||
DiscordRPC:update({
|
DiscordRPC:update({
|
||||||
details = "In menus",
|
details = "In menus",
|
||||||
state = mainmenuidle[math.random(#mainmenuidle)],
|
state = mainmenuidle[math.random(#mainmenuidle)],
|
||||||
|
largeImageKey = "icon2",
|
||||||
|
largeImageText = version
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -82,7 +93,6 @@ function TitleScene:render()
|
|||||||
for i, screen in pairs(main_menu_screens) do
|
for i, screen in pairs(main_menu_screens) do
|
||||||
love.graphics.printf(screen.title, 40, 280 + 20 * i, 120, "left")
|
love.graphics.printf(screen.title, 40, 280 + 20 * i, 120, "left")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function TitleScene:changeOption(rel)
|
function TitleScene:changeOption(rel)
|
||||||
@ -106,6 +116,9 @@ function TitleScene:onInputPress(e)
|
|||||||
self.text = self.text .. (e.scancode ~= nil and e.scancode or "")
|
self.text = self.text .. (e.scancode ~= nil and e.scancode or "")
|
||||||
if self.text == "ffffff" then
|
if self.text == "ffffff" then
|
||||||
self.text_flag = true
|
self.text_flag = true
|
||||||
|
DiscordRPC:update({
|
||||||
|
largeImageKey = "snow"
|
||||||
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -16,7 +16,7 @@ local optioncount = #TuningScene.options
|
|||||||
|
|
||||||
function TuningScene:new()
|
function TuningScene:new()
|
||||||
DiscordRPC:update({
|
DiscordRPC:update({
|
||||||
details = "In menus",
|
details = "In settings",
|
||||||
state = "Changing tuning settings",
|
state = "Changing tuning settings",
|
||||||
})
|
})
|
||||||
self.highlight = 1
|
self.highlight = 1
|
||||||
|
@ -111,18 +111,24 @@ function Grid:getClearedRowCount()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Grid:markClearedRows()
|
function Grid:markClearedRows()
|
||||||
|
local block_table = {}
|
||||||
for row = 1, self.height do
|
for row = 1, self.height do
|
||||||
if self:isRowFull(row) then
|
if self:isRowFull(row) then
|
||||||
|
block_table[row] = {}
|
||||||
for x = 1, self.width do
|
for x = 1, self.width do
|
||||||
|
block_table[row][x] = {
|
||||||
|
skin = self.grid[row][x].skin,
|
||||||
|
colour = self.grid[row][x].colour,
|
||||||
|
}
|
||||||
self.grid[row][x] = {
|
self.grid[row][x] = {
|
||||||
skin = self.grid[row][x].skin,
|
skin = self.grid[row][x].skin,
|
||||||
colour = "X"
|
colour = "X"
|
||||||
}
|
}
|
||||||
self.grid_age[row][x] = 0
|
--self.grid_age[row][x] = 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return true
|
return block_table
|
||||||
end
|
end
|
||||||
|
|
||||||
function Grid:clearClearedRows()
|
function Grid:clearClearedRows()
|
||||||
@ -201,7 +207,7 @@ function Grid:applyBigPiece(piece)
|
|||||||
y = piece.position.y + offset.y
|
y = piece.position.y + offset.y
|
||||||
for a = 1, 2 do
|
for a = 1, 2 do
|
||||||
for b = 1, 2 do
|
for b = 1, 2 do
|
||||||
if y*2+a > 0 then
|
if y*2+a > 0 and y*2 < self.height then
|
||||||
self.grid[y*2+a][x*2+b] = {
|
self.grid[y*2+a][x*2+b] = {
|
||||||
skin = piece.skin,
|
skin = piece.skin,
|
||||||
colour = piece.colour
|
colour = piece.colour
|
||||||
@ -343,7 +349,7 @@ function Grid:markSquares()
|
|||||||
elseif i == 2 then
|
elseif i == 2 then
|
||||||
for j = 0, 3 do
|
for j = 0, 3 do
|
||||||
for k = 0, 3 do
|
for k = 0, 3 do
|
||||||
self.grid[y+j][x+k].colour = "F"
|
self.grid[y+j][x+k].colour = "W"
|
||||||
self.grid[y+j][x+k].skin = "square"
|
self.grid[y+j][x+k].skin = "square"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -388,15 +394,16 @@ end
|
|||||||
function Grid:draw()
|
function Grid:draw()
|
||||||
for y = 5, self.height do
|
for y = 5, self.height do
|
||||||
for x = 1, self.width do
|
for x = 1, self.width do
|
||||||
if self.grid[y][x] ~= empty then
|
if blocks[self.grid[y][x].skin] and
|
||||||
|
blocks[self.grid[y][x].skin][self.grid[y][x].colour] then
|
||||||
if self.grid_age[y][x] < 2 then
|
if self.grid_age[y][x] < 2 then
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
love.graphics.draw(blocks[self.grid[y][x].skin]["F"], 48+x*16, y*16)
|
love.graphics.draw(blocks[self.grid[y][x].skin]["F"], 48+x*16, y*16)
|
||||||
else
|
else
|
||||||
if self.grid[y][x].skin == "bone" then
|
if self.grid[y][x].colour == "X" then
|
||||||
|
love.graphics.setColor(0, 0, 0, 0)
|
||||||
|
elseif self.grid[y][x].skin == "bone" then
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
elseif self.grid[y][x].colour == "X" then
|
|
||||||
love.graphics.setColor(0.5, 0.5, 0.5, 1 - self.grid_age[y][x] / 15)
|
|
||||||
else
|
else
|
||||||
love.graphics.setColor(0.5, 0.5, 0.5, 1)
|
love.graphics.setColor(0.5, 0.5, 0.5, 1)
|
||||||
end
|
end
|
||||||
@ -405,11 +412,11 @@ function Grid:draw()
|
|||||||
if self.grid[y][x].skin ~= "bone" and self.grid[y][x].colour ~= "X" then
|
if self.grid[y][x].skin ~= "bone" and self.grid[y][x].colour ~= "X" then
|
||||||
love.graphics.setColor(0.8, 0.8, 0.8, 1)
|
love.graphics.setColor(0.8, 0.8, 0.8, 1)
|
||||||
love.graphics.setLineWidth(1)
|
love.graphics.setLineWidth(1)
|
||||||
if y > 1 and self.grid[y-1][x] == empty or self.grid[y-1][x].colour == "X" then
|
if y > 5 and self.grid[y-1][x] == empty or self.grid[y-1][x].colour == "X" then
|
||||||
love.graphics.line(48.0+x*16, -0.5+y*16, 64.0+x*16, -0.5+y*16)
|
love.graphics.line(48.0+x*16, -0.5+y*16, 64.0+x*16, -0.5+y*16)
|
||||||
end
|
end
|
||||||
if y < self.height and self.grid[y+1][x] == empty or
|
if y < self.height and self.grid[y+1][x] == empty or
|
||||||
(y + 1 > self.height or self.grid[y+1][x].colour == "X") then
|
(y + 1 <= self.height and self.grid[y+1][x].colour == "X") then
|
||||||
love.graphics.line(48.0+x*16, 16.5+y*16, 64.0+x*16, 16.5+y*16)
|
love.graphics.line(48.0+x*16, 16.5+y*16, 64.0+x*16, 16.5+y*16)
|
||||||
end
|
end
|
||||||
if x > 1 and self.grid[y][x-1] == empty then
|
if x > 1 and self.grid[y][x-1] == empty then
|
||||||
@ -427,18 +434,14 @@ end
|
|||||||
function Grid:drawOutline()
|
function Grid:drawOutline()
|
||||||
for y = 5, self.height do
|
for y = 5, self.height do
|
||||||
for x = 1, self.width do
|
for x = 1, self.width do
|
||||||
if self.grid[y][x].colour == "X" then
|
|
||||||
love.graphics.setColor(0.5, 0.5, 0.5, 1 - self.grid_age[y][x] / 15)
|
|
||||||
love.graphics.draw(blocks[self.grid[y][x].skin][self.grid[y][x].colour], 48+x*16, y*16)
|
|
||||||
end
|
|
||||||
if self.grid[y][x] ~= empty and self.grid[y][x].colour ~= "X" then
|
if self.grid[y][x] ~= empty and self.grid[y][x].colour ~= "X" then
|
||||||
love.graphics.setColor(0.8, 0.8, 0.8, 1)
|
love.graphics.setColor(0.8, 0.8, 0.8, 1)
|
||||||
love.graphics.setLineWidth(1)
|
love.graphics.setLineWidth(1)
|
||||||
if y > 1 and self.grid[y-1][x] == empty or self.grid[y-1][x].colour == "X" then
|
if y > 5 and self.grid[y-1][x] == empty or self.grid[y-1][x].colour == "X" then
|
||||||
love.graphics.line(48.0+x*16, -0.5+y*16, 64.0+x*16, -0.5+y*16)
|
love.graphics.line(48.0+x*16, -0.5+y*16, 64.0+x*16, -0.5+y*16)
|
||||||
end
|
end
|
||||||
if y < self.height and self.grid[y+1][x] == empty or
|
if y < self.height and self.grid[y+1][x] == empty or
|
||||||
(y + 1 > self.height or self.grid[y+1][x].colour == "X") then
|
(y + 1 <= self.height and self.grid[y+1][x].colour == "X") then
|
||||||
love.graphics.line(48.0+x*16, 16.5+y*16, 64.0+x*16, 16.5+y*16)
|
love.graphics.line(48.0+x*16, 16.5+y*16, 64.0+x*16, 16.5+y*16)
|
||||||
end
|
end
|
||||||
if x > 1 and self.grid[y][x-1] == empty then
|
if x > 1 and self.grid[y][x-1] == empty then
|
||||||
@ -459,7 +462,7 @@ function Grid:drawInvisible(opacity_function, garbage_opacity_function, lock_fla
|
|||||||
for x = 1, self.width do
|
for x = 1, self.width do
|
||||||
if self.grid[y][x] ~= empty then
|
if self.grid[y][x] ~= empty then
|
||||||
if self.grid[y][x].colour == "X" then
|
if self.grid[y][x].colour == "X" then
|
||||||
opacity = 1 - self.grid_age[y][x] / 15
|
opacity = 0
|
||||||
elseif garbage_opacity_function and self.grid[y][x].colour == "A" then
|
elseif garbage_opacity_function and self.grid[y][x].colour == "A" then
|
||||||
opacity = garbage_opacity_function(self.grid_age[y][x])
|
opacity = garbage_opacity_function(self.grid_age[y][x])
|
||||||
else
|
else
|
||||||
@ -471,11 +474,11 @@ function Grid:drawInvisible(opacity_function, garbage_opacity_function, lock_fla
|
|||||||
if opacity > 0 and self.grid[y][x].colour ~= "X" then
|
if opacity > 0 and self.grid[y][x].colour ~= "X" then
|
||||||
love.graphics.setColor(0.64, 0.64, 0.64)
|
love.graphics.setColor(0.64, 0.64, 0.64)
|
||||||
love.graphics.setLineWidth(1)
|
love.graphics.setLineWidth(1)
|
||||||
if y > 1 and self.grid[y-1][x] == empty or self.grid[y-1][x].colour == "X" then
|
if y > 5 and self.grid[y-1][x] == empty or self.grid[y-1][x].colour == "X" then
|
||||||
love.graphics.line(48.0+x*16, -0.5+y*16, 64.0+x*16, -0.5+y*16)
|
love.graphics.line(48.0+x*16, -0.5+y*16, 64.0+x*16, -0.5+y*16)
|
||||||
end
|
end
|
||||||
if y < self.height and self.grid[y+1][x] == empty or
|
if y < self.height and self.grid[y+1][x] == empty or
|
||||||
(y + 1 > self.height or self.grid[y+1][x].colour == "X") then
|
(y + 1 <= self.height and self.grid[y+1][x].colour == "X") then
|
||||||
love.graphics.line(48.0+x*16, 16.5+y*16, 64.0+x*16, 16.5+y*16)
|
love.graphics.line(48.0+x*16, 16.5+y*16, 64.0+x*16, 16.5+y*16)
|
||||||
end
|
end
|
||||||
if x > 1 and self.grid[y][x-1] == empty then
|
if x > 1 and self.grid[y][x-1] == empty then
|
||||||
@ -506,18 +509,18 @@ function Grid:drawCustom(colour_function, gamestate)
|
|||||||
if block ~= empty then
|
if block ~= empty then
|
||||||
local R, G, B, A, outline = colour_function(gamestate, block, x, y, self.grid_age[y][x])
|
local R, G, B, A, outline = colour_function(gamestate, block, x, y, self.grid_age[y][x])
|
||||||
if self.grid[y][x].colour == "X" then
|
if self.grid[y][x].colour == "X" then
|
||||||
A = 1 - self.grid_age[y][x] / 15
|
A = 0
|
||||||
end
|
end
|
||||||
love.graphics.setColor(R, G, B, A)
|
love.graphics.setColor(R, G, B, A)
|
||||||
love.graphics.draw(blocks[self.grid[y][x].skin][self.grid[y][x].colour], 48+x*16, y*16)
|
love.graphics.draw(blocks[self.grid[y][x].skin][self.grid[y][x].colour], 48+x*16, y*16)
|
||||||
if outline > 0 and self.grid[y][x].colour ~= "X" then
|
if outline > 0 and self.grid[y][x].colour ~= "X" then
|
||||||
love.graphics.setColor(0.64, 0.64, 0.64, outline)
|
love.graphics.setColor(0.64, 0.64, 0.64, outline)
|
||||||
love.graphics.setLineWidth(1)
|
love.graphics.setLineWidth(1)
|
||||||
if y > 1 and self.grid[y-1][x] == empty or self.grid[y-1][x].colour == "X" then
|
if y > 5 and self.grid[y-1][x] == empty or self.grid[y-1][x].colour == "X" then
|
||||||
love.graphics.line(48.0+x*16, -0.5+y*16, 64.0+x*16, -0.5+y*16)
|
love.graphics.line(48.0+x*16, -0.5+y*16, 64.0+x*16, -0.5+y*16)
|
||||||
end
|
end
|
||||||
if y < self.height and self.grid[y+1][x] == empty or
|
if y < self.height and self.grid[y+1][x] == empty or
|
||||||
(y + 1 > self.height or self.grid[y+1][x].colour == "X") then
|
(y + 1 <= self.height and self.grid[y+1][x].colour == "X") then
|
||||||
love.graphics.line(48.0+x*16, 16.5+y*16, 64.0+x*16, 16.5+y*16)
|
love.graphics.line(48.0+x*16, 16.5+y*16, 64.0+x*16, 16.5+y*16)
|
||||||
end
|
end
|
||||||
if x > 1 and self.grid[y][x-1] == empty then
|
if x > 1 and self.grid[y][x-1] == empty then
|
||||||
|
@ -104,9 +104,8 @@ function Piece:dropToBottom(grid)
|
|||||||
self:dropSquares(math.huge, grid)
|
self:dropSquares(math.huge, grid)
|
||||||
self.gravity = 0
|
self.gravity = 0
|
||||||
if self.position.y > piece_y then
|
if self.position.y > piece_y then
|
||||||
-- if it got dropped any, also reset lock delay
|
|
||||||
if self.ghost == false then playSE("bottom") end
|
if self.ghost == false then playSE("bottom") end
|
||||||
self.lock_delay = 0
|
-- self.lock_delay = 0
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -118,19 +117,37 @@ function Piece:lockIfBottomed(grid)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function Piece:addGravity(gravity, grid)
|
function Piece:addGravity(gravity, grid, classic_lock)
|
||||||
|
gravity = gravity / (self.big and 2 or 1)
|
||||||
local new_gravity = self.gravity + gravity
|
local new_gravity = self.gravity + gravity
|
||||||
if self:isDropBlocked(grid) then
|
if self:isDropBlocked(grid) then
|
||||||
self.gravity = math.min(1, new_gravity)
|
if classic_lock then
|
||||||
self.lock_delay = self.lock_delay + 1
|
self.gravity = new_gravity
|
||||||
else
|
else
|
||||||
local dropped_squares = math.floor(new_gravity)
|
self.gravity = 0
|
||||||
local new_frac_gravity = new_gravity - dropped_squares
|
self.lock_delay = self.lock_delay + 1
|
||||||
self.gravity = new_frac_gravity
|
|
||||||
self:dropSquares(dropped_squares, grid)
|
|
||||||
if self:isDropBlocked(grid) then
|
|
||||||
playSE("bottom")
|
|
||||||
end
|
end
|
||||||
|
elseif not (
|
||||||
|
self:isMoveBlocked(grid, { x=0, y=-1 }) and gravity < 0
|
||||||
|
) then
|
||||||
|
local dropped_squares = math.floor(math.abs(new_gravity))
|
||||||
|
if gravity >= 0 then
|
||||||
|
local new_frac_gravity = new_gravity - dropped_squares
|
||||||
|
self.gravity = new_frac_gravity
|
||||||
|
self:dropSquares(dropped_squares, grid)
|
||||||
|
if self:isDropBlocked(grid) then
|
||||||
|
playSE("bottom")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local new_frac_gravity = new_gravity + dropped_squares
|
||||||
|
self.gravity = new_frac_gravity
|
||||||
|
self:moveInGrid({ x=0, y=-1 }, dropped_squares, grid)
|
||||||
|
if self:isMoveBlocked(grid, { x=0, y=-1 }) then
|
||||||
|
playSE("bottom")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.gravity = 0
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user