69 lines
2.3 KiB
Lua
69 lines
2.3 KiB
Lua
---@class BatRenderState
|
|
---@field batBase XyPair
|
|
---@field batTip XyPair
|
|
---@field batAngleDeg number
|
|
---@field batSpeed number
|
|
|
|
---@class Batting
|
|
---@field private Baserunning
|
|
---@field state BatRenderState Is updated by checkForHit()
|
|
Batting = {}
|
|
|
|
local SwingBackDeg <const> = 30
|
|
local SwingForwardDeg <const> = 170
|
|
local OffscreenPos <const> = utils.xy(-999, -999)
|
|
|
|
---@param baserunning Baserunning
|
|
function Batting.new(baserunning)
|
|
return setmetatable({
|
|
baserunning = baserunning,
|
|
state = {
|
|
batAngleDeg = 0,
|
|
batSpeed = 0,
|
|
batTip = OffscreenPos,
|
|
batBase = OffscreenPos,
|
|
},
|
|
}, { __index = Batting })
|
|
end
|
|
|
|
-- TODO? Make the bat angle work more like the throw meter.
|
|
-- Would instead constantly drift toward a default value, giving us a little more control,
|
|
-- and letting the user find a crank position and direction that works for them
|
|
|
|
--- Assumes the bat is being held by self.baserunning.batter
|
|
--- Mutates self.state for later rendering.
|
|
---@param batDeg number
|
|
---@param batSpeed number
|
|
---@param ball Point3d
|
|
---@return XyPair | nil, boolean, number | nil Ball destination or nil if no hit, true only if batter swung, power mult
|
|
function Batting:checkForHit(batDeg, batSpeed, ball)
|
|
local batter = self.baserunning.batter
|
|
local isSwinging = batDeg > SwingBackDeg and batDeg < SwingForwardDeg
|
|
local batRadians = math.rad(batDeg)
|
|
|
|
local base = batter and utils.xy(batter.x + C.BatterHandPos.x, batter.y + C.BatterHandPos.y) or OffscreenPos
|
|
local tip = utils.xy(base.x + (C.BatLength * math.sin(batRadians)), base.y + (C.BatLength * math.cos(batRadians)))
|
|
|
|
self.state.batSpeed = batSpeed
|
|
self.state.batAngleDeg = batDeg
|
|
self.state.batTip = tip
|
|
self.state.batBase = base
|
|
|
|
local ballWasHit = batSpeed > 0 and ball.y < 232 and utils.pointOnOrUnderLine(ball, base, tip, C.Screen.H)
|
|
|
|
if not ballWasHit then
|
|
return nil, isSwinging
|
|
end
|
|
|
|
local ballAngle = batRadians + math.rad(90)
|
|
local mult = math.abs(batSpeed / 15)
|
|
local ballVelX = mult * C.BattingPower * 10 * math.sin(ballAngle)
|
|
local ballVelY = mult * C.BattingPower * 5 * math.cos(ballAngle)
|
|
if ballVelY > 0 then
|
|
ballVelX = ballVelX * -1
|
|
ballVelY = ballVelY * -1
|
|
end
|
|
|
|
return utils.xy(ball.x + ballVelX, ball.y + ballVelY), isSwinging, mult
|
|
end
|