152 lines
5.0 KiB
Lua
152 lines
5.0 KiB
Lua
---@class Characters
|
|
---@field homeSprites SpriteCollection
|
|
---@field awaySprites SpriteCollection
|
|
---@field homeBlipper table
|
|
---@field awayBlipper table
|
|
Characters = {}
|
|
|
|
local gfx <const> = playdate.graphics
|
|
|
|
local GloveSizeX, GloveSizeY <const> = Glove:getSize()
|
|
local GloveOffX, GloveOffY <const> = GloveSizeX / 2, GloveSizeY / 2
|
|
|
|
---@param homeSprites SpriteCollection
|
|
---@param awaySprites SpriteCollection
|
|
function Characters.new(homeSprites, awaySprites)
|
|
return setmetatable({
|
|
homeSprites = homeSprites,
|
|
awaySprites = awaySprites,
|
|
homeBlipper = blipper.new(100, homeSprites),
|
|
awayBlipper = blipper.new(100, awaySprites),
|
|
}, { __index = Characters })
|
|
end
|
|
|
|
---@param ball Point3d
|
|
---@param fielderX number
|
|
---@param fielderY number
|
|
---@return boolean isHoldingBall
|
|
local function drawFielderGlove(ball, fielderX, fielderY, flip)
|
|
local distanceFromBall = utils.distanceBetweenZ(fielderX, fielderY, 0, ball.x, ball.y, ball.z)
|
|
local shoulderX, shoulderY = fielderX + 10, fielderY - 5
|
|
if distanceFromBall > 20 then
|
|
Glove:draw(shoulderX, shoulderY, flip)
|
|
return false
|
|
else
|
|
GloveHoldingBall:draw(ball.x - GloveOffX, ball.y - GloveOffY, flip)
|
|
return true
|
|
end
|
|
end
|
|
|
|
---@param fieldingTeamSprites SpriteCollection
|
|
---@param fielder Fielder
|
|
---@param ball Point3d
|
|
---@param flip boolean | nil
|
|
---@return boolean isHoldingBall
|
|
function drawFielder(fieldingTeamSprites, fielder, ball, flip)
|
|
local danceOffset = FielderDanceAnimator:currentValue()
|
|
|
|
local x = fielder.x
|
|
local y = fielder.y + danceOffset
|
|
fieldingTeamSprites[fielder.spriteIndex].smiling:draw(fielder.x, y - 20, flip)
|
|
return drawFielderGlove(ball, x, y)
|
|
end
|
|
|
|
---@param batState BatRenderState
|
|
local function drawBat(batState)
|
|
gfx.setLineWidth(7)
|
|
gfx.drawLine(batState.batBase.x, batState.batBase.y, batState.batTip.x, batState.batTip.y)
|
|
|
|
gfx.setColor(gfx.kColorWhite)
|
|
gfx.setLineCapStyle(gfx.kLineCapStyleRound)
|
|
gfx.setLineWidth(3)
|
|
gfx.drawLine(batState.batBase.x, batState.batBase.y, batState.batTip.x, batState.batTip.y)
|
|
|
|
gfx.setColor(gfx.kColorBlack)
|
|
end
|
|
|
|
---@param battingTeamSprites SpriteCollection
|
|
---@param batter Runner
|
|
---@param batState BatRenderState
|
|
local function drawBatter(battingTeamSprites, batter, batState)
|
|
local spriteCollection = battingTeamSprites[batter.spriteIndex]
|
|
if batState.batAngleDeg > 50 and batState.batAngleDeg < 200 then
|
|
drawBat(batState)
|
|
spriteCollection.back:draw(batter.x, batter.y - C.PlayerHeightOffset)
|
|
else
|
|
spriteCollection.smiling:draw(batter.x, batter.y - C.PlayerHeightOffset)
|
|
drawBat(batState)
|
|
end
|
|
end
|
|
|
|
---@param battingTeam TeamId
|
|
---@return SpriteCollection battingTeam, SpriteCollection fieldingTeam, table runnerBlipper
|
|
function Characters:getSpriteCollections(battingTeam)
|
|
if battingTeam == "home" then
|
|
return self.homeSprites, self.awaySprites, self.homeBlipper
|
|
end
|
|
return self.awaySprites, self.homeSprites, self.awayBlipper
|
|
end
|
|
|
|
---@param fielding Fielding
|
|
---@param baserunning Baserunning
|
|
---@param batState BatRenderState
|
|
---@param battingTeam TeamId
|
|
---@param ball Point3d
|
|
---@return Fielder | nil ballHeldBy
|
|
function Characters:drawAll(fielding, baserunning, batState, battingTeam, ball)
|
|
---@type { y: number, drawAction: fun() }[]
|
|
local characterDraws = {}
|
|
function addDraw(y, drawAction)
|
|
characterDraws[#characterDraws + 1] = { y = y, drawAction = drawAction }
|
|
end
|
|
|
|
local battingTeamSprites, fieldingTeamSprites, runnerBlipper = self:getSpriteCollections(battingTeam)
|
|
---@type Fielder | nil
|
|
local ballHeldBy
|
|
for _, fielder in pairs(fielding.fielders) do
|
|
addDraw(fielder.y, function()
|
|
local ballHeldByThisFielder = drawFielder(fieldingTeamSprites, fielder, ball)
|
|
if ballHeldByThisFielder then
|
|
ballHeldBy = fielder
|
|
end
|
|
end)
|
|
end
|
|
|
|
for _, runner in pairs(baserunning.runners) do
|
|
addDraw(runner.y, function()
|
|
local currentBatter = baserunning.batter
|
|
if runner == currentBatter then
|
|
drawBatter(battingTeamSprites, currentBatter, batState)
|
|
else
|
|
-- TODO? Change blip speed depending on runner speed?
|
|
runnerBlipper:draw(false, runner.x, runner.y - C.PlayerHeightOffset, runner)
|
|
end
|
|
end)
|
|
end
|
|
|
|
for _, runner in pairs(baserunning.outRunners) do
|
|
addDraw(runner.y, function()
|
|
battingTeamSprites[runner.spriteIndex].frowning:draw(runner.x, runner.y - C.PlayerHeightOffset)
|
|
end)
|
|
end
|
|
for _, runner in pairs(baserunning.scoredRunners) do
|
|
addDraw(runner.y, function()
|
|
runnerBlipper:draw(false, runner.x, runner.y - C.PlayerHeightOffset, runner)
|
|
end)
|
|
end
|
|
|
|
table.sort(characterDraws, function(a, b)
|
|
return a.y < b.y
|
|
end)
|
|
for _, character in pairs(characterDraws) do
|
|
character.drawAction()
|
|
end
|
|
|
|
return ballHeldBy
|
|
end
|
|
|
|
-- luacheck: ignore
|
|
if not playdate or playdate.TEST_MODE then
|
|
return Characters
|
|
end
|