From 44ba30ee978466fd7834291dcf25ba3d36b124d7 Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Tue, 4 Feb 2025 13:04:26 -0500 Subject: [PATCH] Remove Fielder.onArrive() callback Instead, just try to throw for an out when touching the ball. This also tentatively moves toward implementing cutoff throws. Re-org to define tryToThrowOut() before it is referenced. --- src/main.lua | 168 +++++++++++++++++++++++++-------------------------- 1 file changed, 82 insertions(+), 86 deletions(-) diff --git a/src/main.lua b/src/main.lua index 1b1202b..3eaa76b 100644 --- a/src/main.lua +++ b/src/main.lua @@ -26,7 +26,6 @@ import 'CoreLibs/ui.lua' --- } --- @alias Fielder { ---- onArrive: fun() | nil, --- x: number | nil, --- y: number | nil, --- target: XYPair | nil, @@ -162,23 +161,24 @@ local NextBaseMap = { [Bases[Third]] = Bases[Home], } -function newFielder(speed) +function newFielder(name, speed) return { + name = name, speed = speed, } end ---@type table local fielders = { - first = newFielder(40), - second = newFielder(40), - shortstop = newFielder(40), - third = newFielder(40), - pitcher = newFielder(30), - catcher = newFielder(20), - left = newFielder(40), - center = newFielder(40), - right = newFielder(40), + first = newFielder("First", 40), + second = newFielder("Second", 40), + shortstop = newFielder("Shortstop", 40), + third = newFielder("Third", 40), + pitcher = newFielder("Pitcher", 30), + catcher = newFielder("Catcher", 20), + left = newFielder("Left", 40), + center = newFielder("Center", 40), + right = newFielder("Right", 40), } local PitcherStartPos = { @@ -380,6 +380,64 @@ function score(runnerIndex) announcer:say("SCORE!") end +---@return Base[] +function getForcedOutTargets() + local targets = {} + for _, base in ipairs(Bases) do + local runnerTargetingBase = getRunnerTargeting(base) + if runnerTargetingBase then + targets[#targets + 1] = base + else + return targets + end + end + return targets +end + +--- Returns the position,distance of the basest closest to the runner furthest from a base +---@return Base | nil, number | nil +function getBaseOfStrandedRunner() + local farRunnersBase, farDistance + for _, runner in pairs(runners) do + local nearestBase, distance = getNearestOf(Bases, runner.x, runner.y, function(base) + return runner.nextBase == base + end) + if farRunnersBase == nil or farDistance < distance then + farRunnersBase = nearestBase + farDistance = distance + end + end + + return farRunnersBase, farDistance +end +--- Returns x,y of the throw target +---@return number|nil, number|nil +function getNextThrowTarget() + -- TODO: Handle missed throws, check for fielders at target, etc. + local targets = getForcedOutTargets() + if #targets ~= 0 then + return targets[#targets].x, targets[#targets].y + end + + local baseCloseToStrandedRunner = getBaseOfStrandedRunner() + if baseCloseToStrandedRunner then + return baseCloseToStrandedRunner.x, baseCloseToStrandedRunner.y + end +end + +function tryToThrowOut(thrower) + local targetX, targetY = getNextThrowTarget() + if targetX ~= nil and targetY ~= nil then + local nearestFielder = getNearestOf(fielders, targetX, targetY) + nearestFielder.target = xy(targetX, targetY) + if nearestFielder == thrower then + ball.heldBy = thrower + else + throwBall(targetX, targetY, playdate.easingFunctions.linear, nil, true) + end + end +end + function updateFielders() local touchingBaseCache = buildCache(function(runner) return isTouchingBase(runner.x, runner.y) @@ -388,6 +446,7 @@ function updateFielders() for _, fielder in pairs(fielders) do -- TODO: Target unforced runners (or their target bases) for tagging -- With new Position-based scheme, fielders are now able to set `fielder.target = runner` to track directly + if fielder.target ~= nil then local x, y, distance = normalizeVector(fielder.x, fielder.y, fielder.target.x, fielder.target.y) @@ -396,9 +455,6 @@ function updateFielders() fielder.y = fielder.y - (y * fielder.speed * deltaSeconds) else fielder.target = nil - if fielder.onArrive then - fielder:onArrive() - end end end @@ -407,22 +463,23 @@ function updateFielders() local touchedBase = isTouchingBase(fielder.x, fielder.y) for i, runner in pairs(runners) do if - touchedBase - and runner.prevBase -- Make sure the runner is not standing at home - and runner.forcedTo == touchedBase - and touchedBase ~= touchingBaseCache.get(runner) + ( -- Force out + touchedBase + and runner.prevBase -- Make sure the runner is not standing at home + and runner.forcedTo == touchedBase + and touchedBase ~= touchingBaseCache.get(runner) + ) + or ( -- Tag out + not touchingBaseCache.get(runner) + and distanceBetween(runner.x, runner.y, fielder.x, fielder.y) < TagDistance + ) then outRunner(i) playdate.timer.new(750, function() tryToThrowOut(fielder) end) - elseif not touchingBaseCache.get(runner) then - if distanceBetween(runner.x, runner.y, fielder.x, fielder.y) < TagDistance then - outRunner(i) - playdate.timer.new(750, function() - tryToThrowOut(fielder) - end) - end + else + tryToThrowOut(fielder) end end end @@ -485,52 +542,6 @@ function updateRunners(currentRunners) return runnerMoved end ----@return Base[] -function getForcedOutTargets() - local targets = {} - for _, base in ipairs(Bases) do - local runnerTargetingBase = getRunnerTargeting(base) - if runnerTargetingBase then - targets[#targets + 1] = base - else - return targets - end - end - return targets -end - ---- Returns the position,distance of the basest closest to the runner furthest from a base ----@return Base | nil, number | nil -function getBaseOfStrandedRunner() - local farRunnersBase, farDistance - for _, runner in pairs(runners) do - local nearestBase, distance = getNearestOf(Bases, runner.x, runner.y, function(base) - return runner.nextBase == base - end) - if farRunnersBase == nil or farDistance < distance then - farRunnersBase = nearestBase - farDistance = distance - end - end - - return farRunnersBase, farDistance -end - ---- Returns x,y of the throw target ----@return number|nil, number|nil -function getNextThrowTarget() - -- TODO: Handle missed throws, check for fielders at target, etc. - local targets = getForcedOutTargets() - if #targets ~= 0 then - return targets[#targets].x, targets[#targets].y - end - - local baseCloseToStrandedRunner = getBaseOfStrandedRunner() - if baseCloseToStrandedRunner then - return baseCloseToStrandedRunner.x, baseCloseToStrandedRunner.y - end -end - local ResetFieldersAfterSeconds = 2 -- TODO: Replace with a timer, repeatedly reset instead of setting to 0 local secondsSinceLastRunnerMove = 0 @@ -551,20 +562,6 @@ function init() end) end -function tryToThrowOut(self) - self.onArrive = nil - local targetX, targetY = getNextThrowTarget() - if targetX ~= nil and targetY ~= nil then - local nearestFielder = getNearestOf(fielders, targetX, targetY) - nearestFielder.target = xy(targetX, targetY) - if nearestFielder == self then - ball.heldBy = self - else - throwBall(targetX, targetY, playdate.easingFunctions.linear, nil, true) - end - end -end - local batAngleDeg function updateBatting() @@ -617,7 +614,6 @@ function updateBatting() local chasingFielder = getNearestOf(fielders, ballDestX, ballDestY) chasingFielder.target = { x = ballDestX, y = ballDestY } - chasingFielder.onArrive = tryToThrowOut end end