From 42a537dae0979cd634de54f5928ca1d8a7b92961 Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Sun, 26 Jan 2025 17:24:32 -0500 Subject: [PATCH] Add simple fielder chasing and throwing mechanics. --- src/main.lua | 104 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 5 deletions(-) diff --git a/src/main.lua b/src/main.lua index 5af58f5..d36d1a1 100644 --- a/src/main.lua +++ b/src/main.lua @@ -40,14 +40,44 @@ local hitAnimatorX local hitMult = 10 +local deltaTime = 0 + +local basePositions = { + first = { x = screenW * 0.93, y = screenH * 0.52 }, + second = { x = screenW * 0.47, y = screenH * 0.19 }, + third = { x = screenW * 0.03, y = screenH * 0.52 }, + home = { x = screenW * 0.474, y = screenH * 0.79 } +} + +local fielders +function resetFielders() + fielders = { + first = { x = screenW - 65, y = screenH * 0.48 }, + second = { x = screenW * 0.70, y = screenH * 0.30 }, + shortstop = { x = screenW * 0.30, y = screenH * 0.30 }, + third = { x = screenW * 0.1, y = screenH * 0.48 }, + pitcher = { x = screenW * 0.48, y = screenH * 0.40 } + } +end +resetFielders() + + function hitBall(destX, destY, hitFlyTime) - ballSizeAnimator:reset() + ballSizeAnimator:reset(ballSizeMs) hitAnimatorY = gfx.animator.new(hitFlyTime, ballY, destY, playdate.easingFunctions.outQuint) hitAnimatorX = gfx.animator.new(hitFlyTime, ballX, destX, playdate.easingFunctions.outQuint) end +function throwBall(destX, destY) + local throwFlyTime = distanceBetween(ballX, ballY, destX, destY) * 5 + ballSizeAnimator:reset(throwFlyTime) + hitAnimatorY = gfx.animator.new(throwFlyTime, ballY, destY, playdate.easingFunctions.linear) + hitAnimatorX = gfx.animator.new(throwFlyTime, ballX, destX, playdate.easingFunctions.linear) +end + function pitch() pitchAnimator:reset() + resetFielders() ballVelX = 0 ballVelY = 0 ballX = 200 @@ -74,7 +104,7 @@ function playdate.leftButtonDown() batBaseX -= 1 end -local pitchClockSec = 5 +local pitchClockSec = 99 local elapsedTime = 0 function ballPassedThruBat(ballX, ballY, batBaseX, batBaseY, batTipX, batTipY) @@ -96,8 +126,57 @@ function ballPassedThruBat(ballX, ballY, batBaseX, batBaseY, batTipX, batTipY) return yDelta <= 0 end +function updateInfield() + if not hit or ballDestX == nil or ballDestY == nil then + return + end + + local fielderSpeed = 50 + for title,fielder in pairs(fielders) do + if fielder.targetX ~= nil and fielder.targetY ~= nil then + local distance, a, b = distanceBetween(fielder.x, fielder.y, fielder.targetX, fielder.targetY) + local normalizer = fielderSpeed / distance + + if distance > 1 then + fielder.x -= a * normalizer * deltaTime + fielder.y -= b * normalizer * deltaTime + else + if fielder.onArrive then + fielder.onArrive(fielder.targetX, fielder.targetY) + end + fielder.targetX = nil + fielder.targetY = nil + end + end + end +end + +function distanceBetween(x1, y1, x2, y2) + local a = x1 - x2 + local b = y1 - y2 + return math.sqrt((a*a) + (b*b)), a, b +end + +function getNearestFielder(x, y) + local nearestFielder, nearestDistance = nil, nil + for title,fielder in pairs(fielders) do + if nearestFielder == nil then + nearestFielder = fielder + nearestDistance = distanceBetween(fielder.x, fielder.y, x, y) + else + local distance = distanceBetween(fielder.x, fielder.y, x, y) + if distance < nearestDistance then + nearestFielder = fielder + nearestDistance = distance + end + end + end + + return nearestFielder +end + function updateGameState() - local deltaTime = playdate.getElapsedTime() + deltaTime = playdate.getElapsedTime() playdate.resetElapsedTime() elapsedTime = elapsedTime + deltaTime @@ -119,10 +198,11 @@ function updateGameState() batTipX = batBaseX + (batLength * math.sin(batAngle)) batTipY = batBaseY + (batLength * math.cos(batAngle)) - if hit == false and ballPassedThruBat(ballX, ballY, batBaseX, batBaseY, batTipX, batTipY) then + crankChange, acceleratedChange = playdate.getCrankChange() + if hit == false and acceleratedChange >= 0 and + ballPassedThruBat(ballX, ballY, batBaseX, batBaseY, batTipX, batTipY) then ballAngle = batAngle + math.rad(90) - crankChange, acceleratedChange = playdate.getCrankChange() mult = math.abs(acceleratedChange / 15) ballVelX = mult * 10 * math.sin(ballAngle) ballVelY = mult * 5 * math.cos(ballAngle) @@ -133,9 +213,19 @@ function updateGameState() ballDestX = ballX + (ballVelX * hitMult) ballDestY = ballY + (ballVelY * hitMult) hitBall(ballDestX, ballDestY, 2000) + local chasingFielder = getNearestFielder(ballDestX, ballDestY) + chasingFielder.targetX = ballDestX + chasingFielder.targetY = ballDestY + chasingFielder.onArrive = function() + throwBall(basePositions.first.x, basePositions.first.y) + end + fielders.first.targetX = basePositions.first.x + fielders.first.targetY = basePositions.first.y hit = true end lastBallY = ballY + + updateInfield() end function playdate.update() @@ -147,6 +237,10 @@ function playdate.update() gfx.setLineWidth(2) gfx.drawCircleAtPoint(ballX, ballY, ballSize) + for title,fielder in pairs(fielders) do + gfx.fillRect(fielder.x, fielder.y, 14, 25) + end + gfx.setLineWidth(5) gfx.drawLine(batBaseX, batBaseY, batTipX, batTipY)