The five normal and three cleared backdrops were flat plates plus a few hand rebuilt effects, so the koi, the treasure ships, the lantern glow and the festival stalls never moved as they do in the original. Each movie is now exported per shape instance with its own loop (bg_data/bg_anim/<name>.lua, textures under background/bga_<name>) and replayed by bg_objects/bg_anim.lua at 60 fps on the lower half of the screen. bg_normal.lua and bg_fever.lua use it when the data exists and keep their old drawing as the fallback; the cleared backdrop's rise/fall wipe is unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
96 lines
3.0 KiB
Lua
96 lines
3.0 KiB
Lua
-- Generic replay of an exported cabinet backdrop movie (lower half of the screen).
|
|
--
|
|
-- Data: Scripts/background/bg_data/bg_anim/<name>.lua (generated by
|
|
-- scratchpad/lyric/movie_export.py): `shapes[c] = {w, h, ox, oy}` and `normal`, a
|
|
-- list of shape instances in depth order, each with the period of its own loop and
|
|
-- channels tx/ty/sx/sy/rot/a (one number when constant, else one value per frame;
|
|
-- a = 0 means not placed) plus an optional presence mask `on`/`on_period`.
|
|
-- Textures: Graphics/background/bga_<name>/s<c>.png. The stage is 1920x540 and is
|
|
-- drawn at screen y 540; the same schema as the donbg band player.
|
|
local BGAnim = {}
|
|
BGAnim.__index = BGAnim
|
|
|
|
local FRAME_MS = 1000.0 / 60.0
|
|
local STAGE_Y = 540
|
|
local ONE = string.byte("1")
|
|
|
|
function BGAnim.available(name)
|
|
local ok, data = pcall(require, "background/bg_data/bg_anim/" .. name)
|
|
return ok and type(data) == "table" and data.normal ~= nil
|
|
end
|
|
|
|
function BGAnim.new(name, path)
|
|
local ok, data = pcall(require, "background/bg_data/bg_anim/" .. name)
|
|
if not ok or type(data) ~= "table" or not data.normal then return nil end
|
|
local self = setmetatable({}, BGAnim)
|
|
self.name = name
|
|
self.subset = "bga_" .. name
|
|
self.path = path or "background"
|
|
tex.load_folder(self.path, self.subset)
|
|
self.data = data
|
|
self.ids = {}
|
|
self.elapsed = 0
|
|
self.last_ms = nil
|
|
return self
|
|
end
|
|
|
|
function BGAnim: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 BGAnim: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
|
|
|
|
function BGAnim:draw(fade)
|
|
fade = fade or 1.0
|
|
if fade <= 0.002 then return end
|
|
local frame = math.floor(self.elapsed / FRAME_MS)
|
|
local list = self.data.normal
|
|
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 = STAGE_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
|
|
|
|
function BGAnim:destroy()
|
|
tex.unload_folder(self.path, self.subset)
|
|
end
|
|
|
|
return BGAnim
|