116 lines
4.1 KiB
Lua
116 lines
4.1 KiB
Lua
-- The score on the lane cover, and the "+100 / +300 ..." numbers that pop up before they are added
|
|
-- to it. The engine's ScoreCounter (score_counter.h) calls update every frame with the player's
|
|
-- score and add_popup whenever points are earned; this owns the animations and draws them.
|
|
|
|
local SKIN = {
|
|
delay_score_addition = true, -- the counter catches up when a popup finishes, not at once
|
|
margin = 30,
|
|
pos = { x = 913.5, y = -16.5 },
|
|
popup_p2_offset = 382.5,
|
|
}
|
|
|
|
ScoreCounter = {}
|
|
ScoreCounter.__index = ScoreCounter
|
|
|
|
local MAX_POPUPS = 5 -- add_popup(value, true) drops a popup past this many
|
|
local POPUP_COLOR = { { 254, 102, 0 }, { 84, 250, 238 } } -- by player
|
|
|
|
local function digit(ch)
|
|
return (ch >= 48 and ch <= 57) and ch - 48 or 0
|
|
end
|
|
|
|
function ScoreCounter.new(is_2p, player_num)
|
|
local self = setmetatable({}, ScoreCounter)
|
|
self.is_2p = is_2p
|
|
self.player_num = player_num
|
|
self.score = 0
|
|
self.stretch = tex.get_animation(4, true)
|
|
self.t_cover = tex.get_texture("lane/lane_score_cover")
|
|
self.t_number = tex.get_texture("lane/score_number")
|
|
self.popups = {}
|
|
return self
|
|
end
|
|
|
|
function ScoreCounter:set_count(score)
|
|
if score ~= self.score then
|
|
self.score = score
|
|
self.stretch:start()
|
|
end
|
|
end
|
|
|
|
function ScoreCounter:add_popup(value, limited)
|
|
if limited and #self.popups >= MAX_POPUPS then return end
|
|
local anim = function(id)
|
|
local a = tex.get_animation(id, true)
|
|
a:start()
|
|
return a
|
|
end
|
|
local str = tostring(math.max(math.floor(value), 0))
|
|
local base = POPUP_COLOR[self.player_num] or POPUP_COLOR[1]
|
|
self.popups[#self.popups + 1] = {
|
|
str = str, base = base, alpha = 255, y_list = {},
|
|
fade_1 = anim(35), move_x = anim(36), fade_2 = anim(37), move_y_pre = anim(38), move_y_fan = anim(39),
|
|
}
|
|
end
|
|
|
|
-- score: the player's current score. With delay_score_addition the counter only catches up
|
|
-- once a popup has finished, otherwise it follows at once.
|
|
function ScoreCounter:update(ms, score)
|
|
local delay = SKIN.delay_score_addition
|
|
local i = 1
|
|
while i <= #self.popups do
|
|
local p = self.popups[i]
|
|
p.fade_1:update(ms)
|
|
p.move_x:update(ms)
|
|
p.move_y_pre:update(ms)
|
|
p.move_y_fan:update(ms)
|
|
p.fade_2:update(ms)
|
|
local fade = p.fade_1.is_finished and p.fade_2.attribute or p.fade_1.attribute
|
|
p.alpha = 255 * fade
|
|
for k = 1, #p.str do p.y_list[k] = p.move_y_fan.attribute + (k - 1) * 5 end
|
|
if p.fade_2.is_finished then
|
|
table.remove(self.popups, i)
|
|
if delay then self:set_count(score) end
|
|
else
|
|
i = i + 1
|
|
end
|
|
end
|
|
if not delay then self:set_count(score) end
|
|
self.stretch:update(ms)
|
|
end
|
|
|
|
function ScoreCounter:draw(y)
|
|
local p2_offset = self.is_2p and tex.get_skin_config("game_score_counter_2p_y_offset").y or 0
|
|
if self.is_2p then
|
|
tex.draw_texture(self.t_cover, { mirror = "vertical", y = y + p2_offset })
|
|
else
|
|
tex.draw_texture(self.t_cover, { y = y })
|
|
end
|
|
|
|
local str = tostring(math.max(self.score, 0))
|
|
local margin, stretch = SKIN.margin, self.stretch.attribute
|
|
local start_x = SKIN.pos.x - #str * margin
|
|
local y_pos = y + SKIN.pos.y + p2_offset
|
|
for i = 1, #str do
|
|
tex.draw_texture(self.t_number, {
|
|
frame = str:byte(i) - 48, x = start_x + (i - 1) * margin, y = y_pos - stretch, y2 = stretch,
|
|
})
|
|
end
|
|
|
|
local direction = self.is_2p and -1 or 1
|
|
for _, p in ipairs(self.popups) do
|
|
local x = p.move_x.attribute
|
|
if math.abs(x) >= 1e-6 then
|
|
local px = x - #p.str * margin
|
|
local color = { p.base[1], p.base[2], p.base[3], p.alpha }
|
|
for i = 1, #p.str do
|
|
local y_i = p.move_y_pre.is_finished and p.y_list[i] or p.move_y_pre.attribute
|
|
tex.draw_texture(self.t_number, {
|
|
color = color, frame = digit(p.str:byte(i)), x = px + (i - 1) * margin,
|
|
y = y_i * direction + y + (self.is_2p and SKIN.popup_p2_offset or 0),
|
|
})
|
|
end
|
|
end
|
|
end
|
|
end
|