Roll effect: fly over the lower backdrop along the original paths #12
@@ -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
|
||||
|
||||
Reference in new issue
Block a user