100 lines
4.3 KiB
Lua
100 lines
4.3 KiB
Lua
-- YataiDON-HSS: arcade msg_L_mc / msg_R_mc bubbles (perfect/success/near/miss) baked as
|
|
-- crown/message frames. 0..3 = left bubble (miss, near, success, perfect), 4..7 = right bubble
|
|
-- (tail on the other side) for 2P.
|
|
--
|
|
-- ROUND 15 — the pop is the CABINET's, not PyTaikoGreen's.
|
|
-- Until now this replayed `result/animation.json` ids 21/22/23: scale 0 -> 1.15 over 166.67 ms
|
|
-- (ease-out quad), 1.15 -> 1.0 over 66.67 ms, alpha 0 -> 1 over 166.67 ms. The cabinet's
|
|
-- `msg_L_mc` (result/result.nulm sprite 283) plays the SAME nine frames for all four states
|
|
-- (labels perfect 5 / success 35 / near 65 / miss 95) and they are a different shape:
|
|
-- f0..f4 scale 0.500 -> 0.806 -> 1.025 -> 1.156 -> 1.200, alpha 0 -> .438 -> .75 -> .938 -> 1
|
|
-- f4..f9 scale 1.200 -> 1.192 -> 1.168 -> 1.128 -> 1.072 -> 1.000, alpha 1
|
|
-- i.e. it starts at HALF size (not zero), overshoots to 1.20 (not 1.15) in 66.7 ms (not 166.7),
|
|
-- and is fully open at 150 ms instead of 233 ms. The numbers come from
|
|
-- `Scripts/anim/result_msg.lua`, exported by scratchpad/anim_export.py (ANIM_PIPELINE.md);
|
|
-- nothing here is fitted by eye.
|
|
--
|
|
-- The bubble PNGs no longer bake the message in -- text is drawn separately with
|
|
-- `text.create_text`, sharing the bubble's pop scale/fade so the two still move as one.
|
|
-- (The cabinet fades its TEXT in separately, five frames behind the bubble art; we don't
|
|
-- replicate that stagger here -- the exported sample table only covers the "success" label
|
|
-- range MSG_F0..MSG_F1, so sampling f-4 near f0 would land before that range starts.)
|
|
ResultCrownMessage = {}
|
|
ResultCrownMessage.__index = ResultCrownMessage
|
|
|
|
local F = 1000 / 60
|
|
|
|
-- FAIL SOFT (ROUND 8 rule): a missing or malformed generated table must degrade to "no pop",
|
|
-- never take the result screen down at require time.
|
|
local _ok, msg_anim = pcall(require, "anim/sampler")
|
|
if not _ok then msg_anim = { safe = function()
|
|
local n = {}
|
|
n.at = function() return nil end; n.get = function() return nil end
|
|
n.label = function() return nil end; n.has = function() return false end
|
|
n.first = function() return 0 end; n.last = function() return 0 end
|
|
return n
|
|
end } end
|
|
local MSG = msg_anim.safe("anim/result_msg")
|
|
local MSG_TRACK = "#277@0"
|
|
local MSG_F0 = MSG:label("success") or 35 -- the exported range starts here
|
|
local MSG_F1 = math.max(MSG_F0, MSG:last())
|
|
|
|
-- frame (pre is_2p offset) is the judgement: 0 miss, 1 near, 2 success, 3 perfect
|
|
-- (result_player.lua's gauge_state/gauge_length -> frame mapping).
|
|
local MSG_KEY = {
|
|
[0] = "crown_message_miss",
|
|
[1] = "crown_message_near",
|
|
[2] = "crown_message_success",
|
|
[3] = "crown_message_perfect",
|
|
}
|
|
|
|
-- Bubble centres, from Graphics/result/crown/texture.json's "message" entries
|
|
-- (1P x=410, 2P x=989, both y=626) plus half the bubble art's canvas size (520x340,
|
|
-- unchanged from the original baked PNGs) -- the anchor `tex.draw_texture(...,
|
|
-- center = true)` scales around.
|
|
local MSG_W, MSG_H = 520, 340
|
|
local MSG_CENTER = {
|
|
{ 410 + MSG_W / 2, 626 + MSG_H / 2 }, -- 1P
|
|
{ 989 + MSG_W / 2, 626 + MSG_H / 2 }, -- 2P
|
|
}
|
|
|
|
function ResultCrownMessage.new(frame, is_2p)
|
|
local self = setmetatable({}, ResultCrownMessage)
|
|
self.t0 = tex.get_current_ms()
|
|
self.now = self.t0
|
|
self.frame = frame + (is_2p and 4 or 0)
|
|
self.is_2p = is_2p
|
|
self.t_msg = tex.load_texture("result/crown/message")
|
|
local key = MSG_KEY[frame]
|
|
self.t_text = key and text.create_text(key, { 255, 255, 255, 255 }, { 0, 0, 0, 255 }, false, 4, 2) or nil
|
|
return self
|
|
end
|
|
|
|
function ResultCrownMessage:update(current_ms)
|
|
self.now = current_ms
|
|
end
|
|
|
|
function ResultCrownMessage:draw()
|
|
if not self.t_msg then return end
|
|
local f = MSG_F0 + (self.now - self.t0) * 0.06
|
|
if f > MSG_F1 then f = MSG_F1 end
|
|
local scale = MSG:get(MSG_TRACK, f, "sx") or 1.0
|
|
local fade = MSG:get(MSG_TRACK, f, "a") or 1.0
|
|
if fade <= 0 then return end
|
|
tex.draw_texture(self.t_msg, {
|
|
frame = self.frame, scale = scale, center = true, fade = fade,
|
|
index = self.is_2p and 1 or 0,
|
|
})
|
|
|
|
local t = self.t_text
|
|
if t and t.width and t.width > 0 then
|
|
local c = MSG_CENTER[self.is_2p and 2 or 1]
|
|
local w, h = t.width * scale, t.height * scale
|
|
t:draw({
|
|
x = c[1] - w / 2, y = c[2] - h / 2,
|
|
x2 = w - t.width, y2 = h - t.height,
|
|
fade = fade,
|
|
})
|
|
end
|
|
end
|