BatterUp/src/control-screen.lua

101 lines
3.1 KiB
Lua

local gfx = playdate.graphics
local HeaderFont <const> = Roobert11Medium
local DetailFont <const> = FontFullCircle
---@alias TextObject { text: string, font: pd_font }
---@param texts TextObject[]
local function drawTexts(texts)
local xOffset = 10
local initialOffset <const> = -(HeaderFont:getHeight()) / 2
local yOffset = initialOffset
--- The text height plus a margin scaled to that height
function getOffsetOffset(textObject)
return (-4 + math.floor(textObject.font:getHeight() * 1.6)) / 2
end
-- Inverted buffer around text to separate it from the background
for _, textObject in ipairs(texts) do
local offsetOffset = getOffsetOffset(textObject)
yOffset = yOffset + offsetOffset
gfx.setImageDrawMode(gfx.kDrawModeInverted)
for x = xOffset - 6, xOffset + 6 do
for y = yOffset - 6, yOffset + 6 do
textObject.font:drawText(textObject.text, x, y)
end
end
yOffset = yOffset + offsetOffset
end
-- Drawing the actual text afterward (instead of inline) keeps the inverted buffer from drawing over it.
yOffset = initialOffset
gfx.setImageDrawMode(gfx.kDrawModeCopy)
for _, textObject in ipairs(texts) do
local offsetOffset = getOffsetOffset(textObject)
yOffset = yOffset + offsetOffset
textObject.font:drawText(textObject.text, xOffset, yOffset)
yOffset = yOffset + offsetOffset
end
end
---@param text string
---@return TextObject
local function header(text)
return { text = text, font = HeaderFont }
end
---@param text string
---@return TextObject
local function detail(text)
return { text = text, font = DetailFont }
end
---@class ControlScreen
---@field sceneToReturnTo Scene
---@field private renderedImage pd_image Static image doesn't need to be constantly re-rendered.
ControlScreen = {}
---@return pd_image
local function draw()
local image = gfx.image.new(C.Screen.W, C.Screen.H)
gfx.pushContext(image)
BallBackground:draw(0, 0)
drawTexts({
header("Batting:"),
detail("Swing the crank to swing your bat"),
detail("But watch out! Some pitches are tricky!"),
header("Pitching:"),
detail("Swing the crank to pitch the ball"),
detail("But be careful! Throw too hard and it might go wild!"),
detail("(shh: try holding A or B while you pitch)"),
header("Fielding:"),
detail("To throw, hold a direction button and crank!"),
detail("Right throws to 1st, Up goes to 2nd, etc."),
})
gfx.popContext()
return image
end
---@param sceneToReturnTo Scene
---@return ControlScreen
function ControlScreen.new(sceneToReturnTo)
return setmetatable({
sceneToReturnTo = sceneToReturnTo,
renderedImage = draw(),
}, { __index = ControlScreen })
end
function ControlScreen:update()
gfx.animation.blinker.updateAll()
gfx.clear()
self.renderedImage:draw(0, 0)
drawButton("B", 370, 210)
if playdate.buttonJustPressed(playdate.kButtonA) or playdate.buttonJustPressed(playdate.kButtonB) then
transitionBetween(self, self.sceneToReturnTo)
end
end