Add batter walk-up.

Attach bat to batter.
Prevent draw-offset changes when the ball is below the screen.
This commit is contained in:
Sage Vaillancourt 2025-02-01 16:26:44 -05:00
parent f1d8c28370
commit 32f9b24d1f
2 changed files with 26 additions and 21 deletions

View File

@ -4,8 +4,11 @@ local ballBuffer = 5
--- XXX
--- XOX
--- Where each character is the size of the screen, and 'O' is the default view.
function getDrawOffset(screenW, _screenH, ballX, ballY)
function getDrawOffset(screenW, screenH, ballX, ballY)
local offsetX, offsetY
if ballY > screenH then
return 0, 0
end
if ballY < ballBuffer then
offsetY = math.max(ballBuffer, -1 * (ballY - ballBuffer))
else

View File

@ -46,6 +46,7 @@ local PITCH_START_Y, PITCH_END_Y = 90, 250
local pitchAnimator = gfx.animator.new(pitchFlyTimeMs, PITCH_START_Y, PITCH_END_Y, playdate.easingFunctions.outQuint)
local CRANK_OFFSET_DEG = 90
local BAT_OFFSET = xy(10, 25)
local batBase = xy(CENTER.x - 34, 215)
local batTip = xy(0, 0)
@ -53,7 +54,7 @@ local TAG_DISTANCE = 20
local ball = {
x = CENTER.x,
y = BALL_OFFSCREEN,
y = CENTER.y,
size = 6,
}
@ -88,6 +89,9 @@ local bases = {
xy(SCREEN.W * 0.474, SCREEN.H * 0.79),
}
-- Pseudo-base for batter to target
local rightHandedBattersBox = xy(bases[HOME].x - 35, bases[HOME].y)
---@type table<Base, Base>
local nextBaseMap = {
[bases[FIRST]] = bases[SECOND],
@ -155,11 +159,12 @@ local runnerNames = { "Barbara", "Steve", "Jerry", "Beatrice" }
---@return Runner
function newRunner()
local new = {
x = PLAYER_STARTING_X,
y = PLAYER_STARTING_Y,
nextBase = nil,
x = PLAYER_STARTING_X - 60,
y = PLAYER_STARTING_Y + 60,
nextBase = rightHandedBattersBox,
prevBase = nil,
name = runnerNames[nameI],
forcedTo = bases[FIRST]
}
nameI = nameI + 1
runners[#runners + 1] = new
@ -168,8 +173,6 @@ end
---@type Runner | nil
local batter = newRunner()
batter.nextBase = bases[FIRST]
batter.forcedTo = bases[FIRST]
--- "Throws" the ball from its current position to the given destination.
function throwBall(destX, destY, easingFunc, flyTimeMs, floaty)
@ -243,7 +246,6 @@ local homeScore = 0
local awayScore = 0
function outRunner(runnerIndex)
print("You're out, runner" .. runnerIndex .. "!")
outs = math.min(3, outs + 1)
outRunners[#outRunners + 1] = runners[runnerIndex]
table.remove(runners, runnerIndex)
@ -285,14 +287,10 @@ function updateFielders()
local touchedBase = isTouchingBase(fielder.x, fielder.y)
for i, runner in pairs(runners) do
local runnerOnBase = touchingBaseCache.get(runner)
if touchedBase and runner.forcedTo == touchedBase and touchedBase ~= runnerOnBase then
print("Force out of runner:")
printTable(runner)
if touchedBase and runner.prevBase and runner.forcedTo == touchedBase and touchedBase ~= runnerOnBase then
outRunner(i)
elseif not runnerOnBase then
local fielderDistance = distanceBetween(runner.x, runner.y, fielder.x, fielder.y)
if fielderDistance < TAG_DISTANCE then
print("Tagged out!")
if distanceBetween(runner.x, runner.y, fielder.x, fielder.y) < TAG_DISTANCE then
outRunner(i)
end
end
@ -306,14 +304,14 @@ end
function updateRunners()
local autoRunSpeed = 20
--autoRunSpeed = 140
local nonPlayerRunners = filter(runners, function(runner)
local currentRunners = currentMode == MODES.batting and {batter} or filter(runners, function(runner)
return runner ~= batter
end)
local runnerMoved = false
for runnerIndex, runner in ipairs(nonPlayerRunners) do
for runnerIndex, runner in ipairs(currentRunners) do
local nearestBase, nearestBaseDistance = getNearestOf(bases, runner.x, runner.y)
if nearestBaseDistance < 5 and runner.nextBase == bases[HOME] and nearestBase == bases[HOME] then
if nearestBaseDistance < 5 and runner.prevBase and runner.nextBase == bases[HOME] and nearestBase == bases[HOME] then
score(runnerIndex)
end
if runner.nextBase then
@ -401,7 +399,7 @@ end
local resetFieldersAfterSeconds = 4
local secondsSinceLastRunnerMove = 0
local pitchAfterSeconds = 4
local pitchAfterSeconds = 5
local secondsSincePitchAllowed = -5
function init()
@ -418,11 +416,14 @@ function updateBatting()
secondsSincePitchAllowed = 0
end
if ball.y < BALL_OFFSCREEN then
ball.y = ballAnimatorY:currentValue()
ball.y = ballAnimatorY:currentValue() + ballFloatAnimator:currentValue()
ball.size = 6
end
local batAngle = math.rad(playdate.getCrankPosition() + CRANK_OFFSET_DEG)
-- TODO: animate bat-flip or something
batBase.x = batter and (batter.x + BAT_OFFSET.x) or 0
batBase.y = batter and (batter.y + BAT_OFFSET.y) or 0
batTip.x = batBase.x + (BAT_LENGTH * math.sin(batAngle))
batTip.y = batBase.y + (BAT_LENGTH * math.cos(batAngle))
@ -443,10 +444,12 @@ function updateBatting()
end
local ballDestX = ball.x + (ballVelX * HIT_MULT)
local ballDestY = ball.y + (ballVelY * HIT_MULT)
-- Hit!
throwBall(ballDestX, ballDestY, playdate.easingFunctions.outQuint, 2000)
fielders.first.target = bases[FIRST]
batter.nextBase = bases[FIRST]
batter.prevBase = bases[HOME]
batter.forcedTo = bases[FIRST]
batter = nil -- Demote batter to a mere runner
@ -474,8 +477,6 @@ function updateRunning()
resetFielderPositions(false)
currentMode = MODES.batting
batter = newRunner()
batter.nextBase = bases[FIRST]
batter.forcedTo = bases[FIRST]
end
end
end
@ -502,6 +503,7 @@ function updateGameState()
if currentMode == MODES.batting then
updateBatting()
updateRunners()
elseif currentMode == MODES.running then
updateRunning()
end