Queue up announcement messages.

Extract drawScoreboard() to new scoreboard.lua
Very, very rudimentary team-switching.
This commit is contained in:
Sage Vaillancourt 2025-02-02 17:36:25 -05:00
parent 073140f700
commit 5fca82bb3a
5 changed files with 85 additions and 60 deletions

View File

@ -1,4 +1,4 @@
SOURCE_FILES := src/utils.lua src/graphics.lua src/main.lua
SOURCE_FILES := src/utils.lua src/graphics.lua src/scoreboard.lua src/main.lua
all:
pdc src BatterUp.pdx

View File

@ -13,3 +13,7 @@ json = json
-- selene: allow(unused_variable)
-- selene: allow(unscoped_variables)
kTextAlignment = kTextAlignment
-- selene: allow(unused_variable)
-- selene: allow(unscoped_variables)
printTable = printTable

View File

@ -7,18 +7,16 @@ import 'CoreLibs/object.lua'
import 'CoreLibs/timer.lua'
import 'CoreLibs/ui.lua'
--- @alias XYPair { x: number, y: number }
--- @alias Base { x: number, y: number }
--- @alias Runner { x: number, y: number, nextBase: Base, prevBase: Base | nil, forcedTo: Base }
--- @alias Fielder { onArrive: fun() | nil, x: number | nil, y: number | nil, target: XYPair | nil, speed: number }
import 'graphics.lua'
import 'scoreboard.lua'
import 'utils.lua'
-- stylua: ignore end
--- @alias XYPair { x: number, y: number }
--- @alias Base { x: number, y: number }
--- @alias Runner { x: number, y: number, nextBase: Base, prevBase: Base | nil, forcedTo: Base }
--- @alias Fielder { onArrive: fun() | nil, x: number | nil, y: number | nil, target: XYPair | nil, speed: number }
local gfx <const> = playdate.graphics
local Screen <const> = {
@ -32,8 +30,6 @@ local BatCrackSound <const> = playdate.sound.sampleplayer.new("sounds/bat-crack-
local GrassBackground <const> = gfx.image.new("images/game/grass.png") --[[@as pd_image]]
local PlayerFrown <const> = gfx.image.new("images/game/player-frown.png") --[[@as pd_image]]
local ScoreFont <const> = gfx.font.new("fonts/font-full-circle.pft")
local PlayerImageBlipper <const> = blipper.new(100, "images/game/player.png", "images/game/player-lowhat.png")
local DanceBounceMs <const> = 500
@ -234,26 +230,38 @@ function isTouchingBall(x, y)
return ballDistance < BallCatchHitbox
end
local outs = 0
local homeScore = 0
local awayScore = 0
local teams <const> = {
home = {
score = 0,
},
away = {
score = 0,
},
}
local battingTeam = teams.away
local outs = 0
function updateForcedRunners() end
function outRunner(runnerIndex)
outs = math.min(3, outs + 1)
outs = outs + 1
outRunners[#outRunners + 1] = runners[runnerIndex]
table.remove(runners, runnerIndex)
FielderDanceAnimator:reset()
updateForcedRunners()
announcer:say("YOU'RE OUT!")
if outs == 3 then
outs = 0
announcer:say("SWITCHING SIDES...")
battingTeam = battingTeam == teams.home and teams.away or teams.home
end
end
-- TODO: Away score
function score(runnerIndex)
outRunners[#outRunners + 1] = runners[runnerIndex]
table.remove(runners, runnerIndex)
homeScore = homeScore + 1
battingTeam.score = battingTeam.score + 1
announcer:say("SCORE!")
end
@ -542,46 +550,12 @@ function updateGameState()
updateOutRunners()
end
local OUT_BUBBLE_SIZE = 5
function drawScoreboard()
gfx.setFont(ScoreFont)
gfx.setDrawOffset(0, 0)
local y = Screen.H * 0.97
local x = 15
gfx.setLineWidth(1)
gfx.setColor(gfx.kColorBlack)
gfx.fillRect(x - 15, y - 44, 75, 55)
gfx.setColor(gfx.kColorWhite)
for i = outs, 2 do
gfx.drawCircleAtPoint(x - 2 + (i * 2.5 * OUT_BUBBLE_SIZE), y, OUT_BUBBLE_SIZE)
end
for i = 0, (outs - 1) do
gfx.fillCircleAtPoint(x - 2 + (i * 2.5 * OUT_BUBBLE_SIZE), y, OUT_BUBBLE_SIZE)
end
local originalDrawMode = gfx.getImageDrawMode()
gfx.setImageDrawMode(playdate.graphics.kDrawModeInverted)
local numOffsetX = gfx.getTextSize("AWAY ")
gfx.drawText("HOME ", x - 7, y - 38)
local homeScoreText = homeScore > 9 and homeScore or " " .. homeScore
gfx.drawText("" .. homeScoreText, x - 7 + numOffsetX, y - 38)
gfx.drawText("AWAY ", x - 7, y - 22)
local awayScoreText = awayScore > 9 and awayScore or " " .. awayScore
gfx.drawText("" .. awayScoreText, x - 7 + numOffsetX, y - 22)
gfx.setImageDrawMode(originalDrawMode)
end
function playdate.update()
updateGameState()
playdate.graphics.animation.blinker.updateAll()
playdate.timer.updateTimers()
updateGameState()
gfx.animation.blinker.updateAll()
gfx.clear()
if ball.x < BallOffscreen then
@ -620,7 +594,8 @@ function playdate.update()
PlayerFrown:draw(runner.x, runner.y)
end
drawScoreboard()
gfx.setDrawOffset(0, 0)
drawScoreboard(0, Screen.H * 0.77, teams, outs)
announcer:draw(Center.x, 10)
end

41
src/scoreboard.lua Normal file
View File

@ -0,0 +1,41 @@
local ScoreFont <const> = playdate.graphics.font.new("fonts/font-full-circle.pft")
local OutBubbleRadius <const> = 5
local ScoreboardMarginX <const> = 8
local ScoreboardHeight = 55
function drawScoreboard(x, y, teams, outs)
local gfx = playdate.graphics
local homeScore = teams.home.score
local awayScore = teams.away.score
local homeScoreText = "HOME " .. (homeScore > 9 and homeScore or " " .. homeScore)
local awayScoreText = "AWAY " .. (awayScore > 9 and awayScore or " " .. awayScore)
local rectWidth = (ScoreboardMarginX * 2) + ScoreFont:getTextWidth(homeScoreText)
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, y + 6)
ScoreFont:drawText(awayScoreText, x + ScoreboardMarginX, y + 22)
gfx.setImageDrawMode(originalDrawMode)
gfx.setColor(gfx.kColorWhite)
function circleParams(i)
return (x + ScoreboardMarginX + OutBubbleRadius) + (i * 2.5 * OutBubbleRadius), y + 46, OutBubbleRadius
end
for i = outs, 2 do
gfx.drawCircleAtPoint(circleParams(i))
end
for i = 0, (outs - 1) do
gfx.fillCircleAtPoint(circleParams(i))
end
end

View File

@ -136,19 +136,24 @@ end
local AnnouncementFont <const> = playdate.graphics.font.new("fonts/Roobert-20-Medium.pft")
-- selene: allow(unscoped_variables)
announcer = {}
announcer = {
textQueue = {},
}
function announcer.say(self, text, durationMs)
self.text = text
durationMs = durationMs and durationMs or 3000
self.textQueue[#self.textQueue + 1] = text
-- Could cause some timing funk if messages are queued up asyncronously.
-- I.e. `:say("hello")` <1.5 seconds pass> `:say("hello")` would result
-- in the second message being displayed for 4.5 seconds instead of just 3.
durationMs = durationMs and durationMs or (3000 * #self.textQueue)
playdate.timer.new(durationMs, function()
self.text = nil
table.remove(self.textQueue, 1)
end)
end
function announcer.draw(self, x, y)
if not self.text then
if #self.textQueue == 0 then
return
end
AnnouncementFont:drawTextAligned(self.text, x, y, kTextAlignment.center)
AnnouncementFont:drawTextAligned(self.textQueue[1], x, y, kTextAlignment.center)
end