123 lines
4.0 KiB
Lua
123 lines
4.0 KiB
Lua
require("entry/mac_popup")
|
|
|
|
CampaignMenu = {}
|
|
CampaignMenu.__index = CampaignMenu
|
|
|
|
local S = tex.get_screen_scale()
|
|
local FADE_MS = 250
|
|
local WAIT_MS = 1500
|
|
local SELECT_MS = 30000
|
|
local SLIDE_MS = 150
|
|
local OUT_MS, IN_MS = 167, 150
|
|
local ARROW_MS, ARROW_DX, ARROW_GAP = 1000, 30 * S, 600 * S
|
|
-- small panel left edge by slot offset; the centre slot sits under the big panel
|
|
local SLOT_X = { [-2] = -338, [-1] = 17, [0] = 482, [1] = 947, [2] = 1302 }
|
|
local SLOT_STEP, SLOT_Y = 355, 262 * S
|
|
local LEFT, RIGHT, DECIDE = 1, 2, 3
|
|
|
|
local function clamp01(v) return math.max(0.0, math.min(1.0, v)) end
|
|
|
|
local function slot_x(offset)
|
|
local lo = math.floor(offset)
|
|
local function at(k)
|
|
if k < -2 then return SLOT_X[-2] + (k + 2) * SLOT_STEP end
|
|
if k > 2 then return SLOT_X[2] + (k - 2) * SLOT_STEP end
|
|
return SLOT_X[k]
|
|
end
|
|
return (at(lo) + (at(lo + 1) - at(lo)) * (offset - lo)) * S
|
|
end
|
|
|
|
function CampaignMenu.new(ids)
|
|
for _, id in ipairs(ids) do
|
|
if id == "mac" then return MacPopup.new() end
|
|
end
|
|
local self = setmetatable({}, CampaignMenu)
|
|
self.ids = { "skip" }
|
|
for _, id in ipairs(ids) do self.ids[#self.ids + 1] = id end
|
|
self.small, self.main = {}, {}
|
|
for _, id in ipairs(self.ids) do
|
|
self.small[id] = tex.get_texture("entry/campaign/" .. id .. "_small")
|
|
self.main[id] = tex.get_texture("entry/campaign/" .. id .. "_main")
|
|
end
|
|
self.arrow = tex.get_texture("entry/campaign/arrow")
|
|
self.current = 1
|
|
self.t0 = tex.get_current_ms()
|
|
self.now = self.t0
|
|
self.turn = nil
|
|
self.decided = nil
|
|
if audio.has_sound("campaign_entry") then audio.play_sound("campaign_entry", "sound") end
|
|
return self
|
|
end
|
|
|
|
function CampaignMenu:update(current_ms)
|
|
self.now = current_ms
|
|
if not self.decided and current_ms - self.t0 >= WAIT_MS + SELECT_MS then
|
|
self:decide()
|
|
end
|
|
if self.turn and current_ms - self.turn.t0 >= OUT_MS + IN_MS then
|
|
self.turn = nil
|
|
end
|
|
end
|
|
|
|
function CampaignMenu:decide()
|
|
self.decided = self.now
|
|
end
|
|
|
|
function CampaignMenu:input(action)
|
|
if self.decided or self.turn or self.now - self.t0 < WAIT_MS then
|
|
return false
|
|
end
|
|
if action == DECIDE then
|
|
self:decide()
|
|
return true
|
|
end
|
|
local dir = action == RIGHT and 1 or -1
|
|
self.turn = { dir = dir, t0 = self.now, from = self.current }
|
|
self.current = (self.current - 1 + dir) % #self.ids + 1
|
|
return true
|
|
end
|
|
|
|
function CampaignMenu:is_done()
|
|
return self.decided ~= nil and self.now - self.decided >= FADE_MS
|
|
end
|
|
|
|
function CampaignMenu:get_choice()
|
|
return self.ids[self.current]
|
|
end
|
|
|
|
function CampaignMenu:draw()
|
|
local fade = clamp01((self.now - self.t0) / FADE_MS)
|
|
if self.decided then fade = 1 - clamp01((self.now - self.decided) / FADE_MS) end
|
|
local n = #self.ids
|
|
|
|
-- mid-turn every slot is still `dir` slots short of where it lands
|
|
local shift = 0
|
|
if self.turn then shift = self.turn.dir * (1 - clamp01((self.now - self.turn.t0) / SLIDE_MS)) end
|
|
for k = -3, 3 do
|
|
local offset = k + shift
|
|
if offset > -3 and offset < 3 then
|
|
local id = self.ids[(self.current - 1 + k) % n + 1]
|
|
tex.draw_texture(self.small[id], { x = slot_x(offset), y = SLOT_Y,
|
|
fade = fade * clamp01(math.abs(offset)) })
|
|
end
|
|
end
|
|
|
|
local id, main_fade = self.ids[self.current], 1
|
|
if self.turn then
|
|
local el = self.now - self.turn.t0
|
|
if el < OUT_MS then
|
|
id, main_fade = self.ids[self.turn.from], 1 - el / OUT_MS
|
|
else
|
|
main_fade = clamp01((el - OUT_MS) / IN_MS)
|
|
end
|
|
end
|
|
tex.draw_texture(self.main[id], { fade = fade * main_fade })
|
|
|
|
local el = self.now - self.t0 - WAIT_MS
|
|
if el >= 0 and not self.decided then
|
|
local u = (el % ARROW_MS) / ARROW_MS
|
|
tex.draw_texture(self.arrow, { x = -ARROW_DX * u, fade = fade * (1 - u) })
|
|
tex.draw_texture(self.arrow, { x = ARROW_GAP + ARROW_DX * u, fade = fade * (1 - u), mirror = "horizontal" })
|
|
end
|
|
end
|