-- selene: allow(shadowing) local gfx = playdate.graphics local ScoreFont = FontFullCircle local MinimapSizeX, MinimapSizeY = Minimap:getSize() local MinimapPosX, MinimapPosY = C.Screen.W - MinimapSizeX, C.Screen.H - MinimapSizeY local MinimapBoundX, MinimapBoundY = (MinimapSizeX + MinimapPosX), (MinimapSizeY + MinimapPosY) local MinimapMultX = 0.75 * MinimapSizeX / C.Screen.W local MinimapOffsetX = MinimapPosX + 5 local MinimapMultY = 0.70 * MinimapSizeY / C.FieldHeight local MinimapOffsetY = MinimapPosY - 15 local RunnerSquareWidth = 8 local FielderCircleRadius = 4 local FielderCircleStrokeWidth = 2 function drawMinimap(runners, fielders) Minimap:draw(MinimapPosX, MinimapPosY) gfx.setColor(gfx.kColorBlack) for _, runner in pairs(runners) do local x = (MinimapMultX * runner.x) + MinimapOffsetX local y = (MinimapMultY * runner.y) + MinimapOffsetY gfx.fillRect(x, y, RunnerSquareWidth, RunnerSquareWidth) end gfx.setLineWidth(FielderCircleStrokeWidth) for _, fielder in pairs(fielders) do local x = (MinimapMultX * fielder.x) + MinimapOffsetX local y = (MinimapMultY * fielder.y) + MinimapOffsetY if x > MinimapPosX and x < MinimapBoundX and y > MinimapPosY and y < MinimapBoundY then gfx.drawCircleAtPoint(x, y, FielderCircleRadius) end end end local BallStrikeMarginY = 4 local BallStrikeWidth = 60 local BallStrikeHeight = (BallStrikeMarginY * 2) + ScoreFont:getHeight() local BallStrikeAnimatorIn = playdate.graphics.animator.new(500, BallStrikeHeight, 0, playdate.easingFunctions.outBounce) local BallStrikeAnimatorOut = playdate.graphics.animator.new(500, 0, BallStrikeHeight, playdate.easingFunctions.linear) -- Start out of frame. local currentBallStrikeAnimator = utils.staticAnimator(20) function drawBallsAndStrikes(x, y, balls, strikes) if balls == 0 and strikes == 0 then if currentBallStrikeAnimator == BallStrikeAnimatorIn then currentBallStrikeAnimator = BallStrikeAnimatorOut currentBallStrikeAnimator:reset() end if currentBallStrikeAnimator:ended() then return end end if balls + strikes == 1 and currentBallStrikeAnimator ~= BallStrikeAnimatorIn then -- First pitch - should pop in now. currentBallStrikeAnimator = BallStrikeAnimatorIn currentBallStrikeAnimator:reset() end y = y + currentBallStrikeAnimator:currentValue() gfx.setColor(gfx.kColorBlack) gfx.fillRect(x, y, BallStrikeWidth, BallStrikeHeight) local originalDrawMode = gfx.getImageDrawMode() gfx.setImageDrawMode(gfx.kDrawModeInverted) local text = tostring(balls) .. " - " .. tostring(strikes) local textWidth = ScoreFont:getTextWidth(text) local widthDiff = BallStrikeWidth - textWidth ScoreFont:drawText(text, x + (widthDiff / 2), y + BallStrikeMarginY) gfx.setImageDrawMode(originalDrawMode) end local OutBubbleRadius = 5 local ScoreboardMarginX = 6 local ScoreboardMarginRight = 4 local ScoreboardHeight = 55 local Indicator = "> " local IndicatorWidth = ScoreFont:getTextWidth(Indicator) ---@param battingTeam any ---@return string, number, string, number function getIndicators(battingTeam) if battingTeam == "home" then return Indicator, 0, "", IndicatorWidth end return "", IndicatorWidth, Indicator, 0 end local stats = { homeScore = 0, awayScore = 0, outs = 0, inning = 1, battingTeam = nil, } function drawScoreboardImpl(x, y) local homeScore = stats.homeScore local awayScore = stats.awayScore local homeIndicator, homeOffset, awayIndicator, awayOffset = getIndicators(stats.battingTeam) local homeScoreText = homeIndicator .. "HOME " .. (homeScore > 9 and homeScore or " " .. homeScore) local awayScoreText = awayIndicator .. "AWAY " .. (awayScore > 9 and awayScore or " " .. awayScore) local rectWidth = (ScoreboardMarginX * 2) + ScoreboardMarginRight + ScoreFont:getTextWidth(homeScoreText) + homeOffset gfx.setLineWidth(1) gfx.setColor(gfx.kColorBlack) gfx.fillRect(x, y, rectWidth, ScoreboardHeight) local originalDrawMode = gfx.getImageDrawMode() gfx.setImageDrawMode(gfx.kDrawModeInverted) ScoreFont:drawText(homeScoreText, x + ScoreboardMarginX + homeOffset, y + 6) ScoreFont:drawText(awayScoreText, x + ScoreboardMarginX + awayOffset, y + 22) local inningOffsetX = (x + ScoreboardMarginX + IndicatorWidth) + (4 * 2.5 * OutBubbleRadius) ScoreFont:drawText(tostring(stats.inning), inningOffsetX, y + 39) gfx.setImageDrawMode(originalDrawMode) gfx.setColor(gfx.kColorWhite) function circleParams(i) local circleOffset = i * 2.5 * OutBubbleRadius return (x + ScoreboardMarginX + OutBubbleRadius + IndicatorWidth) + circleOffset, y + 46, OutBubbleRadius end for i = stats.outs, 2 do gfx.drawCircleAtPoint(circleParams(i)) end for i = 0, (stats.outs - 1) do gfx.fillCircleAtPoint(circleParams(i)) end end local newStats = stats function drawScoreboard(x, y, homeScore, awayScore, outs, battingTeam, inning) if newStats.homeScore ~= homeScore or newStats.awayScore ~= awayScore or newStats.outs ~= outs or newStats.inning ~= inning or newStats.battingTeam ~= battingTeam then newStats = { homeScore = homeScore, awayScore = awayScore, outs = outs, inning = inning, battingTeam = battingTeam, } playdate.timer.new(C.ScoreboardDelayMs, function() stats = newStats end) end drawScoreboardImpl(x, y) end