Files
TaikoZhongandClaude Opus 5.5 48660a8b87 dan game: the soul gauge over the lane's top edge, as on the cabinet
The engine draws the lane after the gauge, and the lane's black top edge (y 276) hid the
cells' last six rows; the cabinet's gauge sits over it (cells down to y 281). The gauge
leaves a redraw (g_dan_gauge_redraw) that the dan background's draw_fore repeats, clipped
to that strip (y 276-288).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:01:01 +08:00

185 lines
7.1 KiB
Lua

-- YataiDON-HSS override of PyTaikoGreen/background/bg_collabs/dan.lua: bg_overlay/bg_overlay_2 tile step + scroll period use x2[1]
local DonBGBase = require("background/bg_objects/donbg/base")
local BGNormal = require("background/bg_objects/bg_normal")
local Footer = require("background/bg_objects/footer")
local ChibiController = require("background/bg_objects/chibi")
local DanInfo = require("background/bg_objects/dan_info")
local COLLAB_PATH = "background/collab/dan"
-- Custom DonBG: DonBG6 draw-shape but with extra bg_overlay_2 scroll
local DanDonBG = setmetatable({}, { __index = DonBGBase })
DanDonBG.__index = DanDonBG
function DanDonBG.new(player_num)
local self = setmetatable({}, DanDonBG)
local base = DonBGBase.new(1, player_num, COLLAB_PATH)
for k, v in pairs(base) do self[k] = v end
self.overlay_move = tex.get_animation(2, "background")
local bg_overlay_info = tex.get_texture_info(self.name, "bg_overlay")
self.bg_overlay_width = bg_overlay_info and bg_overlay_info.x2[1] or 0
local bg_overlay_2_info = tex.get_texture_info(self.name, "bg_overlay_2")
self.bg_overlay_2_width = bg_overlay_2_info and bg_overlay_2_info.x2[1] or 0
self.overlay_move_2 = anim.move(8000, {
total_distance = -self.bg_overlay_2_width, loop = true
})
self._id_bg_overlay = tex.get_texture(self.path .. "/" .. self.name .. "/bg_overlay") or 0
self._id_bg_overlay_2 = tex.get_texture(self.path .. "/" .. self.name .. "/bg_overlay_2") or 0
self._id_overlay_1 = tex.get_texture(self.path .. "/" .. self.name .. "/overlay_1") or 0
self._id_bg_overlay_3 = tex.get_texture(self.path .. "/" .. self.name .. "/bg_overlay_3") or 0
self._id_overlay_2 = tex.get_texture(self.path .. "/" .. self.name .. "/overlay_2") or 0
self._id_layer_a = tex.get_texture(self.path .. "/" .. self.name .. "/layer_a")
self._id_layer_b = tex.get_texture(self.path .. "/" .. self.name .. "/layer_b")
self._id_layer_c = tex.get_texture(self.path .. "/" .. self.name .. "/layer_c")
self._id_layer_d = tex.get_texture(self.path .. "/" .. self.name .. "/layer_d")
self._id_petal = tex.get_texture(self.path .. "/" .. self.name .. "/petal")
-- hand-built five-layer parallax band; missing layers are simply skipped.
local back, front = {}, {}
local function add(list, id, period, vx)
if id == nil then return end
table.insert(list, {
id = id, frame = 0, index = 0, period = period, vx = vx,
n = (period > 0) and (math.ceil(1920 / period) + 1) or 0,
})
end
add(back, self._id_bg, 0, 0) -- static plate (donbg_dojo_1p shape rec 0)
add(back, self._id_layer_a, 1920, -90.0000) -- #6@1 dark cloud silhouettes
add(back, self._id_layer_b, 1920, -72.0450) -- #10@2 outlined cloud bands
add(back, self._id_layer_c, 1920, -65.4918) -- #16@3 seigaiha-filled clouds
-- petals sit between the back and front lists
add(front, self._id_layer_d, 960, -45.0000) -- #27@6 sakura blossom row
-- 段位道場 title (bg_overlay_3) intentionally not drawn
self._layers_back = back
self._layers_front = front
self.states = { normal = {} }
for _, l in ipairs(back) do table.insert(self.states.normal, l) end
for _, l in ipairs(front) do table.insert(self.states.normal, l) end
-- use the hand-built layer list above
self.use_layers = true
return self
end
local PETAL_W, PETAL_H = 480, 240
local PETAL_LOOP_FRAMES = 320
local PETAL_X0, PETAL_Y0 = 2073.0, -218.0
local PETAL_DX, PETAL_DY = -4.36875, 2.321875
local PETAL_GAP = 960.0
-- background.png is 1920x280 pasted at screen y 0 and its row 0 is stage row
-- -2, so screen y = stage y + 2 and the band's bottom edge is screen y 278.
local BAND_Y_CONST = 2.0
local BAND_BOTTOM = 278.0
function DanDonBG:_draw_petals(y)
if self._id_petal == nil then return end
local f = (self.elapsed / (1000.0 / 60.0)) % PETAL_LOOP_FRAMES
local top = (PETAL_Y0 + PETAL_DY * f) - PETAL_H / 2.0 + BAND_Y_CONST + y
if top >= BAND_BOTTOM then return end
local h = BAND_BOTTOM - top
if h > PETAL_H then h = PETAL_H end
local cx = PETAL_X0 + PETAL_DX * f
for i = 0, 1 do
tex.draw_texture(self._id_petal, {
x = cx - i * PETAL_GAP - PETAL_W / 2.0,
y = top,
src = { x = 0, y = 0, width = PETAL_W, height = h },
y2 = h - PETAL_H,
})
end
end
-- petals sit between the back and front layers
function DanDonBG:draw(y)
y = y or 0
self:draw_layers(self._layers_back or {}, 1.0, y)
self:_draw_petals(y)
self:draw_layers(self._layers_front or {}, 1.0, y)
end
function DanDonBG:update(current_time_ms)
DonBGBase.update(self, current_time_ms)
self.overlay_move:update(current_time_ms)
self.overlay_move_2:update(current_time_ms)
end
-- dead code: DonBGBase:draw() uses self.states, not this hook.
function DanDonBG:draw_textures(fade, y, frame)
tex.draw_texture(self._id_bg, { y = y })
tex.draw_texture(self._id_bg_overlay_3)
end
-- Background
local DanBackground = {}
DanBackground.__index = DanBackground
function DanBackground.new(player_num, bpm)
local self = setmetatable({}, DanBackground)
self.donbg = DanDonBG.new(player_num)
self.bg_normal = BGNormal.Base.new(0, COLLAB_PATH)
self.footer = Footer.new(COLLAB_PATH, 0)
self.chibi = ChibiController.new(bpm, COLLAB_PATH, 2)
self.dan_info = DanInfo.new()
return self
end
function DanBackground:update(current_ms, bpm)
self.donbg:update(current_ms)
self.chibi:update(current_ms, bpm)
end
function DanBackground:handle_good(player_num) self.chibi:add_chibi(player_num, false) end
function DanBackground:handle_ok(player_num) self.chibi:add_chibi(player_num, false) end
function DanBackground:handle_bad(player_num) self.chibi:add_chibi(player_num, true) end
function DanBackground:handle_drumroll(player_num) end
function DanBackground:handle_balloon(player_num) end
function DanBackground:handle_gauge(player_num, progress, is_clear, is_rainbow)
self.donbg:set_clear(is_clear)
end
-- engine pushes the live 段位道場 exam state here every frame.
function DanBackground:handle_dan(player_num, state)
self.dan_info:handle(state)
end
function DanBackground:draw_back()
self.bg_normal:draw()
self.donbg:draw()
self.footer:draw()
self.chibi:draw()
end
-- the soul gauge's strip the lane covers (the cabinet draws the gauge over the lane), then
-- its threshold marker, on top of everything
local LANE_TOP, GAUGE_BOTTOM = 276, 288
function DanBackground:draw_fore()
local redraw = _G.g_dan_gauge_redraw
if redraw then
tex.begin_scissor(0, LANE_TOP, tex.get_screen_width(), GAUGE_BOTTOM - LANE_TOP)
local ok, err = pcall(redraw)
tex.end_scissor()
if not ok then error(err, 0) end
end
self.dan_info:draw_marker()
end
-- dan condition plate, drawn in the gauge's own layer.
function DanBackground:draw_gauge(player_num)
self.dan_info:draw()
end
function DanBackground:destroy()
self.donbg:destroy()
self.bg_normal:destroy()
self.footer:destroy()
self.chibi:destroy()
end
return DanBackground