Files
YataiDONNijiiro/Scripts/global/result_transition.lua
T
2026-09-19 13:45:48 -04:00

90 lines
4.1 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- YataiDON-HSS — the GAME→RESULT transition, ROUND 13.
--
-- The cabinet does NOT close a shutter here. `000_default/loading/loading_kuro_result.nulm`
-- (root sprite 4, 166 frames, labels `init 0 / in 6 / stop 115 / out 145 / end 165`) is a
-- SINGLE full-stage black shape whose **alpha** ramps linearly 0 → 1 over frames 6…115 —
-- 109 frames = 1816.7 ms — then holds at `stop` until the result screen takes over.
--
-- The engine's built-in rig (`src/objects/game/result_transition.cpp`) is a `move`
-- animation with no alpha at all, so this could not be expressed as skin data; round 13
-- added the scripted hook (see ENGINE_BINDINGS.md) and this file is the consumer.
-- The engine calls `start` / `update` / `draw` / `is_finished`; defining `draw` is what
-- takes the shutter out of the picture, and defining `is_finished` is what stops the scene
-- cutting to RESULT at 983 ms, when the screen would still be only ~54 % black.
--
-- The ramp itself is NOT hand-fitted: it is the exported arcade timeline,
-- `Scripts/anim/kuro_result.lua` (ANIM_PIPELINE.md). `anim_export.py` compressed the 318
-- dense rows to 4 breakpoints, which is itself the proof the ramp is linear between them,
-- and `anim_check.py kuro_result` samples the shipped table through the shipped sampler at
-- every arcade frame: `a max|d| = 0.001938`, inside the 0.004 (1/256) export tolerance.
--
-- The fade-out half of the record (`stop 115` → `end 165`) is deliberately NOT played
-- here: the result screen's own entry already fades its backdrop out over the board
-- (`result` animation 15), so playing both would double the dip.
local anim = require("anim/sampler")
ResultTransition = {}
ResultTransition.__index = ResultTransition
local F_IN, F_STOP = 6, 115 -- loading_kuro_result frame labels
local MS_PER_F = 1000.0 / 60.0
local TRACK = "#3@0" -- the black plate's own placement
function ResultTransition.new(player_num)
local self = setmetatable({}, ResultTransition)
self.player_num = player_num
self.t0 = nil
self.alpha = 0.0
-- Belt and braces: the engine already refuses to forward `update` / `is_finished`
-- before `start()` (it drives this object from the first frame of the song, and
-- `is_finished` is what ends the GAME screen), but a script that can run its clock
-- unstarted would cut the chart short, so refuse here too.
self.started = false
-- FAIL SOFT: `anim.safe` never raises — a missing or malformed generated table
-- yields the NULL clip, whose readers return nil, and `update` falls back to the
-- arcade's own documented linear ramp below.
self.clip = anim.safe("anim/kuro_result")
self.t_black = tex.get_texture("global/result_transition/fade")
return self
end
function ResultTransition:start()
self.t0 = nil
self.alpha = 0.0
self.started = true
end
function ResultTransition:update(current_ms)
if not self.started then return end
if not self.t0 then self.t0 = current_ms end
local f = F_IN + (current_ms - self.t0) / MS_PER_F
if f > F_STOP then f = F_STOP end
local a = self.clip:at(TRACK, f)
if not a then
-- the generated table is gone: the record is linear f6…f115, 0 → 1
a = (f - F_IN) / (F_STOP - F_IN)
end
if a < 0 then a = 0 elseif a > 1 then a = 1 end
self.alpha = a
end
-- The engine hands the screen over once this is true AND the result voice has stopped.
function ResultTransition:is_finished()
return self.started and self.alpha >= 1.0
end
function ResultTransition:draw()
if not self.t_black then return end
if self.alpha <= 0.004 then return end -- below the engine's own 1/256 quantisation
local w = tex.get_screen_width()
local h = tex.get_screen_height()
-- `fade.png` is an 8×8 black plate; texture.json carries its own 8×8 size as the base
-- destination rect and `x2`/`y2` are ADDED to it (texture.cpp:655-680), so this
-- stretches it to exactly the screen at any resolution.
tex.draw_texture(self.t_black, { x = 0, y = 0, x2 = w - 8, y2 = h - 8, fade = self.alpha })
end
return ResultTransition