Fielders can catch passing balls.
Implemented with a new catchEligible field. Should be easy enough to add some erroring to those catches, too. Allow npc to control individual baserunners. Add a bit more dirt to the infield. This commit *does* introduce some entanglement between files. E.g. the markIneligible() calls, and overriding ball.heldBy from within Fielding
This commit is contained in:
parent
1926960c86
commit
a801b64f55
35
src/ball.lua
35
src/ball.lua
|
@ -1,6 +1,5 @@
|
||||||
-- selene: allow(unscoped_variables)
|
-- selene: allow(unscoped_variables)
|
||||||
---@class Ball
|
---@class Ball
|
||||||
---@field private animator pd_animator_lib
|
|
||||||
---@field x number
|
---@field x number
|
||||||
---@field y number
|
---@field y number
|
||||||
---@field z number
|
---@field z number
|
||||||
|
@ -10,13 +9,15 @@
|
||||||
---@field yAnimator SimpleAnimator
|
---@field yAnimator SimpleAnimator
|
||||||
---@field sizeAnimator SimpleAnimator
|
---@field sizeAnimator SimpleAnimator
|
||||||
---@field floatAnimator SimpleAnimator
|
---@field floatAnimator SimpleAnimator
|
||||||
|
---@field private animatorLib pd_animator_lib
|
||||||
|
---@field private flyTimeMs number
|
||||||
Ball = {}
|
Ball = {}
|
||||||
|
|
||||||
---@param animator pd_animator_lib
|
---@param animatorLib pd_animator_lib
|
||||||
---@return Ball
|
---@return Ball
|
||||||
function Ball.new(animator)
|
function Ball.new(animatorLib)
|
||||||
return setmetatable({
|
return setmetatable({
|
||||||
animator = animator,
|
animatorLib = animatorLib,
|
||||||
x = C.Center.x --[[@as number]],
|
x = C.Center.x --[[@as number]],
|
||||||
y = C.Center.y --[[@as number]],
|
y = C.Center.y --[[@as number]],
|
||||||
z = 0,
|
z = 0,
|
||||||
|
@ -29,10 +30,26 @@ function Ball.new(animator)
|
||||||
-- TODO? Replace these with a ballAnimatorZ?
|
-- TODO? Replace these with a ballAnimatorZ?
|
||||||
-- ...that might lose some of the magic of both. Compromise available? idk
|
-- ...that might lose some of the magic of both. Compromise available? idk
|
||||||
sizeAnimator = utils.staticAnimator(C.SmallestBallRadius),
|
sizeAnimator = utils.staticAnimator(C.SmallestBallRadius),
|
||||||
floatAnimator = animator.new(2000, -60, 0, utils.easingHill),
|
floatAnimator = animatorLib.new(2000, -60, 0, utils.easingHill),
|
||||||
}, { __index = Ball })
|
}, { __index = Ball })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Ball:updatePosition()
|
||||||
|
if self.heldBy then
|
||||||
|
self.x = self.heldBy.x
|
||||||
|
self.y = self.heldBy.y
|
||||||
|
self.z = C.GloveZ
|
||||||
|
self.size = C.SmallestBallRadius
|
||||||
|
else
|
||||||
|
self.x = self.xAnimator:currentValue()
|
||||||
|
local z = self.floatAnimator:currentValue()
|
||||||
|
-- TODO: This `+ z` is more graphics logic than physics logic
|
||||||
|
self.y = self.yAnimator:currentValue() + z
|
||||||
|
self.z = z
|
||||||
|
self.size = self.sizeAnimator:currentValue()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Launches the ball from its current position to the given destination.
|
--- Launches the ball from its current position to the given destination.
|
||||||
---@param destX number
|
---@param destX number
|
||||||
---@param destY number
|
---@param destY number
|
||||||
|
@ -47,14 +64,16 @@ function Ball:launch(destX, destY, easingFunc, flyTimeMs, floaty, customBallScal
|
||||||
flyTimeMs = utils.distanceBetween(self.x, self.y, destX, destY) * C.DefaultLaunchPower
|
flyTimeMs = utils.distanceBetween(self.x, self.y, destX, destY) * C.DefaultLaunchPower
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self.flyTimeMs = flyTimeMs
|
||||||
|
|
||||||
if customBallScaler then
|
if customBallScaler then
|
||||||
self.sizeAnimator = customBallScaler
|
self.sizeAnimator = customBallScaler
|
||||||
else
|
else
|
||||||
-- TODO? Scale based on distance?
|
-- TODO? Scale based on distance?
|
||||||
self.sizeAnimator = self.animator.new(flyTimeMs, 9, C.SmallestBallRadius, utils.easingHill)
|
self.sizeAnimator = self.animatorLib.new(flyTimeMs, 9, C.SmallestBallRadius, utils.easingHill)
|
||||||
end
|
end
|
||||||
self.yAnimator = self.animator.new(flyTimeMs, self.y, destY, easingFunc)
|
self.yAnimator = self.animatorLib.new(flyTimeMs, self.y, destY, easingFunc)
|
||||||
self.xAnimator = self.animator.new(flyTimeMs, self.x, destX, easingFunc)
|
self.xAnimator = self.animatorLib.new(flyTimeMs, self.x, destX, easingFunc)
|
||||||
if floaty then
|
if floaty then
|
||||||
self.floatAnimator:reset(flyTimeMs)
|
self.floatAnimator:reset(flyTimeMs)
|
||||||
end
|
end
|
||||||
|
|
|
@ -181,8 +181,10 @@ function Baserunning:updateRunner(runner, runnerIndex, appliedSpeed, deltaSecond
|
||||||
|
|
||||||
-- TODO: Do a better job drifting runners toward their bases when appliedSpeed is low/zero
|
-- TODO: Do a better job drifting runners toward their bases when appliedSpeed is low/zero
|
||||||
if distance < 2 then
|
if distance < 2 then
|
||||||
|
if runner.prevBase ~= nearestBase then
|
||||||
runner.prevBase = runner.nextBase
|
runner.prevBase = runner.nextBase
|
||||||
runner.nextBase = C.NextBaseMap[runner.nextBase]
|
runner.nextBase = C.NextBaseMap[runner.nextBase]
|
||||||
|
end
|
||||||
runner.forcedTo = nil
|
runner.forcedTo = nil
|
||||||
return false, false
|
return false, false
|
||||||
end
|
end
|
||||||
|
@ -214,16 +216,21 @@ end
|
||||||
|
|
||||||
--- Update non-batter runners.
|
--- Update non-batter runners.
|
||||||
--- Returns true only if at least one of the given runners moved during this update
|
--- Returns true only if at least one of the given runners moved during this update
|
||||||
---@param appliedSpeed number
|
---@param appliedSpeed number | fun(runner: Runner): number
|
||||||
---@return boolean someRunnerMoved, number runnersScored
|
---@return boolean someRunnerMoved, number runnersScored
|
||||||
function Baserunning:updateNonBatterRunners(appliedSpeed, forcedOnly, deltaSeconds)
|
function Baserunning:updateNonBatterRunners(appliedSpeed, forcedOnly, deltaSeconds)
|
||||||
local someRunnerMoved = false
|
local someRunnerMoved = false
|
||||||
local runnersScored = 0
|
local runnersScored = 0
|
||||||
|
|
||||||
|
local speedIsFunction = type(appliedSpeed) == "function"
|
||||||
-- TODO: Filter for the runner closest to the currently-held direction button
|
-- TODO: Filter for the runner closest to the currently-held direction button
|
||||||
for runnerIndex, runner in ipairs(self.runners) do
|
for runnerIndex, runner in ipairs(self.runners) do
|
||||||
if runner ~= self.batter and (not forcedOnly or runner.forcedTo) then
|
if runner ~= self.batter and (not forcedOnly or runner.forcedTo) then
|
||||||
local thisRunnerMoved, thisRunnerScored = self:updateRunner(runner, runnerIndex, appliedSpeed, deltaSeconds)
|
local speed = appliedSpeed
|
||||||
|
if speedIsFunction then
|
||||||
|
speed = appliedSpeed(runner)
|
||||||
|
end
|
||||||
|
local thisRunnerMoved, thisRunnerScored = self:updateRunner(runner, runnerIndex, speed, deltaSeconds)
|
||||||
someRunnerMoved = someRunnerMoved or thisRunnerMoved
|
someRunnerMoved = someRunnerMoved or thisRunnerMoved
|
||||||
if thisRunnerScored then
|
if thisRunnerScored then
|
||||||
runnersScored = runnersScored + 1
|
runnersScored = runnersScored + 1
|
||||||
|
|
|
@ -86,6 +86,7 @@ C.BaseHitbox = 10
|
||||||
|
|
||||||
C.BattingPower = 25
|
C.BattingPower = 25
|
||||||
C.BatterHandPos = utils.xy(25, 15)
|
C.BatterHandPos = utils.xy(25, 15)
|
||||||
|
C.GloveZ = 0 -- 10
|
||||||
|
|
||||||
C.SmallestBallRadius = 6
|
C.SmallestBallRadius = 6
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
--- @alias Fielder {
|
--- @class Fielder {
|
||||||
--- x: number,
|
--- @field catchEligible boolean
|
||||||
--- y: number,
|
--- @field x number
|
||||||
--- target: XyPair | nil,
|
--- @field y number
|
||||||
--- speed: number,
|
--- @field target XyPair | nil
|
||||||
--- }
|
--- @field speed number
|
||||||
|
|
||||||
-- TODO: Run down baserunners in a pickle.
|
-- TODO: Run down baserunners in a pickle.
|
||||||
|
|
||||||
-- selene: allow(unscoped_variables)
|
-- selene: allow(unscoped_variables)
|
||||||
---@class Fielding
|
---@class Fielding
|
||||||
---@field fielders table<string, Fielder>
|
---@field fielders table<string, Fielder>
|
||||||
---@field fielderTouchingBall Fielder | nil
|
---@field fielderHoldingBall Fielder | nil
|
||||||
Fielding = {}
|
Fielding = {}
|
||||||
|
|
||||||
local FielderDanceAnimator <const> = playdate.graphics.animator.new(1, 10, 0, utils.easingHill)
|
local FielderDanceAnimator <const> = playdate.graphics.animator.new(1, 10, 0, utils.easingHill)
|
||||||
|
@ -23,6 +23,7 @@ local function newFielder(name, speed)
|
||||||
return {
|
return {
|
||||||
name = name,
|
name = name,
|
||||||
speed = speed * C.FielderRunMult,
|
speed = speed * C.FielderRunMult,
|
||||||
|
catchEligible = true,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ function Fielding.new()
|
||||||
right = newFielder("Right", 50),
|
right = newFielder("Right", 50),
|
||||||
},
|
},
|
||||||
---@type Fielder | nil
|
---@type Fielder | nil
|
||||||
fielderTouchingBall = nil,
|
fielderHoldingBall = nil,
|
||||||
}, { __index = Fielding })
|
}, { __index = Fielding })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ end
|
||||||
---@param deltaSeconds number
|
---@param deltaSeconds number
|
||||||
---@param fielder Fielder
|
---@param fielder Fielder
|
||||||
---@param ballPos XyPair
|
---@param ballPos XyPair
|
||||||
---@return boolean isTouchingBall
|
---@return boolean inCatchingRange
|
||||||
local function updateFielderPosition(deltaSeconds, fielder, ballPos)
|
local function updateFielderPosition(deltaSeconds, fielder, ballPos)
|
||||||
if fielder.target ~= nil then
|
if fielder.target ~= nil then
|
||||||
if not utils.moveAtSpeed(fielder, fielder.speed * deltaSeconds, fielder.target) then
|
if not utils.moveAtSpeed(fielder, fielder.speed * deltaSeconds, fielder.target) then
|
||||||
|
@ -108,40 +109,62 @@ function Fielding:haveSomeoneChase(ballDestX, ballDestY)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param ball XyPair
|
---@param ball Ball
|
||||||
---@param deltaSeconds number
|
---@param deltaSeconds number
|
||||||
---@return Fielder | nil fielderTouchingBall nil if no fielder is currently touching the ball
|
---@return Fielder | nil fielderHoldingBall nil if no fielder is currently touching the ball
|
||||||
function Fielding:updateFielderPositions(ball, deltaSeconds)
|
function Fielding:updateFielderPositions(ball, deltaSeconds)
|
||||||
local fielderTouchingBall = nil
|
local fielderHoldingBall = nil
|
||||||
for _, fielder in pairs(self.fielders) do
|
for _, fielder in pairs(self.fielders) do
|
||||||
local isTouchingBall = updateFielderPosition(deltaSeconds, fielder, ball)
|
local inCatchingRange = updateFielderPosition(deltaSeconds, fielder, ball)
|
||||||
if isTouchingBall then
|
if inCatchingRange and fielder.catchEligible then
|
||||||
fielderTouchingBall = fielder
|
-- TODO: Base this catch on fielder skill?
|
||||||
|
fielderHoldingBall = fielder
|
||||||
|
ball.heldBy = fielder -- How much havoc will this wreak?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- TODO: The need is growing for a distinction between touching the ball and holding the ball.
|
-- TODO: The need is growing for a distinction between touching the ball and holding the ball.
|
||||||
-- Or, at least, fielders need to start *stopping* the ball when they make contact with it.
|
-- Or, at least, fielders need to start *stopping* the ball when they make contact with it.
|
||||||
-- Right now, a line-drive *through* first will be counted as an out.
|
-- Right now, a line-drive *through* first will be counted as an out.
|
||||||
self.fielderTouchingBall = fielderTouchingBall
|
self.fielderHoldingBall = fielderHoldingBall
|
||||||
return fielderTouchingBall
|
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:markAllIneligible()
|
||||||
|
for _, fielder in pairs(self.fielders) do
|
||||||
|
fielder.catchEligible = false
|
||||||
|
end
|
||||||
|
playdate.timer.new(750, function()
|
||||||
|
for _, fielder in pairs(self.fielders) do
|
||||||
|
fielder.catchEligible = true
|
||||||
|
end
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO? Start moving target fielders close sooner?
|
-- TODO? Start moving target fielders close sooner?
|
||||||
---@param field table
|
---@param field Fielding
|
||||||
---@param targetBase Base
|
---@param targetBase Base
|
||||||
---@param launchBall LaunchBall
|
---@param launchBall LaunchBall
|
||||||
---@param throwFlyMs number
|
---@param throwFlyMs number
|
||||||
---@return ActionResult
|
---@return ActionResult
|
||||||
local function userThrowToImpl(field, targetBase, launchBall, throwFlyMs)
|
local function userThrowToImpl(field, targetBase, launchBall, throwFlyMs)
|
||||||
if field.fielderTouchingBall == nil then
|
if field.fielderHoldingBall == nil then
|
||||||
return ActionResult.NeedsMoreTime
|
return ActionResult.NeedsMoreTime
|
||||||
end
|
end
|
||||||
local closestFielder = utils.getNearestOf(field.fielders, targetBase.x, targetBase.y, function(fielder)
|
local closestFielder = utils.getNearestOf(field.fielders, targetBase.x, targetBase.y, function(fielder)
|
||||||
return fielder ~= field.fielderTouchingBall -- presumably, this is who will be doing the throwing
|
return fielder ~= field.fielderHoldingBall -- presumably, this is who will be doing the throwing
|
||||||
end)
|
end)
|
||||||
|
|
||||||
closestFielder.target = targetBase
|
closestFielder.target = targetBase
|
||||||
launchBall(targetBase.x, targetBase.y, playdate.easingFunctions.linear, throwFlyMs)
|
launchBall(targetBase.x, targetBase.y, playdate.easingFunctions.linear, throwFlyMs)
|
||||||
|
Fielding.markIneligible(field.fielderHoldingBall)
|
||||||
return ActionResult.Succeeded
|
return ActionResult.Succeeded
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 34 KiB |
21
src/main.lua
21
src/main.lua
|
@ -148,6 +148,8 @@ end
|
||||||
---@param pitchFlyTimeMs number | nil
|
---@param pitchFlyTimeMs number | nil
|
||||||
---@param pitchTypeIndex number | nil
|
---@param pitchTypeIndex number | nil
|
||||||
local function pitch(pitchFlyTimeMs, pitchTypeIndex)
|
local function pitch(pitchFlyTimeMs, pitchTypeIndex)
|
||||||
|
Fielding.markIneligible(fielding.fielders.pitcher)
|
||||||
|
ball.heldBy = nil
|
||||||
catcherThrownBall = false
|
catcherThrownBall = false
|
||||||
offenseState = C.Offense.batting
|
offenseState = C.Offense.batting
|
||||||
|
|
||||||
|
@ -318,7 +320,7 @@ local function updateBatting(batDeg, batSpeed)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param appliedSpeed number
|
---@param appliedSpeed number | fun(runner: Runner): number
|
||||||
---@return boolean someRunnerMoved
|
---@return boolean someRunnerMoved
|
||||||
local function updateNonBatterRunners(appliedSpeed, forcedOnly)
|
local function updateNonBatterRunners(appliedSpeed, forcedOnly)
|
||||||
local runnerMoved, runnersScored = baserunning:updateNonBatterRunners(appliedSpeed, forcedOnly, deltaSeconds)
|
local runnerMoved, runnersScored = baserunning:updateNonBatterRunners(appliedSpeed, forcedOnly, deltaSeconds)
|
||||||
|
@ -351,16 +353,7 @@ local function updateGameState()
|
||||||
crankLimited = crankLimited * -1
|
crankLimited = crankLimited * -1
|
||||||
end
|
end
|
||||||
|
|
||||||
if ball.heldBy then
|
ball:updatePosition()
|
||||||
ball.x = ball.heldBy.x
|
|
||||||
ball.y = ball.heldBy.y
|
|
||||||
ball.size = C.SmallestBallRadius
|
|
||||||
else
|
|
||||||
ball.x = ball.xAnimator:currentValue()
|
|
||||||
ball.z = ball.floatAnimator:currentValue()
|
|
||||||
ball.y = ball.yAnimator:currentValue() + ball.z
|
|
||||||
ball.size = ball.sizeAnimator:currentValue()
|
|
||||||
end
|
|
||||||
|
|
||||||
local userOnOffense, userOnDefense = userIsOn(C.Sides.offense)
|
local userOnOffense, userOnDefense = userIsOn(C.Sides.offense)
|
||||||
|
|
||||||
|
@ -418,7 +411,10 @@ local function updateGameState()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif offenseState == C.Offense.running then
|
elseif offenseState == C.Offense.running then
|
||||||
local appliedSpeed = userOnOffense and crankLimited or npc:runningSpeed(ball)
|
local appliedSpeed = userOnOffense and crankLimited
|
||||||
|
or function(runner)
|
||||||
|
return npc:runningSpeed(runner, ball)
|
||||||
|
end
|
||||||
if updateNonBatterRunners(appliedSpeed) then
|
if updateNonBatterRunners(appliedSpeed) then
|
||||||
secondsSinceLastRunnerMove = 0
|
secondsSinceLastRunnerMove = 0
|
||||||
else
|
else
|
||||||
|
@ -426,6 +422,7 @@ local function updateGameState()
|
||||||
if secondsSinceLastRunnerMove > C.ResetFieldersAfterSeconds then
|
if secondsSinceLastRunnerMove > C.ResetFieldersAfterSeconds then
|
||||||
-- End of play. Throw the ball back to the pitcher
|
-- End of play. Throw the ball back to the pitcher
|
||||||
launchBall(C.PitchStartX, C.PitchStartY, playdate.easingFunctions.linear, nil, true)
|
launchBall(C.PitchStartX, C.PitchStartY, playdate.easingFunctions.linear, nil, true)
|
||||||
|
fielding:markAllIneligible() -- This is ugly, and ideally would not be necessary if Fielding handled the return throw directly.
|
||||||
fielding:resetFielderPositions()
|
fielding:resetFielderPositions()
|
||||||
offenseState = C.Offense.batting
|
offenseState = C.Offense.batting
|
||||||
-- TODO: Remove, or replace with nextBatter()
|
-- TODO: Remove, or replace with nextBatter()
|
||||||
|
|
24
src/npc.lua
24
src/npc.lua
|
@ -39,26 +39,25 @@ end
|
||||||
local baseRunningSpeed = 25
|
local baseRunningSpeed = 25
|
||||||
|
|
||||||
--- TODO: Individual runner control.
|
--- TODO: Individual runner control.
|
||||||
|
---@param runner Runner
|
||||||
---@param ball Point3d
|
---@param ball Point3d
|
||||||
---@return number
|
---@return number
|
||||||
function Npc:runningSpeed(ball)
|
function Npc:runningSpeed(runner, ball)
|
||||||
if #self.runners == 0 then
|
if #self.runners == 0 then
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
local runner1 = self.runners[1]
|
local distanceFromBall = utils.distanceBetweenZ(ball.x, ball.y, ball.z, runner.x, runner.y, 0)
|
||||||
|
|
||||||
local ballIsFar = utils.distanceBetweenZ(ball.x, ball.y, ball.z, runner1.x, runner1.y, 0) > 300
|
if distanceFromBall > 400 or runner.forcedTo then
|
||||||
|
|
||||||
if ballIsFar or runner1.forcedTo then
|
|
||||||
return baseRunningSpeed
|
return baseRunningSpeed
|
||||||
end
|
end
|
||||||
|
|
||||||
local touchedBase = utils.isTouchingBase(runner1.x, runner1.y)
|
local touchedBase = utils.isTouchingBase(runner.x, runner.y)
|
||||||
if not touchedBase and runner1.nextBase then
|
if not touchedBase and runner.nextBase then
|
||||||
local distToNext = utils.distanceBetween(runner1.x, runner1.y, runner1.nextBase.x, runner1.nextBase.y)
|
local distToNext = utils.distanceBetween(runner.x, runner.y, runner.nextBase.x, runner.nextBase.y)
|
||||||
local distToPrev = utils.distanceBetween(runner1.x, runner1.y, runner1.prevBase.x, runner1.prevBase.y)
|
local distToPrev = utils.distanceBetween(runner.x, runner.y, runner.prevBase.x, runner.prevBase.y)
|
||||||
if distToNext < distToPrev then
|
if distToNext < distToPrev or distanceFromBall > 350 then
|
||||||
return baseRunningSpeed
|
return baseRunningSpeed
|
||||||
else
|
else
|
||||||
return -1 * baseRunningSpeed
|
return -1 * baseRunningSpeed
|
||||||
|
@ -124,12 +123,15 @@ end
|
||||||
local function tryToMakeAPlay(fielders, fielder, runners, ball, launchBall)
|
local function tryToMakeAPlay(fielders, fielder, runners, ball, launchBall)
|
||||||
local targetX, targetY = getNextOutTarget(runners)
|
local targetX, targetY = getNextOutTarget(runners)
|
||||||
if targetX ~= nil and targetY ~= nil then
|
if targetX ~= nil and targetY ~= nil then
|
||||||
local nearestFielder = utils.getNearestOf(fielders, targetX, targetY)
|
local nearestFielder = utils.getNearestOf(fielders, targetX, targetY, function(grabCandidate)
|
||||||
|
return grabCandidate.catchEligible
|
||||||
|
end)
|
||||||
nearestFielder.target = utils.xy(targetX, targetY)
|
nearestFielder.target = utils.xy(targetX, targetY)
|
||||||
if nearestFielder == fielder then
|
if nearestFielder == fielder then
|
||||||
ball.heldBy = fielder
|
ball.heldBy = fielder
|
||||||
else
|
else
|
||||||
launchBall(targetX, targetY, playdate.easingFunctions.linear, nil, true)
|
launchBall(targetX, targetY, playdate.easingFunctions.linear, nil, true)
|
||||||
|
Fielding.markIneligible(nearestFielder)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue