182 lines
5.9 KiB
Lua
182 lines
5.9 KiB
Lua
local Timing = require("background/bg_objects/timing")
|
|
local chain_moves, sum = Timing.chain_moves, Timing.sum
|
|
|
|
local BaseFever = {}
|
|
BaseFever.__index = BaseFever
|
|
|
|
function BaseFever.new(index, bpm, path)
|
|
local self = setmetatable({}, BaseFever)
|
|
self.name = "fever_" .. index
|
|
self.path = path or "background"
|
|
tex.load_folder(self.path, "fever/" .. self.name)
|
|
local half_beat = (60000 / bpm) / 2
|
|
self.bounce_up = anim.move(half_beat, {total_distance = 50, ease_out = "quadratic"})
|
|
self.bounce_down = anim.move(half_beat, {total_distance = 50, ease_in = "quadratic", delay = half_beat})
|
|
return self
|
|
end
|
|
|
|
-- Only look up the keys a variant draws: a missing key makes tex.get_texture log a load error
|
|
function BaseFever:load_ids(keys)
|
|
for _, key in ipairs(keys) do
|
|
self["_id_" .. key] = tex.get_texture(self.path .. "/" .. self.name .. "/" .. key)
|
|
end
|
|
end
|
|
|
|
function BaseFever:start()
|
|
self.bounce_up:start()
|
|
self.bounce_down:start()
|
|
end
|
|
|
|
function BaseFever:update(current_time_ms, bpm)
|
|
self.bounce_up:update(current_time_ms)
|
|
self.bounce_down:update(current_time_ms)
|
|
if self.bounce_down.is_finished then
|
|
local half_beat = (60000 / bpm) / 2
|
|
self.bounce_up = anim.move(half_beat, {total_distance = 50, ease_out = "quadratic"})
|
|
self.bounce_down = anim.move(half_beat, {total_distance = 50, ease_in = "quadratic", delay = half_beat})
|
|
self.bounce_up:start()
|
|
self.bounce_down:start()
|
|
end
|
|
end
|
|
|
|
function BaseFever:destroy()
|
|
tex.unload_folder(self.path, "fever/" .. self.name)
|
|
end
|
|
|
|
local Fever0 = setmetatable({}, {__index = BaseFever})
|
|
Fever0.__index = Fever0
|
|
|
|
function Fever0.new(index, bpm, path)
|
|
local self = setmetatable({}, Fever0)
|
|
local base = BaseFever.new(index, bpm, path)
|
|
for k, v in pairs(base) do self[k] = v end
|
|
self:load_ids({ "overlay_l", "overlay_r" })
|
|
return self
|
|
end
|
|
|
|
function Fever0:draw()
|
|
local y = self.bounce_down.attribute - self.bounce_up.attribute
|
|
if self._id_overlay_l then tex.draw_texture(self._id_overlay_l, {y = y}) end
|
|
if self._id_overlay_r then tex.draw_texture(self._id_overlay_r, {y = y}) end
|
|
end
|
|
|
|
-- Fever1 and Fever2 share the same draw as Fever0
|
|
local Fever1 = setmetatable({}, {__index = Fever0})
|
|
Fever1.__index = Fever1
|
|
function Fever1.new(index, bpm, path)
|
|
local self = setmetatable({}, Fever1)
|
|
local base = BaseFever.new(index, bpm, path)
|
|
for k, v in pairs(base) do self[k] = v end
|
|
self:load_ids({ "overlay_l", "overlay_r" })
|
|
return self
|
|
end
|
|
function Fever1:draw() Fever0.draw(self) end
|
|
|
|
local Fever2 = setmetatable({}, {__index = Fever0})
|
|
Fever2.__index = Fever2
|
|
function Fever2.new(index, bpm, path)
|
|
local self = setmetatable({}, Fever2)
|
|
local base = BaseFever.new(index, bpm, path)
|
|
for k, v in pairs(base) do self[k] = v end
|
|
self:load_ids({ "overlay_l", "overlay_r" })
|
|
return self
|
|
end
|
|
function Fever2:draw() Fever0.draw(self) end
|
|
|
|
local Fever3 = setmetatable({}, {__index = BaseFever})
|
|
Fever3.__index = Fever3
|
|
|
|
function Fever3.new(index, bpm, path)
|
|
local self = setmetatable({}, Fever3)
|
|
local base = BaseFever.new(index, bpm, path)
|
|
for k, v in pairs(base) do self[k] = v end
|
|
self:load_ids({ "overlay" })
|
|
return self
|
|
end
|
|
|
|
function Fever3:draw()
|
|
local y = self.bounce_down.attribute - self.bounce_up.attribute
|
|
if self._id_overlay then tex.draw_texture(self._id_overlay, {y = y}) end
|
|
end
|
|
|
|
-- LumenFever: the Lumen collabs' fever overlay (Miku, GUMI). The line-up jumps up from
|
|
-- below the screen, bounces once a beat switching between its two poses (overlay_l/overlay_r
|
|
-- frames 0 and 1), and hops off again when the rainbow gauge is lost. Timed in beats.
|
|
|
|
local FEVER_IN = { { 0.475, -280, "out" }, { 0.5, 70, "in" } }
|
|
local FEVER_BOUNCE = { { 0.5, -70, "out" }, { 0.5, 70, "in" } }
|
|
local FEVER_OUT = { { 0.25, -70, "out" }, { 0.75, 400, "in" } }
|
|
local FEVER_IN_OFFSET = 210
|
|
|
|
local LumenFever = {}
|
|
LumenFever.__index = LumenFever
|
|
|
|
function LumenFever.new(bpm, path)
|
|
local self = setmetatable({}, LumenFever)
|
|
self.name = "fever_0"
|
|
self.path = path
|
|
tex.load_folder(self.path, "fever/" .. self.name)
|
|
self._id_l = tex.get_texture(self.path .. "/" .. self.name .. "/" .. "overlay_l") or 0
|
|
self._id_r = tex.get_texture(self.path .. "/" .. self.name .. "/" .. "overlay_r") or 0
|
|
self.beat = 60000 / bpm
|
|
self.state = nil -- nil (hidden), "in", "bounce", "out"
|
|
return self
|
|
end
|
|
|
|
function LumenFever:play(state, moves, offset)
|
|
self.state = state
|
|
self.offset = offset
|
|
self.moves = chain_moves(moves, self.beat, tex.get_screen_scale())
|
|
end
|
|
|
|
function LumenFever:y()
|
|
return self.offset + sum(self.moves)
|
|
end
|
|
|
|
function LumenFever:start()
|
|
self.pose = 0
|
|
self:play("in", FEVER_IN, math.floor(FEVER_IN_OFFSET * tex.get_screen_scale()))
|
|
end
|
|
|
|
-- leaves from wherever the bounce currently is
|
|
function LumenFever:stop()
|
|
if self.state then self:play("out", FEVER_OUT, self:y()) end
|
|
end
|
|
|
|
function LumenFever:update(current_time_ms, bpm)
|
|
if bpm then self.beat = 60000 / bpm end
|
|
if not self.state then return end
|
|
for _, m in ipairs(self.moves) do m:update(current_time_ms) end
|
|
if not self.moves[#self.moves].is_finished then return end
|
|
if self.state == "out" then
|
|
self.state = nil
|
|
else
|
|
self.pose = 1 - self.pose
|
|
self:play("bounce", FEVER_BOUNCE, 0)
|
|
end
|
|
end
|
|
|
|
function LumenFever:draw()
|
|
if not self.state then return end
|
|
local y = self:y()
|
|
tex.draw_texture(self._id_l, { frame = self.pose, y = y })
|
|
tex.draw_texture(self._id_r, { frame = self.pose, y = y })
|
|
end
|
|
|
|
function LumenFever:destroy() tex.unload_folder(self.path, "fever/" .. self.name) end
|
|
|
|
local Fever = {}
|
|
Fever.Base = BaseFever
|
|
Fever.Fever0 = Fever0
|
|
Fever.Fever1 = Fever1
|
|
Fever.Fever2 = Fever2
|
|
Fever.Fever3 = Fever3
|
|
Fever.Lumen = LumenFever
|
|
|
|
function Fever.create(index, bpm, path)
|
|
local map = {Fever0, Fever1, Fever2, Fever3}
|
|
return map[index + 1].new(index, bpm, path)
|
|
end
|
|
|
|
return Fever
|