forked from Yonokid/PyTaikoGreen
185 lines
6.1 KiB
Lua
185 lines
6.1 KiB
Lua
AISupportMenu = {}
|
|
AISupportMenu.__index = AISupportMenu
|
|
|
|
local FRAME_MS = 1000 / 60
|
|
local S_SCALE = tex.get_screen_scale()
|
|
local DIR = "song_select/ai_battle/"
|
|
local P2_OFFSET = 836
|
|
|
|
local BOARD_OFFSETS = { [1] = { 0 }, [4] = { -117, -39, 38, 116 } }
|
|
local COURSES = {
|
|
[0] = { board = "subdiff_easy", count = 1 },
|
|
[1] = { board = "subdiff_normal", count = 4 },
|
|
[2] = { board = "subdiff_hard", count = 4 },
|
|
[3] = { board = "subdiff_oni", count = 4 },
|
|
}
|
|
|
|
local SLIDE_IN = { { 0, 0, 0.2 }, { 5, -124, 1 }, { 15, -373, 1 }, { 21, -356, 1 } }
|
|
local SLIDE_OUT = { { 0, -356, 1 }, { 15, -89, 1 }, { 20, 0, 0 } }
|
|
local GRAY_FRAMES, GRAY_FADE = 30, 0.4
|
|
local GLOW_PERIOD, GLOW_LOW = 120, 0.7
|
|
local BRANCH_PERIOD = 120
|
|
|
|
local function slide_at(keys, frame)
|
|
for i = 2, #keys do
|
|
local a, b = keys[i - 1], keys[i]
|
|
if frame <= b[1] then
|
|
local t = math.max(0, (frame - a[1]) / (b[1] - a[1]))
|
|
return a[2] + (b[2] - a[2]) * t, a[3] + (b[3] - a[3]) * t
|
|
end
|
|
end
|
|
return keys[#keys][2], keys[#keys][3]
|
|
end
|
|
|
|
local function wave(frame, period, from, to)
|
|
local t = 1 - math.abs(2 * (frame % period) / period - 1)
|
|
return from + (to - from) * t
|
|
end
|
|
|
|
function AISupportMenu.new()
|
|
local self = setmetatable({}, AISupportMenu)
|
|
self.ids = {}
|
|
self.shown = false
|
|
self.slide_ms = -math.huge
|
|
self.course = 0
|
|
self.choose_ms = nil
|
|
return self
|
|
end
|
|
|
|
function AISupportMenu:id(key)
|
|
self.ids[key] = self.ids[key] or tex.get_texture(DIR .. key)
|
|
return self.ids[key]
|
|
end
|
|
|
|
function AISupportMenu:set_status(status)
|
|
self.status = status
|
|
self.rank_ids = {}
|
|
end
|
|
|
|
local RANK_DIR = "song_select/ai_rank/"
|
|
local RANK_MAX, ASSIGNED_RANK = 11, 10
|
|
local TODO_X, TODO_Y = 396, 590
|
|
local TODO_BACK = { [0] = 0, 0, 0, 1, 1, 2, 2, 3, 3, 3 }
|
|
|
|
function AISupportMenu:rank_tex(key, x, y, frame, fade, scale)
|
|
self.rank_ids[key] = self.rank_ids[key] or tex.get_texture(RANK_DIR .. key)
|
|
local o = { x = x * S_SCALE, y = y * S_SCALE, frame = frame or 0, fade = fade or 1 }
|
|
if scale then
|
|
local info = tex.get_texture_info("ai_rank", key)
|
|
o.x2 = info.width * S_SCALE * (scale - 1)
|
|
o.y2 = info.height * S_SCALE * (scale - 1)
|
|
end
|
|
tex.draw_texture(self.rank_ids[key], o)
|
|
end
|
|
|
|
function AISupportMenu:rank_number(key, value, right_x, y, step, scale)
|
|
value = math.max(0, math.floor(value))
|
|
local x = right_x
|
|
repeat
|
|
self:rank_tex(key, x, y, value % 10, 1, scale)
|
|
value = value // 10
|
|
x = x - step
|
|
until value == 0
|
|
end
|
|
|
|
function AISupportMenu:draw_rank_panels(ms)
|
|
local s = self.status
|
|
if not s then return end
|
|
if s.rank >= RANK_MAX then
|
|
self:rank_tex("rank_panel_max", 17, 146)
|
|
else
|
|
self:rank_tex("rank_panel", 17, 139)
|
|
if s.rank >= 10 then
|
|
self:rank_tex("digits_rank", 112.5, 117, 1)
|
|
self:rank_tex("digits_rank", 149.5, 117, s.rank - 10)
|
|
else
|
|
self:rank_tex("digits_rank", 131, 117, s.rank)
|
|
end
|
|
self:rank_number("digits_small", s.next_rank_tokens - s.tokens, 158, 189.2, 16.8, 0.8)
|
|
end
|
|
if s.next_reward_wins >= 0 then
|
|
self:rank_tex("wins_panel", 16, 225)
|
|
self:rank_number("digits_small", s.next_reward_wins - s.wins, 173, 277.2, 16.8, 0.8)
|
|
else
|
|
self:rank_tex("wins_panel_max", 44, 219)
|
|
end
|
|
self:rank_number("digits_wins", s.wins, 198.2, 243.2, 18, 0.8)
|
|
end
|
|
|
|
function AISupportMenu:draw_rank_todo(ms)
|
|
local s = self.status
|
|
if not s then return end
|
|
local pulse = 0.5 + 0.5 * wave(ms / FRAME_MS, 80, 0, 1)
|
|
if s.rank >= RANK_MAX then
|
|
self:rank_tex("todo_glow", TODO_X, TODO_Y, 0, pulse)
|
|
self:rank_tex("todo_strongest", TODO_X, TODO_Y)
|
|
self:rank_tex("todo_sparkle", TODO_X + 438, TODO_Y + 44, 0, wave(ms / FRAME_MS, 60, 0, 1))
|
|
elseif s.rank >= ASSIGNED_RANK then
|
|
self:rank_tex("todo_glow", TODO_X, TODO_Y, 0, pulse)
|
|
self:rank_tex("todo_strip", TODO_X, TODO_Y, 10)
|
|
else
|
|
self:rank_tex("todo_back", TODO_X, TODO_Y, TODO_BACK[s.rank])
|
|
self:rank_tex("todo_strip", TODO_X, TODO_Y, s.rank)
|
|
end
|
|
end
|
|
|
|
function AISupportMenu:draw(ms, course, cursor, choosing, branching, player, tension)
|
|
tex.draw_texture(self:id("tension"), { frame = tension })
|
|
self:draw_rank_panels(ms)
|
|
if course < 0 then self:draw_rank_todo(ms) end
|
|
|
|
local keys = self.shown and SLIDE_IN or SLIDE_OUT
|
|
local frame = (ms - self.slide_ms) / FRAME_MS
|
|
if (course >= 0) ~= self.shown and frame >= keys[#keys][1] then
|
|
self.shown = course >= 0
|
|
self.slide_ms = ms
|
|
keys = self.shown and SLIDE_IN or SLIDE_OUT
|
|
frame = 0
|
|
end
|
|
if not self.shown and frame >= keys[#keys][1] then
|
|
return
|
|
end
|
|
if self.shown then
|
|
self.course = course
|
|
end
|
|
|
|
local y, fade = slide_at(keys, frame)
|
|
local x = player == 2 and P2_OFFSET or 0
|
|
local function draw(key, params)
|
|
params = params or {}
|
|
params.x, params.y = (params.x or 0) + x, (params.y or 0) + y
|
|
params.fade = (params.fade or 1) * fade
|
|
tex.draw_texture(self:id(key), params)
|
|
end
|
|
|
|
if choosing and not self.choose_ms then
|
|
self.choose_ms = ms
|
|
end
|
|
if choosing then
|
|
local gray = math.min(1, (ms - self.choose_ms) / FRAME_MS / GRAY_FRAMES)
|
|
tex.draw_texture(self:id("gray_filter"), { x2 = 1264, y2 = 704, fade = GRAY_FADE * gray })
|
|
draw("box_bg", { fade = wave(ms / FRAME_MS, GLOW_PERIOD, 1, GLOW_LOW) })
|
|
draw("box_bg_blur")
|
|
draw("box_2")
|
|
draw("subdiff_select_text")
|
|
draw(player == 2 and "2p" or "1p")
|
|
else
|
|
draw("box_1")
|
|
end
|
|
|
|
local info = COURSES[self.course]
|
|
local offsets = BOARD_OFFSETS[info.count]
|
|
local row = info.count == 1 and 1 or 0
|
|
for i = 0, info.count - 1 do
|
|
local board_x = offsets[i + 1]
|
|
if choosing and i == cursor then
|
|
draw("subdiff_selector", { x = board_x, y = row })
|
|
end
|
|
draw(info.board, { frame = i, x = board_x, y = row })
|
|
if branching then
|
|
draw("branch_indicator", { x = board_x, y = row, fade = wave(ms / FRAME_MS, BRANCH_PERIOD, 0, 1) })
|
|
end
|
|
end
|
|
draw("bottom_text")
|
|
end
|