Add basic home-run handling
Still needs to pan the camera back from the home run while the runners circle the bases. Also add a wrapping-pattern.png, though I'm not sure if it's actually used?
This commit is contained in:
parent
1bdcc62347
commit
2d812f2046
|
@ -16,7 +16,8 @@
|
||||||
---@field onThirdOut fun()
|
---@field onThirdOut fun()
|
||||||
Baserunning = {}
|
Baserunning = {}
|
||||||
|
|
||||||
-- TODO: Implement slides. Would require making fielders' gloves "real objects" whose state is tracked.
|
-- TODO: Implement slides? Would require making fielders' gloves "real objects" whose state is tracked.
|
||||||
|
-- TODO: Don't allow runners to occupy the same base!
|
||||||
|
|
||||||
---@param announcer Announcer
|
---@param announcer Announcer
|
||||||
---@return Baserunning
|
---@return Baserunning
|
||||||
|
|
|
@ -98,6 +98,7 @@ C.Offense = {
|
||||||
batting = "batting",
|
batting = "batting",
|
||||||
running = "running",
|
running = "running",
|
||||||
walking = "walking",
|
walking = "walking",
|
||||||
|
homeRun = "homeRun",
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias Side "offense" | "defense"
|
---@alias Side "offense" | "defense"
|
||||||
|
@ -124,17 +125,23 @@ C.WalkedRunnerSpeed = 10
|
||||||
C.ResetFieldersAfterSeconds = 2.5
|
C.ResetFieldersAfterSeconds = 2.5
|
||||||
|
|
||||||
C.OutfieldWall = {
|
C.OutfieldWall = {
|
||||||
{ x = 0, y = 137 },
|
{ x = -400, y = -103 },
|
||||||
{ x = 233, y = 32 },
|
{ x = -167, y = -208 },
|
||||||
{ x = 450, y = 29 },
|
{ x = 50, y = -211 },
|
||||||
{ x = 550, y = 59 },
|
{ x = 150, y = -181 },
|
||||||
{ x = 739, y = 64 },
|
{ x = 339, y = -176 },
|
||||||
{ x = 850, y = 19 },
|
{ x = 450, y = -221 },
|
||||||
{ x = 1100, y = 31 },
|
{ x = 700, y = -209 },
|
||||||
{ x = 1185, y = 181 },
|
{ x = 785, y = -59 },
|
||||||
{ x = 1201, y = 224 },
|
{ x = 801, y = -16 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
C.BottomOfOutfieldWall = {}
|
||||||
|
|
||||||
|
for i, v in ipairs(C.OutfieldWall) do
|
||||||
|
C.BottomOfOutfieldWall[i] = utils.xy(v.x, v.y + 40)
|
||||||
|
end
|
||||||
|
|
||||||
if not playdate then
|
if not playdate then
|
||||||
return C
|
return C
|
||||||
end
|
end
|
||||||
|
|
|
@ -80,7 +80,10 @@ end
|
||||||
---@return boolean inCatchingRange
|
---@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
|
||||||
|
utils.pointIsSquarelyAboveLine(fielder, C.BottomOfOutfieldWall)
|
||||||
|
or not utils.moveAtSpeed(fielder, fielder.speed * deltaSeconds, fielder.target)
|
||||||
|
then
|
||||||
fielder.target = nil
|
fielder.target = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
33
src/main.lua
33
src/main.lua
|
@ -416,8 +416,7 @@ function Game:updateBatting(batDeg, batSpeed)
|
||||||
local ballDestX = self.state.ball.x + (ballVelX * C.BattingPower)
|
local ballDestX = self.state.ball.x + (ballVelX * C.BattingPower)
|
||||||
local ballDestY = self.state.ball.y + (ballVelY * C.BattingPower)
|
local ballDestY = self.state.ball.y + (ballVelY * C.BattingPower)
|
||||||
pitchTracker:reset()
|
pitchTracker:reset()
|
||||||
local hitBallScaler = gfx.animator.new(2000, 9 + (mult * mult * 0.5), C.SmallestBallRadius, utils.easingHill)
|
local flyTimeMs = 2000
|
||||||
self.state.ball:launch(ballDestX, ballDestY, playdate.easingFunctions.outQuint, 2000, nil, hitBallScaler)
|
|
||||||
-- TODO? A dramatic eye-level view on a home-run could be sick.
|
-- TODO? A dramatic eye-level view on a home-run could be sick.
|
||||||
local battingTeamStats = self:battingTeamCurrentInning()
|
local battingTeamStats = self:battingTeamCurrentInning()
|
||||||
battingTeamStats.hits[#battingTeamStats.hits + 1] = utils.xy(ballDestX, ballDestY)
|
battingTeamStats.hits[#battingTeamStats.hits + 1] = utils.xy(ballDestX, ballDestY)
|
||||||
|
@ -428,8 +427,21 @@ function Game:updateBatting(batDeg, batSpeed)
|
||||||
-- TODO: Have a fielder chase for the fly-out
|
-- TODO: Have a fielder chase for the fly-out
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self.baserunning:convertBatterToRunner()
|
|
||||||
|
|
||||||
|
if utils.pointIsSquarelyAboveLine(utils.xy(ballDestX, ballDestY), C.OutfieldWall) then
|
||||||
|
playdate.timer.new(flyTimeMs, function()
|
||||||
|
-- Verify that the home run wasn't intercepted
|
||||||
|
if utils.within(1, self.state.ball.x, ballDestX) and utils.within(1, self.state.ball.y, ballDestY) then
|
||||||
|
self.announcer:say("HOME RUN!")
|
||||||
|
self.state.offenseState = C.Offense.homeRun
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local hitBallScaler = gfx.animator.new(2000, 9 + (mult * mult * 0.5), C.SmallestBallRadius, utils.easingHill)
|
||||||
|
self.state.ball:launch(ballDestX, ballDestY, playdate.easingFunctions.outQuint, flyTimeMs, nil, hitBallScaler)
|
||||||
|
|
||||||
|
self.baserunning:convertBatterToRunner()
|
||||||
self.fielding:haveSomeoneChase(ballDestX, ballDestY)
|
self.fielding:haveSomeoneChase(ballDestX, ballDestY)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -490,14 +502,7 @@ function Game:updateGameState()
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.state.secondsSincePitchAllowed > C.ReturnToPitcherAfterSeconds and not self.state.pitchIsOver then
|
if self.state.secondsSincePitchAllowed > C.ReturnToPitcherAfterSeconds and not self.state.pitchIsOver then
|
||||||
local outcome = pitchTracker:updatePitchCounts(self.state.didSwing)
|
local outcome = pitchTracker:updatePitchCounts(self.state.didSwing, self:fieldingTeamCurrentInning())
|
||||||
local currentPitchingStats = self:fieldingTeamCurrentInning().pitching
|
|
||||||
if outcome == PitchOutcomes.Strike or outcome == PitchOutcomes.StrikeOut then
|
|
||||||
currentPitchingStats.strikes = currentPitchingStats.strikes + 1
|
|
||||||
end
|
|
||||||
if outcome == PitchOutcomes.Ball or outcome == PitchOutcomes.Walk then
|
|
||||||
currentPitchingStats.balls = currentPitchingStats.balls + 1
|
|
||||||
end
|
|
||||||
if outcome == PitchOutcomes.StrikeOut then
|
if outcome == PitchOutcomes.StrikeOut then
|
||||||
self:strikeOut()
|
self:strikeOut()
|
||||||
elseif outcome == PitchOutcomes.Walk then
|
elseif outcome == PitchOutcomes.Walk then
|
||||||
|
@ -560,6 +565,12 @@ function Game:updateGameState()
|
||||||
if not self:updateNonBatterRunners(C.WalkedRunnerSpeed, true) then
|
if not self:updateNonBatterRunners(C.WalkedRunnerSpeed, true) then
|
||||||
self.state.offenseState = C.Offense.batting
|
self.state.offenseState = C.Offense.batting
|
||||||
end
|
end
|
||||||
|
elseif self.state.offenseState == C.Offense.homeRun then
|
||||||
|
self:updateNonBatterRunners(C.WalkedRunnerSpeed * 3, false)
|
||||||
|
if #self.baserunning.runners == 0 then
|
||||||
|
self.state.offenseState = C.Offense.batting
|
||||||
|
self.baserunning:pushNewBatter()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local fielderHoldingBall = self.fielding:updateFielderPositions(self.state.ball, self.state.deltaSeconds)
|
local fielderHoldingBall = self.fielding:updateFielderPositions(self.state.ball, self.state.deltaSeconds)
|
||||||
|
|
|
@ -83,6 +83,10 @@ function utils.moveAtSpeed(mover, speed, target)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function utils.within(within, n1, n2)
|
||||||
|
return math.abs(n1 - n2) < within
|
||||||
|
end
|
||||||
|
|
||||||
---@generic T
|
---@generic T
|
||||||
---@param array T[]
|
---@param array T[]
|
||||||
---@param condition fun(T): boolean
|
---@param condition fun(T): boolean
|
||||||
|
@ -266,19 +270,24 @@ pitchTracker = {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
---@param didSwing boolean
|
---@param didSwing boolean
|
||||||
updatePitchCounts = function(self, didSwing)
|
---@param fieldingTeamInningData TeamInningData
|
||||||
|
updatePitchCounts = function(self, didSwing, fieldingTeamInningData)
|
||||||
if not self.recordedPitchX then
|
if not self.recordedPitchX then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local currentPitchingStats = fieldingTeamInningData.pitching
|
||||||
|
|
||||||
if didSwing or self.recordedPitchX > C.StrikeZoneStartX and self.recordedPitchX < C.StrikeZoneEndX then
|
if didSwing or self.recordedPitchX > C.StrikeZoneStartX and self.recordedPitchX < C.StrikeZoneEndX then
|
||||||
self.strikes = self.strikes + 1
|
self.strikes = self.strikes + 1
|
||||||
|
currentPitchingStats.strikes = currentPitchingStats.strikes + 1
|
||||||
if self.strikes >= 3 then
|
if self.strikes >= 3 then
|
||||||
self:reset()
|
self:reset()
|
||||||
return PitchOutcomes.StrikeOut
|
return PitchOutcomes.StrikeOut
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self.balls = self.balls + 1
|
self.balls = self.balls + 1
|
||||||
|
currentPitchingStats.balls = currentPitchingStats.balls + 1
|
||||||
if self.balls >= 4 then
|
if self.balls >= 4 then
|
||||||
self:reset()
|
self:reset()
|
||||||
return PitchOutcomes.Walk
|
return PitchOutcomes.Walk
|
||||||
|
|
Loading…
Reference in New Issue