483 lines
21 KiB
Lua
483 lines
21 KiB
Lua
local DonBGBase = require("background/bg_objects/donbg/base")
|
|
local Fever = require("background/bg_objects/fever")
|
|
local Footer = require("background/bg_objects/footer")
|
|
local Dancer = require("background/bg_objects/dancer")
|
|
local RendaController = require("background/bg_objects/renda")
|
|
local ChibiController = require("background/bg_objects/chibi")
|
|
local BaseChibi = require("background/bg_objects/chibi/base")
|
|
local ChibiWave = require("background/bg_objects/chibi/wave")
|
|
local Timing = require("background/bg_objects/timing")
|
|
|
|
local pose_at = Timing.pose_at
|
|
|
|
-- THE IDOLM@STER (IMAS, IMAS_CG, IMAS_ML). The three share the stage, drumroll and footer
|
|
-- (same Lumen data and art), loaded from IMAS's folder; the don band, dancers, chibis and
|
|
-- line-up are each collab's own.
|
|
local IMAS_PATH = "background/collab/imas"
|
|
|
|
-- Spotlights: additive beams, each tinted one colour
|
|
local CYAN, YELLOW, MAGENTA = { 0, 255, 255, 255 }, { 255, 255, 0, 255 }, { 255, 0, 255, 255 }
|
|
|
|
-- 0..1 opacity of a light that fades in over `fade` beats from `on`, holds, and fades out over
|
|
-- `fade` from `off`, in a cycle of `period` beats (a fade-out may wrap past the cycle's end)
|
|
local function window(t, on, off, fade, period)
|
|
local u = t % period
|
|
if u < on then u = u + period end
|
|
return math.max(0, math.min(1, (u - on) / fade, (off + fade - u) / fade))
|
|
end
|
|
|
|
-- the stage's glow strip pulses out and back in every 2 beats
|
|
local function overlay_fade(t) return math.abs(1 - t % 2) end
|
|
|
|
-- Normal background: the stage under a glowing strip and five spotlights (cyan, yellow,
|
|
-- magenta, cyan, yellow). Two groups take turns: 1, 3, 5 shine for 1.25 beats, then 2 and 4,
|
|
-- in a 2.75-beat cycle. Timed in beats.
|
|
local NORMAL_SPOT_COLORS = { CYAN, YELLOW, MAGENTA, CYAN, YELLOW }
|
|
local NORMAL_SPOT_CYCLE = 2.75
|
|
local SPOT_FADE = 0.25
|
|
|
|
local function normal_spot_fade(t, i)
|
|
local on = (i % 2 == 0) and 0 or 1.25
|
|
return window(t, on, on + 1.25, SPOT_FADE, NORMAL_SPOT_CYCLE)
|
|
end
|
|
|
|
local function draw_normal_spots(id, t)
|
|
for i = 0, 4 do
|
|
local fade = normal_spot_fade(t, i)
|
|
if fade > 0 then
|
|
tex.draw_texture(id, { index = i, color = NORMAL_SPOT_COLORS[i + 1], fade = fade,
|
|
mirror = "horizontal", blend = "additive" })
|
|
end
|
|
end
|
|
end
|
|
|
|
local ImasBGNormal = {}
|
|
ImasBGNormal.__index = ImasBGNormal
|
|
|
|
function ImasBGNormal.new(bpm)
|
|
local self = setmetatable({}, ImasBGNormal)
|
|
self.name = "bg_0"
|
|
tex.load_folder(IMAS_PATH, "bg_normal/" .. self.name)
|
|
local function id(key) return tex.get_texture(IMAS_PATH .. "/" .. self.name .. "/" .. key) or 0 end
|
|
self._id_bg = id("background")
|
|
self._id_overlay = id("overlay")
|
|
self._id_spotlight = id("spotlight")
|
|
self.beat = 60000 / bpm
|
|
self.t = 0
|
|
return self
|
|
end
|
|
|
|
function ImasBGNormal:update(current_time_ms, bpm)
|
|
if bpm then self.beat = 60000 / bpm end
|
|
self.t = self.t + (current_time_ms - (self.last_ms or current_time_ms)) / self.beat
|
|
self.last_ms = current_time_ms
|
|
end
|
|
|
|
function ImasBGNormal:draw_background() tex.draw_texture(self._id_bg) end
|
|
|
|
function ImasBGNormal:draw()
|
|
self:draw_background()
|
|
local fade = overlay_fade(self.t)
|
|
for _ = 1, 2 do tex.draw_texture(self._id_overlay, { fade = fade, blend = "additive" }) end
|
|
draw_normal_spots(self._id_spotlight, self.t)
|
|
end
|
|
|
|
function ImasBGNormal:destroy() tex.unload_folder(IMAS_PATH, "bg_normal/" .. self.name) end
|
|
|
|
-- Clear background: the stage cuts to its lit-up version 0.375 beat in, under four big stars
|
|
-- spinning around the stage on their own paths, and two sets of five spotlights taking turns
|
|
-- every 1.23 beats. Orange and green floor lights pulse against each other every 2 beats.
|
|
-- Losing clear drops the stars and lights at once, switches to the normal spotlights and cuts
|
|
-- back to the normal stage after 0.375 beat (it's gone at 0.75). Timed in beats; drawn over
|
|
-- bg_normal, which takes over again after.
|
|
local CUT_BEATS = 0.375
|
|
local LEAVE_BEATS = 0.75
|
|
local FEVER_SPOTS = {
|
|
{ first = 5, colors = { CYAN, MAGENTA, YELLOW, CYAN, MAGENTA } },
|
|
{ first = 10, colors = { YELLOW, MAGENTA, CYAN, YELLOW, MAGENTA } },
|
|
}
|
|
local FEVER_SPOT_START = 0.775 -- beats after the clear
|
|
local FEVER_SPOT_TURN = 7.4 / 6 -- each set shines this long
|
|
|
|
-- Stars: { beat, x, y, sx, sy, ease } corners of each star's path in a 7.4-beat loop that
|
|
-- starts a beat after the clear, as offsets from the star's texture.json position (Lumen
|
|
-- mirrors it). sx narrows as the star turns edge-on; it glides straight between corners.
|
|
local STAR_LOOP = 7.4
|
|
local STAR_START = 1
|
|
local STAR_PIVOT = { 142, 128 } -- the star's centre in its image
|
|
local STARS = {
|
|
{ -- from the far left across to the right edge and back
|
|
{ 0, -1228, -145, 0.3, 1.5 }, { 0.35, -1125, -11, 0.33, 1.34 }, { 0.725, -952, 44, 0.6, 1.19, "out" },
|
|
{ 0.875, -888, 40, 1, 1.16 }, { 1.725, -480, -86, 1, 1 }, { 2.275, -220, -30, 0.95, 1.07 },
|
|
{ 2.825, 33, 32, 0.67, 1.13 }, { 3.425, 282, -43, 0.3, 1.2 }, { 3.95, 41, 32, 0.52, 1.14, "out" },
|
|
{ 4.125, -42, 26, 0.9, 1.12 }, { 4.65, -296, -59, 0.9, 1.06 }, { 4.975, -451, -87, 0.9, 1.03 },
|
|
{ 5.55, -680, -20, 0.8, 1 }, { 6.35, -966, 44, 0.6, 1 }, { 6.875, -1127, -13, 0.45, 1.1 },
|
|
{ 7.15, -1190, -80, 0.37, 1.16, "in" },
|
|
},
|
|
{ -- leaps at the far left, crosses along the top and leaps at the right
|
|
{ 0, -495, -72, 1, 1 }, { 0.625, -783, -12, 0.93, 1 }, { 0.85, -889, -24, 0.9, 1 },
|
|
{ 1, -956, -48, 0.4, 1.14 }, { 1.35, -1082, -155, 0.42, 1.45 }, { 1.7, -1148, -308, 0.43, 1.77 },
|
|
{ 2.15, -1075, -145, 0.39, 1.43 }, { 2.575, -943, -42, 0.35, 1.11 }, { 2.725, -886, -23, 1, 1 },
|
|
{ 2.925, -781, -12, 1, 1 }, { 3.85, -303, -118, 1, 1 }, { 4.425, -11, -37, 1, 1 },
|
|
{ 4.675, 112, 2, 0.48, 1.2 }, { 4.925, 211, -75, 0.51, 1.4 }, { 5.175, 252, -202, 0.53, 1.6 },
|
|
{ 5.65, 211, -76, 0.49, 1.36 }, { 6.125, 112, 2, 0.44, 1.13 }, { 6.375, 43, -14, 0.41, 1 },
|
|
{ 7.025, -298, -118, 0.9, 1 },
|
|
},
|
|
{ -- from the right, across the top to a leap at the far left and back
|
|
{ 0, 298, -7, 0.6, 1.5 }, { 0.7, -1, -108, 0.42, 1.29 }, { 0.85, -67, -118, 0.95, 1.25 },
|
|
{ 1.225, -246, -131, 0.92, 1.16 }, { 1.975, -600, -89, 0.86, 0.98 }, { 2.725, -935, 30, 0.8, 0.8 },
|
|
{ 3.125, -1048, 40, 0.73, 1.11 }, { 3.9, -1248, -28, 0.6, 1.73 }, { 4.425, -1049, 40, 0.56, 1.35 },
|
|
{ 4.625, -968, 34, 0.54, 1.2 }, { 4.95, -814, -1, 1, 1.34 }, { 5.6, -537, -103, 1, 1.3 },
|
|
{ 6.225, -254, -131, 1, 1.26 }, { 6.65, -62, -118, 1, 1.23 }, { 6.875, 36, -100, 0.44, 1.22 },
|
|
},
|
|
{ -- wobbles at the right, then runs the whole stage to the far left and back
|
|
{ 0, -460, -73, 1, 1 }, { 1.025, -10, 27, 1, 1.25 }, { 1.275, 108, 38, 0.54, 1.33 },
|
|
{ 1.675, 280, -14, 0.4, 1.57 }, { 2, 162, 35, 0.4, 1.55 }, { 2.275, 53, 35, 0.4, 1.53 },
|
|
{ 2.575, -64, 17, 1.1, 1.1 }, { 4.025, -637, -90, 1.1, 1.1 }, { 4.625, -876, -34, 1.1, 1.1 },
|
|
{ 4.95, -996, -6, 0.35, 1.56 }, { 5.475, -1202, -3, 0.43, 1.98 }, { 5.675, -1122, 5, 0.49, 1.88 },
|
|
{ 6.95, -629, -90, 0.87, 1.22 },
|
|
},
|
|
}
|
|
-- as pose tables: each corner glides `to` the next (the last back to the first)
|
|
for s, corners in ipairs(STARS) do
|
|
local poses = { length = STAR_LOOP }
|
|
for i, c in ipairs(corners) do
|
|
local n = corners[i + 1] or corners[1]
|
|
poses[i] = { c[1], 0, c[2], c[3], sx = c[4], sy = c[5], to = { n[2], n[3], c[6], sx = n[4], sy = n[5] } }
|
|
end
|
|
STARS[s] = poses
|
|
end
|
|
|
|
local ImasBGFever = {}
|
|
ImasBGFever.__index = ImasBGFever
|
|
|
|
function ImasBGFever.new(bpm)
|
|
local self = setmetatable({}, ImasBGFever)
|
|
self.name = "bg_fever_0"
|
|
tex.load_folder(IMAS_PATH, "bg_fever/" .. self.name)
|
|
local function id(key) return tex.get_texture(IMAS_PATH .. "/" .. self.name .. "/" .. key) or 0 end
|
|
self._id_bg = id("background")
|
|
self._id_overlay = id("overlay")
|
|
self._id_spotlight = id("spotlight")
|
|
self._id_star = id("star")
|
|
self._id_light_orange = id("light_orange")
|
|
self._id_light_green = id("light_green")
|
|
self.star_info = tex.get_texture_info(self.name, "star")
|
|
self.beat = 60000 / bpm
|
|
self.state = nil -- nil (hidden), "in", "out"
|
|
return self
|
|
end
|
|
|
|
function ImasBGFever:start() self.state, self.t, self.overlay_t = "in", 0, 0 end
|
|
|
|
function ImasBGFever:stop()
|
|
if self.state ~= "in" then return end
|
|
self.state, self.t = "out", 0
|
|
end
|
|
|
|
function ImasBGFever:update(current_time_ms, bpm)
|
|
if bpm then self.beat = 60000 / bpm end
|
|
local dt = (current_time_ms - (self.last_ms or current_time_ms)) / self.beat
|
|
self.last_ms = current_time_ms
|
|
if not self.state then return end
|
|
self.t, self.overlay_t = self.t + dt, self.overlay_t + dt
|
|
if self.state == "out" and self.t >= LEAVE_BEATS then self.state = nil end
|
|
end
|
|
|
|
function ImasBGFever:draw_star(poses, t)
|
|
local p = pose_at(poses, (t - STAR_START) % STAR_LOOP)
|
|
local w, h = self.star_info.width, self.star_info.height
|
|
local ox, oy = STAR_PIVOT[1] * p.sx, STAR_PIVOT[2] * p.sy
|
|
tex.draw_texture(self._id_star, {
|
|
x = p.x + STAR_PIVOT[1], y = p.y + STAR_PIVOT[2], x2 = w * (p.sx - 1), y2 = h * (p.sy - 1),
|
|
origin = { ox, oy }, mirror = "horizontal", blend = "additive",
|
|
})
|
|
end
|
|
|
|
-- Draws over bg_normal while clear (or leaving it); bg_normal shows its stage before the cut
|
|
function ImasBGFever:draw(bg_normal)
|
|
if not self.state then return false end
|
|
local t = self.t
|
|
local fever_bg = (self.state == "in") == (t >= CUT_BEATS)
|
|
if fever_bg then tex.draw_texture(self._id_bg) else bg_normal:draw_background() end
|
|
tex.draw_texture(self._id_overlay, { fade = overlay_fade(self.overlay_t), blend = "additive" })
|
|
if self.state == "out" then
|
|
draw_normal_spots(self._id_spotlight, t)
|
|
return true
|
|
end
|
|
for _, star in ipairs(STARS) do self:draw_star(star, t) end
|
|
for k, set in ipairs(FEVER_SPOTS) do
|
|
local on = FEVER_SPOT_START + (k - 1) * FEVER_SPOT_TURN
|
|
local fade = t >= on and window(t, on, on + FEVER_SPOT_TURN, SPOT_FADE, 2 * FEVER_SPOT_TURN) or 0
|
|
if fade > 0 then
|
|
for i = 0, 4 do
|
|
tex.draw_texture(self._id_spotlight, { index = set.first + i, color = set.colors[i + 1],
|
|
fade = fade, mirror = "horizontal", blend = "additive" })
|
|
end
|
|
end
|
|
end
|
|
local pulse = math.abs(1 - t % 2) -- orange brightens as green dims, and back
|
|
tex.draw_texture(self._id_light_orange, { fade = 1 - pulse / 2, blend = "additive" })
|
|
tex.draw_texture(self._id_light_green, { fade = 0.5 + pulse / 2, blend = "additive" })
|
|
return true
|
|
end
|
|
|
|
function ImasBGFever:destroy() tex.unload_folder(IMAS_PATH, "bg_fever/" .. self.name) end
|
|
|
|
-- Drumroll: notes fly up and to the right, the default renda_c flight
|
|
local RENDA = { ms = { 2000 }, dx = 1560, dy = -1648, x_range = 500, y_range = 20 }
|
|
|
|
-- IMAS ---------------------------------------------------------------------------------------
|
|
|
|
-- Don band: the base scrolls one tile left every 5.33s; the clear set scrolls with it under
|
|
-- a pink glow strip that pulses every second
|
|
local IMAS_DONBG = {
|
|
fade = 0.2,
|
|
layers = {
|
|
{ key = "background", ms = 5333 },
|
|
{ key = "glow", clear_only = true, tile = 0, alpha = 0.148, blend = "additive",
|
|
period = 1000, pulse = { { 500, -1000 }, { 500, 1000, "out" } } },
|
|
},
|
|
}
|
|
|
|
-- Dancers: all five jump up from below, land with a squash, dance a 4-beat routine (a pose a
|
|
-- quarter beat, two held for a half) and hop up and drop away when removed. Timed in beats;
|
|
-- poses are offsets from y 670, pivoting about Lumen's origin in the images.
|
|
local function imas_dancer(rest)
|
|
return {
|
|
origin = { 152, 152 },
|
|
at = { 0, rest },
|
|
enter = {
|
|
beats = 2,
|
|
{ 0, 0, 0, rest + 320, to = { 0, rest - 60, "out" } }, -- jumps up from below
|
|
{ 0.675, 0, 0, rest - 60, to = { 0, rest, "in" } },
|
|
{ 0.925, 1, 0, rest, to = { nil, nil, nil, sy = 0.92 } }, -- lands with a squash
|
|
{ 1.025, 1, 0, rest, sy = 0.95, to = { nil, nil, nil, sy = 1 } },
|
|
{ 1.1, 1, 0, rest },
|
|
},
|
|
dance = Timing.steps({
|
|
{ 0, 0.25, x = 0, y = rest }, { 1, 0.25 }, { 2, 0.25 }, { 3, 0.25 }, { 4, 0.25 }, { 5, 0.5 },
|
|
{ 6, 0.25 }, { 7, 0.25 }, { 8, 0.25 }, { 9, 0.25 }, { 10, 0.25 }, { 11, 0.25 }, { 12, 0.5 },
|
|
{ 13, 0.25 },
|
|
}),
|
|
leave = {
|
|
beats = 1.45,
|
|
{ 0, 0, 0, rest },
|
|
{ 0.1, 1, 0, rest, to = { 0, rest - 60, "out" } }, -- hops up and drops away
|
|
{ 0.5, 1, 0, rest - 60, to = { 0, rest + 320, "in" } },
|
|
},
|
|
}
|
|
end
|
|
local IMAS_DANCERS = Dancer.define({ default = imas_dancer(-145), [1] = imas_dancer(-142), [2] = imas_dancer(-148) })
|
|
|
|
-- Fixed slots (far-left .. far-right), from Lumen's dancer positions; each dancer has its own
|
|
local DANCER_CENTERS = { 213, 427, 640, 853, 1067 }
|
|
-- (joins fill the centre, left, right, far-left, far-right slots)
|
|
|
|
-- Chibis for good hits: one of four idols hops in growing from 70% size, then bobs across
|
|
-- the don band in a zig-zag, flapping between two poses every half beat
|
|
local IMAS_CHIBIS = {}
|
|
for key = 0, 3 do
|
|
IMAS_CHIBIS[key + 1] = {
|
|
key = tostring(key),
|
|
run = { y = -1 },
|
|
wave = { first = 17, height = 40, beats = 0.85 },
|
|
period = 1,
|
|
poses = { { 0, 0 }, { 0.5, 1 } },
|
|
}
|
|
end
|
|
|
|
-- IMAS CG ------------------------------------------------------------------------------------
|
|
|
|
-- Three dancers on fixed slots (Lumen's dancer2, dancer1, dancer3 at x 427, 640, 853; index 1,
|
|
-- 2, 0), standing 8px under the dancer's base. Same routine as IMAS, but their images are
|
|
-- bottom-anchored and the routine borrows frame 0 of the entry once. Timed in beats; poses
|
|
-- are offsets from the rest position.
|
|
local function cg_dancer(origin)
|
|
return {
|
|
origin = origin,
|
|
at = { 0, 0 },
|
|
enter = {
|
|
beats = 2,
|
|
{ 0, 0, 20, 310, to = { 20, -46, "out" } }, -- jumps up from below
|
|
{ 0.65, 0, 20, -46, to = { 20, 4, "in" } },
|
|
{ 0.925, 1, 0, 4, to = { 0, 3, "out", sy = 0.95 } }, -- lands with a squash
|
|
{ 1.025, 1, 0, 3, sy = 0.95, to = { 0, 0, sy = 1 } },
|
|
{ 1.1, 1, 0, 0 },
|
|
},
|
|
dance = Timing.steps({
|
|
{ 0, 0.25, x = 0, y = 0 }, { 1, 0.25 }, { 2, 0.25 }, { 3, 0.25 }, { 4, 0.25 }, { 5, 0.5 },
|
|
{ 6, 0.25 }, { 7, 0.25 }, { 0, 0.25, key = "start" }, { 8, 0.25 }, { 9, 0.25 }, { 10, 0.25 },
|
|
{ 11, 0.625 }, { 12, 0.125 },
|
|
}),
|
|
leave = {
|
|
beats = 1.45,
|
|
{ 0, 0, 0, 4, key = "start", to = { 0, 3, "in", sy = 0.935 } },
|
|
{ 0.125, 0, 0, -4, key = "start", sy = 0.943, to = { 0, -50, "out", sy = 1 } }, -- hops up
|
|
{ 0.475, 0, 0, -46, key = "end", to = { 0, 374, "in" } }, -- and drops away
|
|
},
|
|
}
|
|
end
|
|
local CG_DANCERS = Dancer.define({
|
|
[0] = cg_dancer({ 112, 280 }), [1] = cg_dancer({ 112, 280 }), [2] = cg_dancer({ 116, 288 }),
|
|
})
|
|
|
|
-- Chibis for good hits: one of two idols (frames 0, 1) hops in from 70% size, then bobs across
|
|
-- the don band in a zig-zag. One image each; the bob is 33px high, a swing every 0.45 beat.
|
|
local CG_CHIBIS = {}
|
|
for frame = 0, 1 do
|
|
CG_CHIBIS[frame + 1] = {
|
|
key = "0",
|
|
first = frame,
|
|
hop = { from = { -428, 13 }, peak = { -354, -36 }, up = 0.25 },
|
|
run = { x = -294, y = 5, distance = 1222 },
|
|
wave = { first = -29, height = 33, beats = 0.45 },
|
|
}
|
|
end
|
|
|
|
local VARIANTS = {
|
|
[IMAS_PATH] = {
|
|
donbg = IMAS_DONBG,
|
|
dancers = IMAS_DANCERS,
|
|
chibis = IMAS_CHIBIS,
|
|
fever = { rise = 210, bounce = 70, drop = 400, poses = true },
|
|
-- dancer index by join order, and the slots' draw order
|
|
join_order = { 4, 3, 2, 1, 0 },
|
|
draw_order = { 5, 1, 4, 2, 3 },
|
|
},
|
|
["background/collab/imas_cg"] = {
|
|
donbg = IMAS_DONBG,
|
|
dancers = CG_DANCERS,
|
|
chibis = CG_CHIBIS,
|
|
fever = { rise = 249, bounce = 70, drop = 439, poses = true },
|
|
join_order = { 2, 1, 0 },
|
|
draw_order = { 2, 4, 3 },
|
|
},
|
|
-- not reviewed yet: the default band, dancers and chibis
|
|
["background/collab/imas_ml"] = { fever = { rise = 249, bounce = 70, drop = 439, poses = true } },
|
|
}
|
|
|
|
-- Background factory (IMAS, IMAS_CG, IMAS_ML)
|
|
|
|
local ImasBackground = {}
|
|
ImasBackground.__index = ImasBackground
|
|
|
|
function ImasBackground.new(player_num, bpm, path, max_dancers)
|
|
local self = setmetatable({}, ImasBackground)
|
|
local v = VARIANTS[path]
|
|
self.variant = v
|
|
self.path = path
|
|
self.donbg = DonBGBase.new(1, player_num, path, v.donbg)
|
|
self.bg_normal = ImasBGNormal.new(bpm)
|
|
self.bg_fever = ImasBGFever.new(bpm)
|
|
self.footer = Footer.new(IMAS_PATH, 0)
|
|
self.fever = Fever.new(bpm, path, v.fever)
|
|
self.dancer = Dancer.BaseDancerGroup.new(0, bpm, max_dancers, path, v.dancers)
|
|
if v.dancers then
|
|
local by_index = {}
|
|
for _, d in ipairs(self.dancer.dancers) do by_index[d.index] = d end
|
|
for i, index in ipairs(v.join_order) do self.dancer.dancers[i] = by_index[index] end
|
|
end
|
|
self.renda = RendaController.new(IMAS_PATH, 0, RENDA)
|
|
self.chibi = ChibiController.new(bpm, path, 0)
|
|
self.max_dancers = max_dancers
|
|
self.is_clear = false
|
|
self.is_rainbow = false
|
|
self.last_milestone = 1
|
|
return self
|
|
end
|
|
|
|
function ImasBackground:update(current_ms, bpm)
|
|
self.donbg:update(current_ms, bpm)
|
|
self.bg_normal:update(current_ms, bpm)
|
|
self.bg_fever:update(current_ms, bpm)
|
|
self.fever:update(current_ms, bpm)
|
|
self.dancer:update(current_ms, bpm)
|
|
self.renda:update(current_ms)
|
|
self.chibi:update(current_ms, bpm)
|
|
end
|
|
|
|
function ImasBackground:add_chibi(player_num)
|
|
local chibis = self.variant.chibis
|
|
if chibis then
|
|
BaseChibi.add(self.chibi, chibis[math.random(#chibis)], self.path, player_num, ChibiWave, "chibi_0")
|
|
else
|
|
self.chibi:add_chibi(player_num, false)
|
|
end
|
|
end
|
|
|
|
function ImasBackground:handle_good(player_num) self:add_chibi(player_num) end
|
|
|
|
function ImasBackground:handle_ok(player_num) self:add_chibi(player_num) end
|
|
|
|
function ImasBackground:handle_bad(player_num) self.chibi:add_chibi(player_num, true) end
|
|
|
|
function ImasBackground:handle_drumroll(player_num) self.renda:add_renda() end
|
|
|
|
function ImasBackground:handle_balloon(player_num) self.renda:add_renda() end
|
|
|
|
function ImasBackground:handle_gauge(player_num, progress, is_clear, is_rainbow)
|
|
self.donbg:set_clear(is_clear)
|
|
if is_clear and not self.is_clear then self.bg_fever:start() end
|
|
if not is_clear and self.is_clear then self.bg_fever:stop() end
|
|
if is_rainbow and not self.is_rainbow then self.fever:start() end
|
|
if not is_rainbow and self.is_rainbow then self.fever:stop() end
|
|
self.is_clear = is_clear
|
|
self.is_rainbow = is_rainbow
|
|
|
|
local md = self.max_dancers
|
|
local current_milestone
|
|
if is_clear then
|
|
current_milestone = md
|
|
else
|
|
current_milestone = math.min(md - 1, math.floor(progress * md))
|
|
end
|
|
if current_milestone > self.last_milestone then
|
|
for _ = 1, current_milestone - self.last_milestone do self.dancer:add_dancer() end
|
|
self.last_milestone = current_milestone
|
|
elseif current_milestone < self.last_milestone then
|
|
for _ = 1, self.last_milestone - current_milestone do self.dancer:leave_dancer() end
|
|
self.last_milestone = current_milestone
|
|
end
|
|
end
|
|
|
|
function ImasBackground:draw_back()
|
|
if not self.bg_fever:draw(self.bg_normal) then self.bg_normal:draw() end
|
|
self.footer:draw()
|
|
self.donbg:draw()
|
|
self.renda:draw()
|
|
if self.variant.dancers then
|
|
self.dancer:draw_slots(DANCER_CENTERS, self.variant.draw_order)
|
|
else
|
|
self.dancer:draw()
|
|
end
|
|
self.fever:draw()
|
|
self.chibi:draw()
|
|
end
|
|
|
|
function ImasBackground:draw_fore() end
|
|
|
|
function ImasBackground:destroy()
|
|
self.donbg:destroy()
|
|
self.bg_normal:destroy()
|
|
self.bg_fever:destroy()
|
|
self.fever:destroy()
|
|
self.dancer:destroy()
|
|
self.footer:destroy()
|
|
self.renda:destroy()
|
|
self.chibi:destroy()
|
|
end
|
|
|
|
-- Export the factory
|
|
local Imas = {}
|
|
Imas.new = ImasBackground.new
|
|
|
|
-- Callable as a collab constructor: Imas.new(player_num, bpm, path, max_dancers)
|
|
setmetatable(Imas, {
|
|
__call = function(_, player_num, bpm, path, max_dancers)
|
|
return ImasBackground.new(player_num, bpm, path, max_dancers)
|
|
end
|
|
})
|
|
|
|
return Imas
|