Files
YataiDONNijiiro/Scripts/background/bg_objects/donbg/anim_player.lua
T
TaikoZhongandClaude Fable 5.1 9b380de94b donbg band: back to 60 Hz
Checked against the original: the band runs at half the speed the 120 Hz step
gave it. Only the soul-max crowd steps at 120 Hz.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 11:35:47 +08:00

91 lines
3.3 KiB
Lua

-- Cabinet-faithful donbg band player.
--
-- Data: Scripts/background/bg_data/donbg_anim/a_NN_Mp.lua (generated by
-- scratchpad/lyric/donbg_export2.py from the cabinet's enso/donbg movie): for each
-- state ("normal" / "fever") the list of shape instances in depth order. Each one
-- carries the period of its own loop and the channels tx/ty/sx/sy/rot/a, a channel
-- being either one number (constant) or one value per frame of the loop (a = 0 means
-- not placed). A flipbook frame additionally has a presence mask `on` (string of
-- '0'/'1') with its own `on_period`, so the fish's arc (parent motion) and its frame
-- swap need not share a period. Textures: Graphics/background/donbga_NN_Mp/s<c>.png;
-- shapes[c] = {w, h, ox, oy} says where the shape origin sits inside its png.
--
-- Everything runs on one 60 Hz clock, so the squid that peeks up, the fish that
-- jumps, the fans that drift and the tiles that scroll keep the cabinet's timing.
local DonBGAnim = {}
DonBGAnim.__index = DonBGAnim
local FRAME_MS = 1000.0 / 60.0 -- the band steps at 60 Hz (checked against the original)
local ONE = string.byte("1")
function DonBGAnim.new(index, player_num, path)
local name = string.format("a_%02d_%dp", index, player_num)
local ok, data = pcall(require, "background/bg_data/donbg_anim/" .. name)
if not ok or type(data) ~= "table" or not data.normal then return nil end
local self = setmetatable({}, DonBGAnim)
self.name = name
self.subset = string.format("donbga_%02d_%dp", index, player_num)
tex.load_folder(path, self.subset)
self.data = data
self.ids = {}
self.elapsed = 0
self.last_ms = nil
return self
end
function DonBGAnim:id_of(shape)
local id = self.ids[shape]
if id == nil then
id = tex.get_id(self.subset, "s" .. shape) or false
self.ids[shape] = id
end
return id or nil
end
function DonBGAnim:update(current_ms)
if self.last_ms then
local dt = current_ms - self.last_ms
if dt > 0 and dt < 500 then self.elapsed = self.elapsed + dt end
end
self.last_ms = current_ms
end
local function ch(v, i)
if type(v) == "number" then return v end
return v[i]
end
-- draw one state with a global fade, the band's top-left at (0, y)
function DonBGAnim:draw_state(state, fade, y)
local list = self.data[state]
if not list or fade <= 0.002 then return end
local frame = math.floor(self.elapsed / FRAME_MS)
local shapes = self.data.shapes
for k = 1, #list do
local e = list[k]
local i = (frame % e.period) + 1
local a = ch(e.a, i)
if a > 0.002 and e.on then
if e.on:byte((frame % e.on_period) + 1) ~= ONE then a = 0 end
end
if a > 0.002 then
local s = shapes[e.shape]
local id = s and self:id_of(e.shape)
if id then
local sx, sy = ch(e.sx, i), ch(e.sy, i)
tex.draw_texture(id, {
x = ch(e.tx, i),
y = y + ch(e.ty, i),
x2 = s[1] * (sx - 1),
y2 = s[2] * (sy - 1),
origin = { s[3] * sx, s[4] * sy },
rotation = ch(e.rot, i),
fade = a * fade,
})
end
end
end
end
return DonBGAnim