Toying with trajectory-based missed-ball physics

This commit is contained in:
Sage Vaillancourt 2025-02-25 08:13:40 -05:00
parent 55a3a7b0ee
commit 58c6ab9fe6
2 changed files with 28 additions and 5 deletions

View File

@ -2,8 +2,10 @@
---@field x number ---@field x number
---@field y number ---@field y number
---@field z number ---@field z number
---@field trajectory Point3d
---@field size number ---@field size number
---@field heldBy Fielder | nil ---@field heldBy Fielder | nil
---@field isFlyBall boolean
---@field catchable boolean ---@field catchable boolean
---@field xAnimator SimpleAnimator ---@field xAnimator SimpleAnimator
---@field yAnimator SimpleAnimator ---@field yAnimator SimpleAnimator
@ -20,6 +22,7 @@ function Ball.new(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,
isFlyBall = false,
catchable = true, catchable = true,
size = C.SmallestBallRadius, size = C.SmallestBallRadius,
heldBy = nil --[[@type Runner | nil]], heldBy = nil --[[@type Runner | nil]],
@ -34,19 +37,39 @@ function Ball.new(animatorLib)
}, { __index = Ball }) }, { __index = Ball })
end end
function Ball:updatePosition() ---@param deltaSeconds number
function Ball:updatePosition(deltaSeconds)
if self.heldBy then if self.heldBy then
self.x = self.heldBy.x self.x = self.heldBy.x
self.y = self.heldBy.y self.y = self.heldBy.y
self.z = C.GloveZ self.z = C.GloveZ
self.size = C.SmallestBallRadius self.size = C.SmallestBallRadius
else elseif self.floatAnimator:ended() then
-- Try to bounce?
if self.trajectory then
printTable(self.trajectory)
-- if utils.distanceBetweenPoints(self, self.trajectory) > 1 then
-- self:launch()
-- end
-- local easing = playdate.easingFunctions.outQuint
-- self:launch(self.x + self.trajectory.x, self.y + self.trajectory.y, easing, nil, true)
self.trajectory = nil
end
--else
local lastPos = { x = self.x, y = self.y, z = self.z }
self.x = self.xAnimator:currentValue() self.x = self.xAnimator:currentValue()
local z = self.floatAnimator:currentValue() local z = self.floatAnimator:currentValue()
-- TODO: This `+ z` is more graphics logic than physics logic -- TODO: This `+ z` is more graphics logic than physics logic
self.y = self.yAnimator:currentValue() + z self.y = self.yAnimator:currentValue() + z
self.z = z self.z = z
self.size = self.sizeAnimator:currentValue() self.size = self.sizeAnimator:currentValue()
self.trajectory = { x = self.x - lastPos.x, y = self.y - lastPos.y, z = self.z - lastPos.z }
self.trajectory.x = self.trajectory.x / deltaSeconds
self.trajectory.y = self.trajectory.y / deltaSeconds
self.trajectory.z = self.trajectory.z / deltaSeconds
end
if self.z < 1 then
self.isFlyBall = false
end end
end end
@ -82,7 +105,7 @@ function Ball:launch(destX, destY, easingFunc, flyTimeMs, floaty, customBallScal
self.yAnimator = self.animatorLib.new(flyTimeMs, self.y, destY, easingFunc) self.yAnimator = self.animatorLib.new(flyTimeMs, self.y, destY, easingFunc)
self.xAnimator = self.animatorLib.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 / 2)
end end
end end

View File

@ -124,7 +124,7 @@ Game = {}
function Game.new(settings, announcer, fielding, baserunning, npc, state) function Game.new(settings, announcer, fielding, baserunning, npc, state)
announcer = announcer or Announcer.new() announcer = announcer or Announcer.new()
fielding = fielding or Fielding.new() fielding = fielding or Fielding.new()
settings.userTeam = nil -- "away" settings.userTeam = "home" -- "away"
local homeTeamBlipper = blipper.new(100, settings.homeTeamSpriteGroup) local homeTeamBlipper = blipper.new(100, settings.homeTeamSpriteGroup)
local awayTeamBlipper = blipper.new(100, settings.awayTeamSpriteGroup) local awayTeamBlipper = blipper.new(100, settings.awayTeamSpriteGroup)
@ -524,7 +524,7 @@ function Game:updateGameState()
gfx.animation.blinker.updateAll() gfx.animation.blinker.updateAll()
self.state.deltaSeconds = playdate.getElapsedTime() or 0 self.state.deltaSeconds = playdate.getElapsedTime() or 0
playdate.resetElapsedTime() playdate.resetElapsedTime()
self.state.ball:updatePosition() self.state.ball:updatePosition(self.state.deltaSeconds)
local offenseHandler, defenseHandler = self:currentInputHandlers() local offenseHandler, defenseHandler = self:currentInputHandlers()