---@class MainMenu MainMenu = { ---@type { new: fun(settings: Settings): { update: fun(self) } } next = nil, } local gfx = playdate.graphics local StartFont = gfx.font.new("fonts/Roobert-20-Medium.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, homeTeamSprites = HomeTeamSprites, awayTeamSprites = AwayTeamSprites, }) 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 = inningCountSelection + 1 end if playdate.buttonJustPressed(playdate.kButtonDown) then inningCountSelection = inningCountSelection - 1 end GameLogo:drawCentered(C.Center.x, 50) StartFont:drawTextAligned("Press A to start!", C.Center.x, 140, kTextAlignment.center) gfx.drawTextAligned("with " .. inningCountSelection .. " innings", C.Center.x, 190, kTextAlignment.center) local ball = { x = animatorX:currentValue(), y = animatorY:currentValue(), z = 6, size = 6, } local ballIsHeld = drawFielder(AwayTeamSprites, ball, 30, 200) ballIsHeld = drawFielder(HomeTeamSprites, ball, 350, 200, playdate.graphics.kImageFlippedX) or ballIsHeld -- drawFielder(AwayTeamSprites, { x = 0, y = 0, z = 0 }, ball.x, ball.y) 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