Class-ify Announcer, Baserunning, and Fielding
Largely to enable dependency injection. I am pushing AWAY the paranoia that metatable lookups will slow things down. (You've got like 20 entities, bud, chill.) Field -> Fielding
This commit is contained in:
parent
aadaa6e0d6
commit
9c0d263a29
|
@ -11,14 +11,21 @@ local AnnouncerAnimatorOutY <const> =
|
||||||
playdate.graphics.animator.new(AnnouncementTransitionMs, 0, -70, playdate.easingFunctions.outQuint)
|
playdate.graphics.animator.new(AnnouncementTransitionMs, 0, -70, playdate.easingFunctions.outQuint)
|
||||||
|
|
||||||
-- selene: allow(unscoped_variables)
|
-- selene: allow(unscoped_variables)
|
||||||
announcer = {
|
---@class Announcer
|
||||||
|
---@field textQueue string[]
|
||||||
|
---@field animatorY pd_animator
|
||||||
|
Announcer = {}
|
||||||
|
|
||||||
|
function Announcer.new()
|
||||||
|
return setmetatable({
|
||||||
textQueue = {},
|
textQueue = {},
|
||||||
animatorY = AnnouncerAnimatorInY,
|
animatorY = AnnouncerAnimatorInY,
|
||||||
}
|
}, { __index = Announcer })
|
||||||
|
end
|
||||||
|
|
||||||
local DurationMs <const> = 3000
|
local DurationMs <const> = 3000
|
||||||
|
|
||||||
function announcer:popIn()
|
function Announcer:popIn()
|
||||||
self.animatorY = AnnouncerAnimatorInY
|
self.animatorY = AnnouncerAnimatorInY
|
||||||
self.animatorY:reset()
|
self.animatorY:reset()
|
||||||
|
|
||||||
|
@ -39,14 +46,14 @@ function announcer:popIn()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function announcer:say(text)
|
function Announcer:say(text)
|
||||||
self.textQueue[#self.textQueue + 1] = text
|
self.textQueue[#self.textQueue + 1] = text
|
||||||
if #self.textQueue == 1 then
|
if #self.textQueue == 1 then
|
||||||
self:popIn()
|
self:popIn()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function announcer:draw(x, y)
|
function Announcer:draw(x, y)
|
||||||
if #self.textQueue == 0 then
|
if #self.textQueue == 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,27 +7,37 @@
|
||||||
--- }
|
--- }
|
||||||
|
|
||||||
-- selene: allow(unscoped_variables)
|
-- selene: allow(unscoped_variables)
|
||||||
baserunning = {
|
---@class Baserunning
|
||||||
---@type Runner[]
|
---@field runners Runner[]
|
||||||
|
---@field outRunners Runner[]
|
||||||
|
---@field scoredRunners Runner[]
|
||||||
|
---@field batter Runner | nil
|
||||||
|
---@field outs number
|
||||||
|
---@field announcer Announcer
|
||||||
|
Baserunning = {}
|
||||||
|
|
||||||
|
---@param announcer any
|
||||||
|
---@return Baserunning
|
||||||
|
function Baserunning.new(announcer)
|
||||||
|
local o = setmetatable({
|
||||||
runners = {},
|
runners = {},
|
||||||
|
|
||||||
---@type Runner[]
|
|
||||||
outRunners = {},
|
outRunners = {},
|
||||||
|
|
||||||
---@type Runner[]
|
|
||||||
scoredRunners = {},
|
scoredRunners = {},
|
||||||
|
|
||||||
---@type Runner | nil
|
|
||||||
batter = nil,
|
batter = nil,
|
||||||
|
|
||||||
--- Since this object is what ultimately *mutates* the out count,
|
--- Since this object is what ultimately *mutates* the out count,
|
||||||
--- it seems sensible to store the value here.
|
--- it seems sensible to store the value here.
|
||||||
outs = 0
|
outs = 0,
|
||||||
}
|
announcer = announcer
|
||||||
|
}, { __index = Baserunning })
|
||||||
|
|
||||||
|
o.batter = o:newRunner()
|
||||||
|
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
---@param runner integer | Runner
|
---@param runner integer | Runner
|
||||||
---@param message string | nil
|
---@param message string | nil
|
||||||
function baserunning:outRunner(runner, message)
|
function Baserunning:outRunner(runner, message)
|
||||||
self.outs = self.outs + 1
|
self.outs = self.outs + 1
|
||||||
if type(runner) ~= "number" then
|
if type(runner) ~= "number" then
|
||||||
for i, maybe in ipairs(self.runners) do
|
for i, maybe in ipairs(self.runners) do
|
||||||
|
@ -44,7 +54,7 @@ function baserunning:outRunner(runner, message)
|
||||||
|
|
||||||
self:updateForcedRunners()
|
self:updateForcedRunners()
|
||||||
|
|
||||||
announcer:say(message or "YOU'RE OUT!")
|
self.announcer:say(message or "YOU'RE OUT!")
|
||||||
if self.outs < 3 then
|
if self.outs < 3 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -55,7 +65,7 @@ function baserunning:outRunner(runner, message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function baserunning:outEligibleRunners(fielder)
|
function Baserunning:outEligibleRunners(fielder)
|
||||||
local touchedBase = utils.isTouchingBase(fielder.x, fielder.y)
|
local touchedBase = utils.isTouchingBase(fielder.x, fielder.y)
|
||||||
local didOutRunner = false
|
local didOutRunner = false
|
||||||
for i, runner in pairs(self.runners) do
|
for i, runner in pairs(self.runners) do
|
||||||
|
@ -76,7 +86,7 @@ function baserunning:outEligibleRunners(fielder)
|
||||||
return didOutRunner
|
return didOutRunner
|
||||||
end
|
end
|
||||||
|
|
||||||
function baserunning:updateForcedRunners()
|
function Baserunning:updateForcedRunners()
|
||||||
local stillForced = true
|
local stillForced = true
|
||||||
for _, base in ipairs(C.Bases) do
|
for _, base in ipairs(C.Bases) do
|
||||||
local runnerTargetingBase = utils.getRunnerWithNextBase(self.runners, base)
|
local runnerTargetingBase = utils.getRunnerWithNextBase(self.runners, base)
|
||||||
|
@ -93,7 +103,7 @@ function baserunning:updateForcedRunners()
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param deltaSeconds number
|
---@param deltaSeconds number
|
||||||
function baserunning:walkAwayOutRunners(deltaSeconds)
|
function Baserunning:walkAwayOutRunners(deltaSeconds)
|
||||||
for i, runner in ipairs(self.outRunners) do
|
for i, runner in ipairs(self.outRunners) do
|
||||||
if runner.x < C.Screen.W + 50 and runner.y < C.Screen.H + 50 then
|
if runner.x < C.Screen.W + 50 and runner.y < C.Screen.H + 50 then
|
||||||
runner.x = runner.x + (deltaSeconds * 25)
|
runner.x = runner.x + (deltaSeconds * 25)
|
||||||
|
@ -105,7 +115,7 @@ function baserunning:walkAwayOutRunners(deltaSeconds)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return Runner
|
---@return Runner
|
||||||
function baserunning:newRunner()
|
function Baserunning:newRunner()
|
||||||
local new = {
|
local new = {
|
||||||
x = C.RightHandedBattersBox.x - 60,
|
x = C.RightHandedBattersBox.x - 60,
|
||||||
y = C.RightHandedBattersBox.y + 60,
|
y = C.RightHandedBattersBox.y + 60,
|
||||||
|
@ -117,11 +127,9 @@ function baserunning:newRunner()
|
||||||
return new
|
return new
|
||||||
end
|
end
|
||||||
|
|
||||||
baserunning.batter = baserunning:newRunner()
|
|
||||||
|
|
||||||
---@param self table
|
---@param self table
|
||||||
---@param runnerIndex integer
|
---@param runnerIndex integer
|
||||||
function baserunning:runnerScored(runnerIndex)
|
function Baserunning:runnerScored(runnerIndex)
|
||||||
-- TODO: outRunners/scoredRunners split
|
-- TODO: outRunners/scoredRunners split
|
||||||
self.outRunners[#self.outRunners + 1] = self.runners[runnerIndex]
|
self.outRunners[#self.outRunners + 1] = self.runners[runnerIndex]
|
||||||
table.remove(self.runners, runnerIndex)
|
table.remove(self.runners, runnerIndex)
|
||||||
|
@ -133,7 +141,7 @@ end
|
||||||
---@param appliedSpeed number
|
---@param appliedSpeed number
|
||||||
---@param deltaSeconds number
|
---@param deltaSeconds number
|
||||||
---@return boolean runnerMoved, boolean runnerScored
|
---@return boolean runnerMoved, boolean runnerScored
|
||||||
function baserunning:updateRunner(runner, runnerIndex, appliedSpeed, deltaSeconds)
|
function Baserunning:updateRunner(runner, runnerIndex, appliedSpeed, deltaSeconds)
|
||||||
local autoRunSpeed = 20 * deltaSeconds
|
local autoRunSpeed = 20 * deltaSeconds
|
||||||
|
|
||||||
if not runner or not runner.nextBase then
|
if not runner or not runner.nextBase then
|
||||||
|
@ -188,7 +196,7 @@ end
|
||||||
--- 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
|
||||||
---@return boolean someRunnerMoved, number runnersScored
|
---@return boolean someRunnerMoved, number runnersScored
|
||||||
function baserunning:updateRunning(appliedSpeed, forcedOnly, deltaSeconds)
|
function Baserunning:updateRunning(appliedSpeed, forcedOnly, deltaSeconds)
|
||||||
local someRunnerMoved = false
|
local someRunnerMoved = false
|
||||||
local runnersScored = 0
|
local runnersScored = 0
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
|
-- selene: allow(unscoped_variables)
|
||||||
|
---@class Fielding
|
||||||
|
---@field fielders table<string, Fielder>
|
||||||
|
---@field fielderTouchingBall Fielder | nil
|
||||||
|
Fielding = {}
|
||||||
|
|
||||||
---@param name string
|
---@param name string
|
||||||
---@param speed number
|
---@param speed number
|
||||||
---@return Fielder
|
---@return Fielder
|
||||||
function newFielder(name, speed)
|
local function newFielder(name, speed)
|
||||||
return {
|
return {
|
||||||
name = name,
|
name = name,
|
||||||
speed = speed,
|
speed = speed,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- selene: allow(unscoped_variables)
|
function Fielding.new()
|
||||||
Field = {
|
return setmetatable({
|
||||||
fielders = {
|
fielders = {
|
||||||
first = newFielder("First", 40),
|
first = newFielder("First", 40),
|
||||||
second = newFielder("Second", 40),
|
second = newFielder("Second", 40),
|
||||||
|
@ -23,11 +29,12 @@ Field = {
|
||||||
},
|
},
|
||||||
---@type Fielder | nil
|
---@type Fielder | nil
|
||||||
fielderTouchingBall = nil,
|
fielderTouchingBall = nil,
|
||||||
}
|
}, { __index = Fielding })
|
||||||
|
end
|
||||||
|
|
||||||
--- Actually only benches the infield, because outfielders are far away!
|
--- Actually only benches the infield, because outfielders are far away!
|
||||||
---@param position XYPair
|
---@param position XYPair
|
||||||
function Field:benchTo(position)
|
function Fielding:benchTo(position)
|
||||||
self.fielders.first.target = position
|
self.fielders.first.target = position
|
||||||
self.fielders.second.target = position
|
self.fielders.second.target = position
|
||||||
self.fielders.shortstop.target = position
|
self.fielders.shortstop.target = position
|
||||||
|
@ -38,7 +45,7 @@ end
|
||||||
|
|
||||||
--- Resets the target positions of all fielders to their defaults (at their field positions).
|
--- Resets the target positions of all fielders to their defaults (at their field positions).
|
||||||
---@param fromOffTheField XYPair | nil If provided, also sets all runners' current position to one centralized location.
|
---@param fromOffTheField XYPair | nil If provided, also sets all runners' current position to one centralized location.
|
||||||
function Field:resetFielderPositions(fromOffTheField)
|
function Fielding:resetFielderPositions(fromOffTheField)
|
||||||
if fromOffTheField then
|
if fromOffTheField then
|
||||||
for _, fielder in pairs(self.fielders) do
|
for _, fielder in pairs(self.fielders) do
|
||||||
fielder.x = fromOffTheField.x
|
fielder.x = fromOffTheField.x
|
||||||
|
@ -76,7 +83,7 @@ end
|
||||||
---@param self table
|
---@param self table
|
||||||
---@param ballDestX number
|
---@param ballDestX number
|
||||||
---@param ballDestY number
|
---@param ballDestY number
|
||||||
function Field:haveSomeoneChase(ballDestX, ballDestY)
|
function Fielding:haveSomeoneChase(ballDestX, ballDestY)
|
||||||
local chasingFielder = utils.getNearestOf(self.fielders, ballDestX, ballDestY)
|
local chasingFielder = utils.getNearestOf(self.fielders, ballDestX, ballDestY)
|
||||||
chasingFielder.target = { x = ballDestX, y = ballDestY }
|
chasingFielder.target = { x = ballDestX, y = ballDestY }
|
||||||
|
|
||||||
|
@ -92,7 +99,7 @@ end
|
||||||
---@param ball XYPair
|
---@param ball XYPair
|
||||||
---@param deltaSeconds number
|
---@param deltaSeconds number
|
||||||
---@return Fielder | nil fielderTouchingBall nil if no fielder is currently touching the ball
|
---@return Fielder | nil fielderTouchingBall nil if no fielder is currently touching the ball
|
||||||
function Field:updateFielderPositions(ball, deltaSeconds)
|
function Fielding:updateFielderPositions(ball, deltaSeconds)
|
||||||
local fielderTouchingBall = nil
|
local fielderTouchingBall = nil
|
||||||
for _, fielder in pairs(self.fielders) do
|
for _, fielder in pairs(self.fielders) do
|
||||||
local isTouchingBall = updateFielderPosition(deltaSeconds, fielder, ball)
|
local isTouchingBall = updateFielderPosition(deltaSeconds, fielder, ball)
|
||||||
|
@ -120,6 +127,7 @@ local function playerThrowToImpl(field, targetBase, throwBall, throwFlyMs)
|
||||||
|
|
||||||
closestFielder.target = targetBase
|
closestFielder.target = targetBase
|
||||||
throwBall(targetBase.x, targetBase.y, playdate.easingFunctions.linear, throwFlyMs)
|
throwBall(targetBase.x, targetBase.y, playdate.easingFunctions.linear, throwFlyMs)
|
||||||
|
return ActionResult.Succeeded
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Buffer in a fielder throw action.
|
--- Buffer in a fielder throw action.
|
||||||
|
@ -127,7 +135,7 @@ end
|
||||||
---@param targetBase Base
|
---@param targetBase Base
|
||||||
---@param throwBall ThrowBall
|
---@param throwBall ThrowBall
|
||||||
---@param throwFlyMs number
|
---@param throwFlyMs number
|
||||||
function Field:playerThrowTo(targetBase, throwBall, throwFlyMs)
|
function Fielding:playerThrowTo(targetBase, throwBall, throwFlyMs)
|
||||||
local maxTryTimeMs = 5000
|
local maxTryTimeMs = 5000
|
||||||
actionQueue:upsert('playerThrowTo', maxTryTimeMs, function()
|
actionQueue:upsert('playerThrowTo', maxTryTimeMs, function()
|
||||||
return playerThrowToImpl(self, targetBase, throwBall, throwFlyMs)
|
return playerThrowToImpl(self, targetBase, throwBall, throwFlyMs)
|
||||||
|
|
28
src/main.lua
28
src/main.lua
|
@ -17,7 +17,7 @@ import 'CoreLibs/ui.lua'
|
||||||
|
|
||||||
--- @alias EasingFunc fun(number, number, number, number): number
|
--- @alias EasingFunc fun(number, number, number, number): number
|
||||||
|
|
||||||
---@alias ThrowBall fun(destX: number, destY: number, easingFunc: EasingFunc, flyTimeMs: number | nil, floaty: boolean | nil, customBallScaler: pd_animator | nil)
|
--- @alias ThrowBall fun(destX: number, destY: number, easingFunc: EasingFunc, flyTimeMs: number | nil, floaty: boolean | nil, customBallScaler: pd_animator | nil)
|
||||||
|
|
||||||
-- stylua: ignore start
|
-- stylua: ignore start
|
||||||
import 'utils.lua'
|
import 'utils.lua'
|
||||||
|
@ -38,6 +38,10 @@ import 'draw/fielder.lua'
|
||||||
-- selene: allow(shadowing)
|
-- selene: allow(shadowing)
|
||||||
local gfx <const>, C <const> = playdate.graphics, C
|
local gfx <const>, C <const> = playdate.graphics, C
|
||||||
|
|
||||||
|
local announcer = Announcer:new()
|
||||||
|
local baserunning = Baserunning.new(announcer)
|
||||||
|
local fielding = Fielding.new()
|
||||||
|
|
||||||
local PlayerImageBlipper <const> = blipper.new(100, Player, PlayerLowHat)
|
local PlayerImageBlipper <const> = blipper.new(100, Player, PlayerLowHat)
|
||||||
|
|
||||||
local FielderDanceAnimator <const> = gfx.animator.new(1, 10, 0, utils.easingHill)
|
local FielderDanceAnimator <const> = gfx.animator.new(1, 10, 0, utils.easingHill)
|
||||||
|
@ -208,7 +212,7 @@ local function outRunner(runner, message)
|
||||||
if not gameOver then
|
if not gameOver then
|
||||||
FielderDanceAnimator:reset(C.DanceBounceMs)
|
FielderDanceAnimator:reset(C.DanceBounceMs)
|
||||||
secondsSinceLastRunnerMove = -7
|
secondsSinceLastRunnerMove = -7
|
||||||
Field:benchTo(currentlyFieldingTeam.benchPosition)
|
fielding:benchTo(currentlyFieldingTeam.benchPosition)
|
||||||
announcer:say("SWITCHING SIDES...")
|
announcer:say("SWITCHING SIDES...")
|
||||||
end
|
end
|
||||||
-- Delay to keep end-of-inning on the scoreboard for a few seconds
|
-- Delay to keep end-of-inning on the scoreboard for a few seconds
|
||||||
|
@ -218,7 +222,7 @@ local function outRunner(runner, message)
|
||||||
if gameOver then
|
if gameOver then
|
||||||
announcer:say("AND THAT'S THE BALL GAME!")
|
announcer:say("AND THAT'S THE BALL GAME!")
|
||||||
else
|
else
|
||||||
Field:resetFielderPositions()
|
fielding:resetFielderPositions()
|
||||||
if battingTeam == teams.home then
|
if battingTeam == teams.home then
|
||||||
inning = inning + 1
|
inning = inning + 1
|
||||||
end
|
end
|
||||||
|
@ -259,7 +263,7 @@ local function buttonControlledThrow(throwFlyMs, forbidThrowHome)
|
||||||
-- Power for this throw has already been determined
|
-- Power for this throw has already been determined
|
||||||
throwMeter = 0
|
throwMeter = 0
|
||||||
|
|
||||||
Field:playerThrowTo(targetBase, throwBall, throwFlyMs)
|
fielding:playerThrowTo(targetBase, throwBall, throwFlyMs)
|
||||||
secondsSinceLastRunnerMove = 0
|
secondsSinceLastRunnerMove = 0
|
||||||
offenseState = C.Offense.running
|
offenseState = C.Offense.running
|
||||||
|
|
||||||
|
@ -330,7 +334,7 @@ local function updateBatting(batDeg, batSpeed)
|
||||||
baserunning.batter.forcedTo = C.Bases[C.First]
|
baserunning.batter.forcedTo = C.Bases[C.First]
|
||||||
baserunning.batter = nil -- Demote batter to a mere runner
|
baserunning.batter = nil -- Demote batter to a mere runner
|
||||||
|
|
||||||
Field:haveSomeoneChase(ballDestX, ballDestY)
|
fielding:haveSomeoneChase(ballDestX, ballDestY)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -392,7 +396,7 @@ local function updateGameState()
|
||||||
pitchTracker.recordedPitchX = ball.x
|
pitchTracker.recordedPitchX = ball.x
|
||||||
end
|
end
|
||||||
|
|
||||||
local pitcher = Field.fielders.pitcher
|
local pitcher = fielding.fielders.pitcher
|
||||||
if utils.distanceBetween(pitcher.x, pitcher.y, C.PitchStartX, C.PitchStartY) < C.BaseHitbox then
|
if utils.distanceBetween(pitcher.x, pitcher.y, C.PitchStartX, C.PitchStartY) < C.BaseHitbox then
|
||||||
secondsSincePitchAllowed = secondsSincePitchAllowed + deltaSeconds
|
secondsSincePitchAllowed = secondsSincePitchAllowed + deltaSeconds
|
||||||
end
|
end
|
||||||
|
@ -441,7 +445,7 @@ local function updateGameState()
|
||||||
secondsSinceLastRunnerMove = secondsSinceLastRunnerMove + deltaSeconds
|
secondsSinceLastRunnerMove = secondsSinceLastRunnerMove + deltaSeconds
|
||||||
if secondsSinceLastRunnerMove > C.ResetFieldersAfterSeconds then
|
if secondsSinceLastRunnerMove > C.ResetFieldersAfterSeconds then
|
||||||
throwBall(C.PitchStartX, C.PitchStartY, playdate.easingFunctions.linear, nil, true)
|
throwBall(C.PitchStartX, C.PitchStartY, playdate.easingFunctions.linear, nil, true)
|
||||||
Field:resetFielderPositions()
|
fielding:resetFielderPositions()
|
||||||
offenseState = C.Offense.batting
|
offenseState = C.Offense.batting
|
||||||
if not baserunning.batter then
|
if not baserunning.batter then
|
||||||
baserunning.batter = baserunning:newRunner()
|
baserunning.batter = baserunning:newRunner()
|
||||||
|
@ -454,7 +458,7 @@ local function updateGameState()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local fielderHoldingBall = Field:updateFielderPositions(ball, deltaSeconds)
|
local fielderHoldingBall = fielding:updateFielderPositions(ball, deltaSeconds)
|
||||||
|
|
||||||
if playerOnDefense then
|
if playerOnDefense then
|
||||||
local throwFly = readThrow()
|
local throwFly = readThrow()
|
||||||
|
@ -465,7 +469,7 @@ local function updateGameState()
|
||||||
if fielderHoldingBall then
|
if fielderHoldingBall then
|
||||||
local outedSomeRunner = baserunning:outEligibleRunners(fielderHoldingBall)
|
local outedSomeRunner = baserunning:outEligibleRunners(fielderHoldingBall)
|
||||||
if playerOnOffense then
|
if playerOnOffense then
|
||||||
npc.fielderAction(offenseState, fielderHoldingBall, outedSomeRunner, ball, throwBall)
|
npc.fielderAction(fielding, baserunning, offenseState, fielderHoldingBall, outedSomeRunner, ball, throwBall)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -488,7 +492,7 @@ function playdate.update()
|
||||||
|
|
||||||
local fielderDanceHeight = FielderDanceAnimator:currentValue()
|
local fielderDanceHeight = FielderDanceAnimator:currentValue()
|
||||||
local ballIsHeld = false
|
local ballIsHeld = false
|
||||||
for _, fielder in pairs(Field.fielders) do
|
for _, fielder in pairs(fielding.fielders) do
|
||||||
ballIsHeld = drawFielder(ball, fielder.x, fielder.y + fielderDanceHeight) or ballIsHeld
|
ballIsHeld = drawFielder(ball, fielder.x, fielder.y + fielderDanceHeight) or ballIsHeld
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -531,7 +535,7 @@ function playdate.update()
|
||||||
|
|
||||||
gfx.setDrawOffset(0, 0)
|
gfx.setDrawOffset(0, 0)
|
||||||
if math.abs(offsetX) > 10 or math.abs(offsetY) > 10 then
|
if math.abs(offsetX) > 10 or math.abs(offsetY) > 10 then
|
||||||
drawMinimap(baserunning.runners, Field.fielders)
|
drawMinimap(baserunning.runners, fielding.fielders)
|
||||||
end
|
end
|
||||||
drawScoreboard(0, C.Screen.H * 0.77, teams, outs, battingTeam, inning)
|
drawScoreboard(0, C.Screen.H * 0.77, teams, outs, battingTeam, inning)
|
||||||
drawBallsAndStrikes(290, C.Screen.H - 20, pitchTracker.balls, pitchTracker.strikes)
|
drawBallsAndStrikes(290, C.Screen.H - 20, pitchTracker.balls, pitchTracker.strikes)
|
||||||
|
@ -542,7 +546,7 @@ local function init()
|
||||||
playdate.display.setRefreshRate(50)
|
playdate.display.setRefreshRate(50)
|
||||||
gfx.setBackgroundColor(gfx.kColorWhite)
|
gfx.setBackgroundColor(gfx.kColorWhite)
|
||||||
playdate.setMenuImage(gfx.image.new("images/game/menu-image.png"))
|
playdate.setMenuImage(gfx.image.new("images/game/menu-image.png"))
|
||||||
Field:resetFielderPositions(teams.home.benchPosition)
|
fielding:resetFielderPositions(teams.home.benchPosition)
|
||||||
playdate.getSystemMenu():addMenuItem("Restart game", function() end) -- TODO?
|
playdate.getSystemMenu():addMenuItem("Restart game", function() end) -- TODO?
|
||||||
|
|
||||||
playdate.timer.new(2000, function()
|
playdate.timer.new(2000, function()
|
||||||
|
|
13
src/npc.lua
13
src/npc.lua
|
@ -85,13 +85,14 @@ function npc.getNextOutTarget(runners)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param fielding Fielding
|
||||||
---@param fielder Fielder
|
---@param fielder Fielder
|
||||||
---@param runners Runner[]
|
---@param runners Runner[]
|
||||||
---@param throwBall ThrowBall
|
---@param throwBall ThrowBall
|
||||||
function npc.tryToMakeAPlay(fielder, runners, ball, throwBall)
|
function npc.tryToMakeAPlay(fielding, fielder, runners, ball, throwBall)
|
||||||
local targetX, targetY = npc.getNextOutTarget(runners)
|
local targetX, targetY = npc.getNextOutTarget(runners)
|
||||||
if targetX ~= nil and targetY ~= nil then
|
if targetX ~= nil and targetY ~= nil then
|
||||||
local nearestFielder = utils.getNearestOf(Field.fielders, targetX, targetY)
|
local nearestFielder = utils.getNearestOf(fielding.fielders, targetX, targetY)
|
||||||
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
|
||||||
|
@ -101,22 +102,24 @@ function npc.tryToMakeAPlay(fielder, runners, ball, throwBall)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param fielding Fielding
|
||||||
|
---@param baserunning Baserunning
|
||||||
---@param offenseState OffenseState
|
---@param offenseState OffenseState
|
||||||
---@param fielder Fielder
|
---@param fielder Fielder
|
||||||
---@param outedSomeRunner boolean
|
---@param outedSomeRunner boolean
|
||||||
---@param ball { x: number, y: number, heldBy: Fielder | nil }
|
---@param ball { x: number, y: number, heldBy: Fielder | nil }
|
||||||
---@param throwBall ThrowBall
|
---@param throwBall ThrowBall
|
||||||
function npc.fielderAction(offenseState, fielder, outedSomeRunner, ball, throwBall)
|
function npc.fielderAction(fielding, baserunning, offenseState, fielder, outedSomeRunner, ball, throwBall)
|
||||||
if offenseState ~= C.Offense.running then
|
if offenseState ~= C.Offense.running then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if outedSomeRunner then
|
if outedSomeRunner then
|
||||||
-- Delay a little before the next play
|
-- Delay a little before the next play
|
||||||
playdate.timer.new(750, function()
|
playdate.timer.new(750, function()
|
||||||
npc.tryToMakeAPlay(fielder, baserunning.runners, ball, throwBall)
|
npc.tryToMakeAPlay(fielding, fielder, baserunning.runners, ball, throwBall)
|
||||||
end)
|
end)
|
||||||
else
|
else
|
||||||
npc.tryToMakeAPlay(fielder, baserunning.runners, ball, throwBall)
|
npc.tryToMakeAPlay(fielding, fielder, baserunning.runners, ball, throwBall)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ function utils.getRunnerWithNextBase(runners, base)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns true only if the point is below the given line, within the x bounds of said line, and above the bottomBound
|
--- Returns true only if the point is below the given line, within the x bounds of said line, and above the bottomBound
|
||||||
--- @return boolean
|
---@return boolean
|
||||||
function utils.pointDirectlyUnderLine(pointX, pointY, lineX1, lineY1, lineX2, lineY2, bottomBound)
|
function utils.pointDirectlyUnderLine(pointX, pointY, lineX1, lineY1, lineX2, lineY2, bottomBound)
|
||||||
-- This check currently assumes right-handedness.
|
-- This check currently assumes right-handedness.
|
||||||
-- I.e. it assumes the ball is to the right of batBaseX
|
-- I.e. it assumes the ball is to the right of batBaseX
|
||||||
|
|
Loading…
Reference in New Issue