Compare commits

...
Author SHA1 Message Date
Yonokid 63fc881fd4 Merge branch 'main' into result-2p-colors 2026-09-09 17:13:27 +02:00
Yonokid 9a22f8f1c9 Merge pull request 'Roll effect: fly over the lower backdrop along the original paths' (#12) from GanYiZhong/YataiDONNijiiro:renda-lower-bg into main
Reviewed-on: Yonokid/YataiDONNijiiro#12
2026-09-09 17:13:14 +02:00
Yonokid eb10ba2c5f Merge branch 'main' into renda-lower-bg 2026-09-09 17:12:09 +02:00
Yonokid 9b08a5d4df Merge pull request 'Soul-max crowd: replay the per-group movie instead of a flat overlay' (#10) from GanYiZhong/YataiDONNijiiro:fever-crowd-anim into main
Reviewed-on: Yonokid/YataiDONNijiiro#10
2026-09-09 17:10:35 +02:00
TaikoZhongandClaude Fable 5.1 f75abf6107 Result: 2P backdrop is red on the left and cyan on the right
The double-play result plate was baked from the wrong atlas layer, so it came
out orange / teal with the header band burnt in. Rebuilt from the original's
two sky halves (the left one placed mirrored) and the header band is now drawn
by the layer code, the same way the 1P backdrop draws it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 12:01:49 +08:00
TaikoZhongandClaude Fable 5.1 166174865d Roll effect: 60 Hz and a pool of ten
Checked against the original: the pieces cross at half the speed the 120 Hz
step gave them, and only about ten are ever live -- the oldest is replaced as
soon as an eleventh starts.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 11:35:53 +08:00
TaikoZhongandClaude Fable 5.1 d9869cfde0 Roll effect: fly over the lower backdrop along the original paths
The birds / shuriken / arrows spawned in the top-left corner and swept across
the top band. The original spawns them over the lower backdrop (x 6..1100,
y 540..1020), behind the dancers, and each movie has its own path: birds and
arrows rise to the right, shuriken fly level and spin. Replayed at 120 Hz for
120 frames, same 25-slot pool as before.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 11:26:55 +08:00
3 changed files with 61 additions and 103 deletions

No files matched your search

Binary file not shown.

Before

Width:  |  Height:  |  Size: 481 KiB

After

Width:  |  Height:  |  Size: 392 KiB

+55 -101
View File
@@ -1,122 +1,74 @@
-- YataiDON-HSS override of PyTaikoGreen/background/bg_objects/renda.lua: Renda1 origin from x2[1]/y2[1]; frame from frame_count
-- The three roll effects, replayed the way the original places them: a piece is
-- spawned somewhere over the LOWER backdrop (x 6..1100, y 540..1020 -- the region
-- the original's spawn box covers below the lane) and flies for 120 frames at
-- 60 Hz along its movie's own path:
-- renda_0 birds (chidori) +17.3 px/frame right, -10.9 px/frame up
-- renda_1 shuriken (shuriken) +17.3 px/frame right, level, spinning -6 deg/frame
-- renda_2 arrow (hamaya) +13.1 px/frame right, -13.8 px/frame up
-- They are drawn before the dancers (see background.lua), as the original does.
local FRAME_MS = 1000.0 / 60.0
local LIFE = 120
local SPAWN_X0, SPAWN_X1 = 6, 1100
local SPAWN_Y0, SPAWN_Y1 = 540, 1020
local BaseRenda = {}
BaseRenda.__index = BaseRenda
function BaseRenda.new(index)
function BaseRenda.new(index, vx, vy, spin)
local self = setmetatable({}, BaseRenda)
self.name = "renda_" .. index
local screen_width = tex.get_screen_width()
local screen_scale = tex.get_screen_scale()
self.hori_move = anim.move(1500 * screen_scale, {total_distance = screen_width})
self.hori_move:start()
self.vx, self.vy, self.spin = vx, vy, spin or 0
self.x0 = math.random(SPAWN_X0, SPAWN_X1)
self.y0 = math.random(SPAWN_Y0, SPAWN_Y1)
self.frames = 0
self.last_ms = nil
local info = tex.get_texture_info("renda", self.name)
self.frame = math.random(0, ((info and info.frame_count) or 1) - 1)
self.w = (info and info.x2 and info.x2[1]) or 0
self.h = (info and info.y2 and info.y2[1]) or 0
self._id = tex.get_id("renda", self.name) -- nil = missing (ROUND 60: id 0 is valid)
return self
end
function BaseRenda:update(current_time_ms)
self.hori_move:update(current_time_ms)
if self.last_ms then
local dt = current_time_ms - self.last_ms
if dt > 0 and dt < 500 then self.frames = self.frames + dt / FRAME_MS end
end
self.last_ms = current_time_ms
end
function BaseRenda:finished()
return self.frames >= LIFE
end
function BaseRenda:draw(y_offset)
if not self._id or self:finished() then return end
local f = self.frames
local cx = self.x0 + self.vx * f
local cy = self.y0 + self.vy * f + (y_offset or 0)
if self.spin ~= 0 then
tex.draw_texture(self._id, {
frame = self.frame, x = cx, y = cy,
origin = { self.w * 0.5, self.h * 0.5 }, rotation = self.spin * f,
})
else
tex.draw_texture(self._id, { frame = self.frame, x = cx - self.w * 0.5, y = cy - self.h * 0.5 })
end
end
local Renda0 = setmetatable({}, {__index = BaseRenda})
Renda0.__index = Renda0
function Renda0.new(index)
local self = setmetatable({}, Renda0)
local base = BaseRenda.new(index)
for k, v in pairs(base) do self[k] = v end
local screen_scale = tex.get_screen_scale()
local screen_height = tex.get_screen_height()
self.vert_move = anim.move(1500 * screen_scale, {total_distance = screen_height + (80 * screen_scale)})
self.vert_move:start()
local tex_info = tex.get_texture_info("renda", self.name)
local num_frames = (tex_info and tex_info.frame_count) or 1
self.frame = math.random(0, num_frames - 1)
self.x = math.random(0, math.floor(500 * screen_scale))
self.y = math.random(0, math.floor(20 * screen_scale))
self._id = tex.get_id("renda", self.name) -- nil = missing (ROUND 60: id 0 is valid)
return self
end
function Renda0:update(current_time_ms)
BaseRenda.update(self, current_time_ms)
self.vert_move:update(current_time_ms)
end
function Renda0:draw(y_offset)
-- ROUND 60 (r60-collab-fix-all): fail soft when the collab ships no renda art
if not self._id then return end
tex.draw_texture(self._id, {
frame = self.frame,
x = self.hori_move.attribute + self.x,
y = -self.vert_move.attribute + self.y + (y_offset or 0)
})
end
function Renda0.new(index) return setmetatable(BaseRenda.new(index, 17.3, -10.9), Renda0) end
local Renda1 = setmetatable({}, {__index = BaseRenda})
Renda1.__index = Renda1
function Renda1.new(index)
local self = setmetatable({}, Renda1)
local base = BaseRenda.new(index)
for k, v in pairs(base) do self[k] = v end
local screen_scale = tex.get_screen_scale()
local screen_height = tex.get_screen_height()
local tex_info = tex.get_texture_info("renda", self.name)
self.frame = math.random(0, ((tex_info and tex_info.frame_count) or 6) - 1)
self.y = math.random(0, math.floor(200 * screen_scale))
self.rotate = anim.move(800 * screen_scale, {total_distance = math.floor(screen_height / 2), loop = true})
self.rotate:start()
self.origin = {(tex_info and tex_info.x2[1] or 0) / 2, (tex_info and tex_info.y2[1] or 0) / 2}
self._id = tex.get_id("renda", self.name) -- nil = missing (ROUND 60: id 0 is valid)
return self
end
function Renda1:update(current_time_ms)
BaseRenda.update(self, current_time_ms)
self.rotate:update(current_time_ms)
end
function Renda1:draw(y_offset)
-- ROUND 60 (r60-collab-fix-all): fail soft when the collab ships no renda art
if not self._id then return end
tex.draw_texture(self._id, {
frame = self.frame,
x = self.hori_move.attribute + self.origin[1],
y = self.y + self.origin[2] + (y_offset or 0),
origin = self.origin,
rotation = self.rotate.attribute
})
end
function Renda1.new(index) return setmetatable(BaseRenda.new(index, 17.3, 0, -6), Renda1) end
local Renda2 = setmetatable({}, {__index = BaseRenda})
Renda2.__index = Renda2
function Renda2.new(index)
local self = setmetatable({}, Renda2)
local base = BaseRenda.new(index)
for k, v in pairs(base) do self[k] = v end
local screen_scale = tex.get_screen_scale()
local screen_height = tex.get_screen_height()
self.vert_move = anim.move(1500, {total_distance = screen_height + (80 * screen_scale)})
self.vert_move:start()
self.x = math.random(0, math.floor(500 * screen_scale))
self.y = math.random(0, math.floor(20 * screen_scale))
self._id = tex.get_id("renda", self.name) -- nil = missing (ROUND 60: id 0 is valid)
return self
end
function Renda2:update(current_time_ms)
BaseRenda.update(self, current_time_ms)
self.vert_move:update(current_time_ms)
end
function Renda2:draw(y_offset)
-- ROUND 60 (r60-collab-fix-all): fail soft when the collab ships no renda art
if not self._id then return end
tex.draw_texture(self._id, {
x = self.hori_move.attribute + self.x,
y = -self.vert_move.attribute + self.y + (y_offset or 0)
})
end
function Renda2.new(index) return setmetatable(BaseRenda.new(index, 13.1, -13.8), Renda2) end
-- ROUND 52 (r52-lua-divergence-fixes): the cabinet's renda effect is a FIXED
-- round-robin pool, not an unbounded per-hit spawner. the reference build
@@ -136,7 +88,9 @@ end
-- is still per-hit -- there is no per-frame "roll active" Lua signal -- so a
-- slow roll spawns fewer than the cabinet's one-per-frame; the cap and the
-- steady-state density now match.)
local POOL_SIZE = 25
-- Observed on the original: about ten pieces are ever live at once -- the oldest
-- is dropped as soon as an eleventh starts, before it leaves the screen.
local POOL_SIZE = 10
local RendaController = {}
RendaController.__index = RendaController
@@ -174,7 +128,7 @@ function RendaController:update(current_time_ms)
local r = self.rendas[slot]
if r then
r:update(current_time_ms)
if r.hori_move.is_finished then
if r:finished() then
self.rendas[slot] = nil
end
end
+6 -2
View File
@@ -61,8 +61,11 @@ function ResultBgLayers.new(player_num)
if self.two_player then
-- The arcade 2P backdrop (main_mc "2p" -> bg_2p, MC 10) is two static sky halves with no
-- clouds and no Fuji, so it stays a single baked plate.
self.t_bg = tex.load_texture("result/background/background_2p")
-- clouds and no Fuji, so it stays a single baked plate: the red half (shape 3, placed
-- mirrored) on the left and the cyan half (shape 1) on the right. The header band is
-- the same one the 1P layers draw, so it is drawn here too instead of being baked in.
self.t_bg = tex.load_texture("result/background/background_2p")
self.t_header = tex.load_texture("result/background/bg_header")
return self
end
@@ -172,6 +175,7 @@ function ResultBgLayers:draw(fade, clear)
if self.two_player then
if self.t_bg then tex.draw_texture(self.t_bg, { fade = fade }) end
if self.t_header then tex.draw_texture(self.t_header, { fade = fade }) end
return
end