BatterUp/src/main-menu.lua

124 lines
3.6 KiB
Lua

---@class MainMenu
MainMenu = {
---@type { new: fun(settings: Settings): { update: fun(self) } }
next = nil,
}
local gfx = playdate.graphics
local StartFont <const> = gfx.font.new("fonts/Roobert-11-Medium.pft")
local TinyFont <const> = gfx.font.new("fonts/Nano Sans.pft")
--- Take control of playdate.update
--- Will replace playdate.update when the menu is done.
---@param next { new: fun(settings: Settings): { update: fun(self) } }
function MainMenu.start(next)
MenuMusic:play(0)
MainMenu.next = next
playdate.update = MainMenu.update
end
local inningCountSelection = 3
local function startGame()
local next = MainMenu.next.new({
finalInning = inningCountSelection,
homeTeamSpriteGroup = HomeTeamSpriteGroup,
awayTeamSpriteGroup = AwayTeamSpriteGroup,
})
playdate.resetElapsedTime()
transitionBetween(MainMenu, next)
MenuMusic:setPaused(true)
end
local function pausingEaser(baseEaser)
--- t: elapsedTime
--- d: duration
return function(t, b, c, d)
local percDone = t / d
if percDone > 0.9 then
t = d
elseif percDone < 0.1 then
t = 0
else
t = (percDone - 0.1) * 1.25 * d
end
return baseEaser(t, b, c, d)
end
end
local animatorX = gfx.animator.new(2000, 30, 350, pausingEaser(playdate.easingFunctions.linear))
animatorX.repeatCount = -1
animatorX.reverses = true
local animatorY = gfx.animator.new(2000, 60, 200, pausingEaser(utils.easingHill))
animatorY.repeatCount = -1
animatorY.reverses = true
local crankStartPos = nil
---@generic T
---@param array T[]
---@param crankPosition number
---@return T
local function arrayElementFromCrank(array, crankPosition)
local i = math.ceil(#array * (crankPosition + 0.001) / 360)
return array[i]
end
local currentLogo
--luacheck: ignore
function MainMenu:update()
playdate.timer.updateTimers()
crankStartPos = crankStartPos or playdate.getCrankPosition()
gfx.clear()
if playdate.getCrankChange() ~= 0 then
local crankOffset = (crankStartPos - playdate.getCrankPosition()) % 360
currentLogo = arrayElementFromCrank(Logos, crankOffset).image
replaceAwayLogo(currentLogo)
end
if currentLogo then
currentLogo:drawScaled(20, C.Center.y + 40, 3)
end
if playdate.buttonJustPressed(playdate.kButtonA) then
startGame()
end
if playdate.buttonJustPressed(playdate.kButtonUp) then
inningCountSelection = math.min(99, inningCountSelection + 1)
end
if playdate.buttonJustPressed(playdate.kButtonDown) then
inningCountSelection = math.max(1, inningCountSelection - 1)
end
local logoCenter = 90
GameLogo:drawCentered(C.Center.x, logoCenter)
TinyFont:drawTextAligned("a game by Sage", C.Center.x, logoCenter + 35, kTextAlignment.center)
StartFont:drawTextAligned("Press A to start!", C.Center.x, 180, kTextAlignment.center)
gfx.drawTextAligned("with " .. inningCountSelection .. " innings", C.Center.x, 210, kTextAlignment.center)
local ball = {
x = animatorX:currentValue(),
y = animatorY:currentValue(),
z = 6,
size = 6,
}
local ballIsHeld = drawFielder(AwayTeamSpriteGroup[1], ball, 30, 200)
ballIsHeld = drawFielder(HomeTeamSpriteGroup[2], ball, 350, 200, playdate.graphics.kImageFlippedX) or ballIsHeld
if not ballIsHeld then
gfx.setLineWidth(2)
gfx.setColor(gfx.kColorWhite)
gfx.fillCircleAtPoint(ball.x, ball.y, ball.size)
gfx.setColor(gfx.kColorBlack)
gfx.drawCircleAtPoint(ball.x, ball.y, ball.size)
end
end