101 lines
3.1 KiB
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
|