Fielder.catchEligible -> Ball.catchable

Much simpler
This commit is contained in:
Sage Vaillancourt 2025-02-19 23:06:22 -05:00
parent b003c148a4
commit 699dab8c7d
4 changed files with 22 additions and 45 deletions

View File

@ -4,12 +4,12 @@
---@field z number
---@field size number
---@field heldBy Fielder | nil
---@field catchable boolean
---@field xAnimator SimpleAnimator
---@field yAnimator SimpleAnimator
---@field sizeAnimator SimpleAnimator
---@field floatAnimator SimpleAnimator
---@field private animatorLib pd_animator_lib
---@field private flyTimeMs number
Ball = {}
---@param animatorLib pd_animator_lib
@ -20,6 +20,7 @@ function Ball.new(animatorLib)
x = C.Center.x --[[@as number]],
y = C.Center.y --[[@as number]],
z = 0,
catchable = true,
size = C.SmallestBallRadius,
heldBy = nil --[[@type Runner | nil]],
@ -49,6 +50,13 @@ function Ball:updatePosition()
end
end
function Ball:markUncatchable()
self.catchable = false
playdate.timer.new(200, function()
self.catchable = true
end)
end
--- Launches the ball from its current position to the given destination.
---@param destX number
---@param destY number
@ -60,12 +68,13 @@ function Ball:launch(destX, destY, easingFunc, flyTimeMs, floaty, customBallScal
throwMeter:reset()
self.heldBy = nil
-- Prevent silly insta-catches
self:markUncatchable()
if not flyTimeMs then
flyTimeMs = utils.distanceBetween(self.x, self.y, destX, destY) * C.DefaultLaunchPower
end
self.flyTimeMs = flyTimeMs
if customBallScaler then
self.sizeAnimator = customBallScaler
else

View File

@ -1,5 +1,4 @@
--- @class Fielder {
--- @field catchEligible boolean
--- @field x number
--- @field y number
--- @field target XyPair | nil
@ -21,7 +20,6 @@ local function newFielder(name, speed)
return {
name = name,
speed = speed * C.FielderRunMult,
catchEligible = true,
}
end
@ -77,9 +75,9 @@ end
---@param deltaSeconds number
---@param fielder Fielder
---@param ballPos XyPair
---@return boolean inCatchingRange
local function updateFielderPosition(deltaSeconds, fielder, ballPos)
---@param ball Ball
---@return boolean canCatch
local function updateFielderPosition(deltaSeconds, fielder, ball)
if fielder.target ~= nil then
if
utils.pointIsSquarelyAboveLine(fielder, C.BottomOfOutfieldWall)
@ -89,7 +87,7 @@ local function updateFielderPosition(deltaSeconds, fielder, ballPos)
end
end
return utils.distanceBetweenPoints(fielder, ballPos) < C.BallCatchHitbox
return ball.catchable and utils.distanceBetweenPoints(fielder, ball) < C.BallCatchHitbox
end
-- TODO: Prevent multiple fielders covering the same base.
@ -115,16 +113,16 @@ function Fielding:haveSomeoneChase(ballDestX, ballDestY)
end
end
--- # Also updates `ball.heldby`
--- **Also updates `ball.heldby`**
---@param ball Ball
---@param deltaSeconds number
---@return Fielder | nil fielderHoldingBall nil if no fielder is currently touching the ball
function Fielding:updateFielderPositions(ball, deltaSeconds)
local fielderHoldingBall
for _, fielder in pairs(self.fielders) do
local inCatchingRange = updateFielderPosition(deltaSeconds, fielder, ball)
if inCatchingRange and fielder.catchEligible then
-- TODO: Base this catch on fielder skill?
-- TODO: Base this catch on fielder skill?
local canCatch = updateFielderPosition(deltaSeconds, fielder, ball)
if canCatch then
fielderHoldingBall = fielder
ball.heldBy = fielder -- How much havoc will this wreak?
end
@ -136,29 +134,6 @@ function Fielding:updateFielderPositions(ball, deltaSeconds)
return fielderHoldingBall
end
---@param fielder Fielder
function Fielding.markIneligible(fielder)
fielder.catchEligible = false
playdate.timer.new(500, function()
fielder.catchEligible = true
end)
end
function Fielding:markAllEligible(eligible)
for _, fielder in pairs(self.fielders) do
fielder.catchEligible = eligible
end
end
function Fielding:resetEligibility()
self:markAllEligible(false)
playdate.timer.new(750, function()
for _, fielder in pairs(self.fielders) do
fielder.catchEligible = true
end
end)
end
-- TODO? Start moving target fielders close sooner?
---@param field Fielding
---@param targetBase Base
@ -175,7 +150,6 @@ local function userThrowToCoroutine(field, targetBase, ball, throwFlyMs)
closestFielder.target = targetBase
ball:launch(targetBase.x, targetBase.y, playdate.easingFunctions.linear, throwFlyMs)
Fielding.markIneligible(field.fielderHoldingBall)
return
end

View File

@ -197,7 +197,7 @@ end
---@param pitchFlyTimeMs number | nil
---@param pitchTypeIndex number | nil
function Game:pitch(pitchFlyTimeMs, pitchTypeIndex)
Fielding.markIneligible(self.fielding.fielders.pitcher)
self.state.ball:markUncatchable()
self.state.ball.heldBy = nil
self.state.pitchIsOver = false
self.state.offenseState = C.Offense.batting
@ -445,8 +445,6 @@ function Game:returnToPitcher()
if not self.baserunning.batter then
self.baserunning:pushNewBatter()
end
self.fielding:resetEligibility()
self.fielding.fielders.pitcher.catchEligible = true
self.state.ball:launch(C.PitchStart.x, C.PitchStart.y, playdate.easingFunctions.linear, nil, true)
end)
end
@ -572,7 +570,6 @@ function Game:updateGameState()
while not self:pitcherIsReady() do
coroutine.yield()
end
self.fielding:markAllEligible(true)
self.state.offenseState = C.Offense.batting
end)
end

View File

@ -124,15 +124,12 @@ end
local function tryToMakeAPlay(fielders, fielder, runners, ball)
local targetX, targetY = getNextOutTarget(runners)
if targetX ~= nil and targetY ~= nil then
local nearestFielder = utils.getNearestOf(fielders, targetX, targetY, function(grabCandidate)
return grabCandidate.catchEligible
end)
local nearestFielder = utils.getNearestOf(fielders, targetX, targetY)
nearestFielder.target = utils.xy(targetX, targetY)
if nearestFielder == fielder then
ball.heldBy = fielder
else
ball:launch(targetX, targetY, playdate.easingFunctions.linear, nil, true)
Fielding.markIneligible(nearestFielder)
end
end
end