cambridge/main.lua

409 lines
12 KiB
Lua
Raw Normal View History

function love.load()
2019-05-22 22:57:34 -05:00
math.randomseed(os.time())
highscores = {}
require "load.rpc"
2019-05-22 22:57:34 -05:00
require "load.graphics"
require "load.fonts"
require "load.sounds"
require "load.bgm"
require "load.save"
require "load.bigint"
2021-03-03 09:33:10 -06:00
require "load.version"
2019-05-22 22:57:34 -05:00
loadSave()
require "funcs"
2019-05-22 22:57:34 -05:00
require "scene"
2020-12-20 08:45:49 -06:00
--config["side_next"] = false
--config["reverse_rotate"] = true
--config["das_last_key"] = false
--config["fullscreen"] = false
2021-08-20 12:44:01 -05:00
runsystem = {
drawfps = 0,
updatefps = 0,
updatedelta = 0,
showperformancestatistics = false
}
love.window.setMode(love.graphics.getWidth(), love.graphics.getHeight(), {resizable = true});
-- used for screenshots
GLOBAL_CANVAS = love.graphics.newCanvas()
-- init config
2021-03-11 08:24:19 -06:00
initConfig()
2021-03-11 08:24:19 -06:00
love.window.setFullscreen(config["fullscreen"])
if config.secret then playSE("welcome") end
2021-03-11 08:24:19 -06:00
-- import custom modules
initModules()
end
2021-03-11 08:24:19 -06:00
function initModules()
game_modes = {}
mode_list = love.filesystem.getDirectoryItems("tetris/modes")
for i=1,#mode_list do
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))
end
end
rulesets = {}
rule_list = love.filesystem.getDirectoryItems("tetris/rulesets")
for i=1,#rule_list do
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))
end
end
--sort mode/rule lists
local function padnum(d) return ("%03d%s"):format(#d, d) end
2020-11-08 15:19:01 -06:00
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)
2020-11-08 15:19:01 -06:00
return tostring(a.name):gsub("%d+",padnum) < tostring(b.name):gsub("%d+",padnum) end)
2019-05-22 22:57:34 -05:00
end
function love.draw()
love.graphics.setCanvas(GLOBAL_CANVAS)
love.graphics.clear()
love.graphics.push()
2020-10-09 17:43:22 -05:00
-- get offset matrix
love.graphics.setDefaultFilter("linear", "nearest")
local width = love.graphics.getWidth()
local height = love.graphics.getHeight()
local scale_factor = math.min(width / 640, height / 480)
love.graphics.translate(
(width - scale_factor * 640) / 2,
(height - scale_factor * 480) / 2
)
love.graphics.scale(scale_factor)
2019-05-22 22:57:34 -05:00
scene:render()
2021-08-20 12:44:01 -05:00
if runsystem.showperformancestatistics then
love.graphics.setColor(1, 1, 1, 1)
love.graphics.print('u='..tostring(runsystem.updatefps)..
'\nd='..tostring(runsystem.drawfps)..
'\ndel='..tostring(runsystem.updatedelta), 0, 0)
end
2019-05-22 22:57:34 -05:00
love.graphics.pop()
love.graphics.setCanvas()
love.graphics.setColor(1,1,1,1)
love.graphics.draw(GLOBAL_CANVAS)
2019-05-22 22:57:34 -05:00
end
function love.keypressed(key, scancode)
2019-05-22 22:57:34 -05:00
-- global hotkeys
if scancode == "f4" then
config["fullscreen"] = not config["fullscreen"]
saveConfig()
2019-05-22 22:57:34 -05:00
love.window.setFullscreen(config["fullscreen"])
elseif scancode == "f2" and scene.title ~= "Input Config" and scene.title ~= "Game" then
scene = InputConfigScene()
switchBGM(nil)
2020-12-19 19:31:14 -06:00
-- secret sound playing :eyes:
elseif scancode == "f8" and scene.title == "Title" then
config.secret = not config.secret
saveConfig()
2020-12-19 19:43:57 -06:00
scene.restart_message = true
2020-12-19 19:31:14 -06:00
if config.secret then playSE("mode_decide")
else playSE("erase") end
2021-08-20 12:44:01 -05:00
-- f12 is reserved for saving screenshots
elseif scancode == "f12" then
local ss_name = os.date("ss/%Y-%m-%d_%H-%M-%S.png")
2021-06-03 15:00:33 -05:00
local info = love.filesystem.getInfo("ss", "directory")
if not info then
2021-03-01 19:37:44 -06:00
love.filesystem.remove("ss")
love.filesystem.createDirectory("ss")
end
print("Saving screenshot as "..ss_name)
GLOBAL_CANVAS:newImageData():encode("png", ss_name)
2021-08-20 12:44:01 -05:00
-- F9 toggles performance statistics for the new runsystem
elseif scancode == "f9" then
runsystem.showperformancestatistics = not runsystem.showperformancestatistics
-- function keys are reserved
elseif string.match(scancode, "^f[1-9]$") or string.match(scancode, "^f[1-9][0-9]+$") then
return
-- escape is reserved for menu_back
elseif scancode == "escape" then
scene:onInputPress({input="menu_back", type="key", key=key, scancode=scancode})
-- pass any other key to the scene, with its configured mapping
2019-05-22 22:57:34 -05:00
else
2020-11-08 15:19:01 -06:00
local input_pressed = nil
if config.input and config.input.keys then
input_pressed = config.input.keys[scancode]
end
scene:onInputPress({input=input_pressed, type="key", key=key, scancode=scancode})
2019-05-22 22:57:34 -05:00
end
end
function love.keyreleased(key, scancode)
-- escape is reserved for menu_back
if scancode == "escape" then
2020-11-08 15:19:01 -06:00
scene:onInputRelease({input="menu_back", type="key", key=key, scancode=scancode})
-- function keys are reserved
elseif string.match(scancode, "^f[1-9]$") or string.match(scancode, "^f[1-9][0-9]+$") then
return
-- handle all other keys; tab is reserved, but the input config scene keeps it from getting configured as a game input, so pass tab to the scene here
else
2020-11-08 15:19:01 -06:00
local input_released = nil
if config.input and config.input.keys then
input_released = config.input.keys[scancode]
end
scene:onInputRelease({input=input_released, type="key", key=key, scancode=scancode})
end
end
function love.joystickpressed(joystick, button)
2020-11-08 15:19:01 -06:00
local input_pressed = nil
if
config.input and
config.input.joysticks and
config.input.joysticks[joystick:getName()] and
config.input.joysticks[joystick:getName()].buttons
then
input_pressed = config.input.joysticks[joystick:getName()].buttons[button]
end
scene:onInputPress({input=input_pressed, type="joybutton", name=joystick:getName(), button=button})
end
function love.joystickreleased(joystick, button)
2020-11-08 15:19:01 -06:00
local input_released = nil
if
config.input and
config.input.joysticks and
config.input.joysticks[joystick:getName()] and
config.input.joysticks[joystick:getName()].buttons
then
input_released = config.input.joysticks[joystick:getName()].buttons[button]
end
scene:onInputRelease({input=input_released, type="joybutton", name=joystick:getName(), button=button})
end
function love.joystickaxis(joystick, axis, value)
2020-11-08 15:19:01 -06:00
local input_pressed = nil
local positive_released = nil
local negative_released = nil
if
config.input and
config.input.joysticks and
config.input.joysticks[joystick:getName()] and
config.input.joysticks[joystick:getName()].axes and
config.input.joysticks[joystick:getName()].axes[axis]
then
2021-02-24 15:58:42 -06:00
if math.abs(value) >= 1 then
input_pressed = config.input.joysticks[joystick:getName()].axes[axis][value >= 1 and "positive" or "negative"]
2020-11-08 15:19:01 -06:00
end
positive_released = config.input.joysticks[joystick:getName()].axes[axis].positive
negative_released = config.input.joysticks[joystick:getName()].axes[axis].negative
end
2021-02-24 15:58:42 -06:00
if math.abs(value) >= 1 then
2020-11-08 15:19:01 -06:00
scene:onInputPress({input=input_pressed, type="joyaxis", name=joystick:getName(), axis=axis, value=value})
else
scene:onInputRelease({input=positive_released, type="joyaxis", name=joystick:getName(), axis=axis, value=value})
scene:onInputRelease({input=negative_released, type="joyaxis", name=joystick:getName(), axis=axis, value=value})
end
end
2021-03-07 15:42:33 -06:00
local last_hat_direction = ""
2021-03-07 19:43:55 -06:00
local directions = {
["u"] = "up",
["d"] = "down",
["l"] = "left",
["r"] = "right",
}
2021-03-07 15:42:33 -06:00
function love.joystickhat(joystick, hat, direction)
2020-11-08 15:19:01 -06:00
local input_pressed = nil
local has_hat = false
if
config.input and
config.input.joysticks and
config.input.joysticks[joystick:getName()] and
config.input.joysticks[joystick:getName()].hats and
config.input.joysticks[joystick:getName()].hats[hat]
then
if direction ~= "c" then
input_pressed = config.input.joysticks[joystick:getName()].hats[hat][direction]
end
has_hat = true
end
if input_pressed then
2021-03-07 15:42:33 -06:00
for i = 1, #direction do
local char = direction:sub(i, i)
local _, count = last_hat_direction:gsub(char, char)
if count == 0 then
2021-03-07 19:43:55 -06:00
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})
2021-03-07 15:42:33 -06:00
end
end
last_hat_direction = direction
2020-11-08 15:19:01 -06:00
elseif has_hat then
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})
end
2021-03-07 19:43:55 -06:00
last_hat_direction = ""
2020-11-08 15:19:01 -06:00
elseif direction ~= "c" then
2021-03-07 15:42:33 -06:00
for i = 1, #direction do
local char = direction:sub(i, i)
local _, count = last_hat_direction:gsub(char, char)
if count == 0 then
2021-03-07 19:43:55 -06:00
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})
2021-03-07 15:42:33 -06:00
end
end
last_hat_direction = direction
2020-11-08 15:19:01 -06:00
else
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})
end
2021-03-07 19:43:55 -06:00
last_hat_direction = ""
2020-11-08 15:19:01 -06:00
end
end
2019-05-22 22:57:34 -05:00
function love.focus(f)
2020-12-20 15:55:34 -06:00
if f and (scene.title ~= "Game" or not scene.paused) then
2019-05-22 22:57:34 -05:00
resumeBGM()
else
pauseBGM()
end
end
function love.resize(w, h)
GLOBAL_CANVAS:release()
GLOBAL_CANVAS = love.graphics.newCanvas(w, h)
end
local TARGET_FPS = 60
2021-08-20 12:44:01 -05:00
--[[
-- OLD RUN CODE BELOW
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
2021-08-20 12:44:01 -05:00
]]
function love.run()
-- New Run system
-- by rin
-- aims to speedup the responsiveness of the game by
-- only updating 60 times per second, but letting
-- it poll as fast as it wants
if not love.timer then
error('new run system requires love.timer to function.')
end
if love.load then love.load(love.arg.parseGameArguments(arg), arg) end
if love.timer then love.timer.step() end
local tacc = 0
local start_time = love.timer.getTime()
return function()
if love.event then
love.event.pump()
for n, a, b, c, d, e, f in love.event.poll() do
if n == 'quit' then
if not love.quit or not love.quit() then
return a or 0
end
end
love.handlers[n](a, b, c, d, e, f)
end
end
if love.timer then
processBGMFadeout(love.timer.step())
end
local ut = love.timer.getTime()
runsystem.updatedelta = ut - start_time
runsystem.updatefps = 1 / (ut - start_time)
if scene and scene.update and love.timer then
local delta = ut - start_time
start_time = ut
tacc = tacc + delta
if tacc >= 1 / TARGET_FPS then
runsystem.drawfps = 1 / tacc
tacc = 0
scene:update()
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
end
end
end
end