Bigger background for panning across.

Refactor out utils.lua
This commit is contained in:
Sage Vaillancourt 2025-01-26 23:24:41 -05:00
parent 5493f350df
commit 8bbc029c42
3 changed files with 92 additions and 57 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -3,6 +3,7 @@ import 'CoreLibs/easing.lua'
import 'CoreLibs/graphics.lua' import 'CoreLibs/graphics.lua'
import 'CoreLibs/object.lua' import 'CoreLibs/object.lua'
import 'CoreLibs/ui.lua' import 'CoreLibs/ui.lua'
import 'utils.lua'
local gfx = playdate.graphics local gfx = playdate.graphics
playdate.display.setRefreshRate(50) playdate.display.setRefreshRate(50)
@ -16,7 +17,10 @@ local playerImage = playerHighHat
local secPerFrame = 0.1 local secPerFrame = 0.1
local playerFrameElapsed = 0 local playerFrameElapsed = 0
local backgroundPan = -240 local backgroundPan = {
x = 0,
y = 0,
}
local pitchFlyTimeMs = 2500 local pitchFlyTimeMs = 2500
local ballStartY, endY = 90, 250 local ballStartY, endY = 90, 250
@ -41,8 +45,8 @@ local batTipX = 0
local batTipY = 0 local batTipY = 0
local MODES = { local MODES = {
batting = 0, batting = {},
running = 1 running = {}
} }
local currentMode = MODES.batting local currentMode = MODES.batting
@ -53,7 +57,7 @@ local hitMult = 10
local deltaTime = 0 local deltaTime = 0
local basePositions = { local bases = {
first = { x = screenW * 0.93, y = screenH * 0.52 }, first = { x = screenW * 0.93, y = screenH * 0.52 },
second = { x = screenW * 0.47, y = screenH * 0.19 }, second = { x = screenW * 0.47, y = screenH * 0.19 },
third = { x = screenW * 0.03, y = screenH * 0.52 }, third = { x = screenW * 0.03, y = screenH * 0.52 },
@ -85,8 +89,8 @@ function resetFielderPositions()
end end
resetFielderPositions() resetFielderPositions()
local playerStartingX = basePositions.home.x - 40 local playerStartingX = bases.home.x - 40
local playerStartingY = basePositions.home.y - 3 local playerStartingY = bases.home.y - 3
local player = { local player = {
x = playerStartingX, x = playerStartingX,
y = playerStartingY, y = playerStartingY,
@ -109,10 +113,6 @@ function throwBall(destX, destY)
hitAnimatorX = gfx.animator.new(throwFlyTime, ballX, destX, playdate.easingFunctions.linear) hitAnimatorX = gfx.animator.new(throwFlyTime, ballX, destX, playdate.easingFunctions.linear)
end end
function getNextThrowTarget()
return basePositions.first.x, basePositions.first.y
end
function pitch() function pitch()
pitchAnimator:reset() pitchAnimator:reset()
resetFielderPositions() resetFielderPositions()
@ -121,6 +121,9 @@ function pitch()
ballX = 200 ballX = 200
currentMode = MODES.batting currentMode = MODES.batting
backgroundPan.y = 0
backgroundPan.x = 0
-- TODO: Add new runners, instead -- TODO: Add new runners, instead
runners = {} runners = {}
player.x = playerStartingX player.x = playerStartingX
@ -151,25 +154,6 @@ local pitchClockSec = 99
local elapsedTime = 0 local elapsedTime = 0
local crankChange local crankChange
function ballPassedThruBat(ballX, ballY, batBaseX, batBaseY, batTipX, batTipY)
-- This check currently assumes right-handedness.
-- I.e. it assumes the ball is to the right of batBaseX
if ballX < batBaseX or ballX > batTipX or ballY > screenH then
return false
end
local m = (batTipY - batBaseY) / (batTipX - batBaseX)
-- y = mx + b
-- b = y1 - (m * x1)
local b = batBaseY - (m * batBaseX)
local yOnLine = (m * ballX) + b
local yP = ballY
local yDelta = yOnLine - yP
return yDelta <= 0
end
function updateInfield() function updateInfield()
if ballDestX == nil or ballDestY == nil then if ballDestX == nil or ballDestY == nil then
return return
@ -200,7 +184,15 @@ function updateRunners()
if runner.nextBase then if runner.nextBase then
local nb = runner.nextBase local nb = runner.nextBase
local x, y, distance = normalizeVector(runner.x, runner.y, nb.x, nb.y) local x, y, distance = normalizeVector(runner.x, runner.y, nb.x, nb.y)
if distance > 1 then runner.hasArrived = distance <= 1
if runner.hasArrived then
-- if runner.onArrive then
-- runner.onArrive()
-- end
runner.targetX = nil
runner.targetY = nil
else
local mult = 1 local mult = 1
if crankChange < 0 then if crankChange < 0 then
mult = -1 mult = -1
@ -208,31 +200,14 @@ function updateRunners()
mult = (mult * runnerSpeed * deltaTime) + (crankChange / 20) mult = (mult * runnerSpeed * deltaTime) + (crankChange / 20)
runner.x -= x * mult runner.x -= x * mult
runner.y -= y * mult runner.y -= y * mult
else
if runner.onArrive then
runner.onArrive()
end
runner.targetX = nil
runner.targetY = nil
end end
end end
end end
end end
function normalizeVector(x1, y1, x2, y2)
local distance, a, b = distanceBetween(x1, y1, x2, y2)
return a / distance, b / distance, distance
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) function getNearestFielder(x, y)
local nearestFielder, nearestDistance = nil, nil local nearestFielder, nearestDistance = nil, nil
for title,fielder in pairs(fielders) do for _, fielder in pairs(fielders) do
if nearestFielder == nil then if nearestFielder == nil then
nearestFielder = fielder nearestFielder = fielder
nearestDistance = distanceBetween(fielder.x, fielder.y, x, y) nearestDistance = distanceBetween(fielder.x, fielder.y, x, y)
@ -256,6 +231,15 @@ function throwArrivedBeforeRunner()
return false return false
end end
function getForcedOutTargets()
return { bases.first }
end
function getNextThrowTarget()
local targets = getForcedOutTargets()
return targets[1].x, targets[1].y
end
function updateGameState() function updateGameState()
deltaTime = playdate.getElapsedTime() deltaTime = playdate.getElapsedTime()
playdate.resetElapsedTime() playdate.resetElapsedTime()
@ -281,7 +265,7 @@ function updateGameState()
crankChange, acceleratedChange = playdate.getCrankChange() crankChange, acceleratedChange = playdate.getCrankChange()
if currentMode == MODES.batting and acceleratedChange >= 0 and if currentMode == MODES.batting and acceleratedChange >= 0 and
ballPassedThruBat(ballX, ballY, batBaseX, batBaseY, batTipX, batTipY) then pointDirectlyUnderLine(ballX, ballY, batBaseX, batBaseY, batTipX, batTipY, screenH) then
ballAngle = batAngle + math.rad(90) ballAngle = batAngle + math.rad(90)
mult = math.abs(acceleratedChange / 15) mult = math.abs(acceleratedChange / 15)
@ -301,10 +285,10 @@ function updateGameState()
throwBall(getNextThrowTarget()) throwBall(getNextThrowTarget())
chasingFielder.onArrive = nil chasingFielder.onArrive = nil
end end
fielders.first.targetX = basePositions.first.x fielders.first.targetX = bases.first.x
fielders.first.targetY = basePositions.first.y fielders.first.targetY = bases.first.y
currentMode = MODES.running currentMode = MODES.running
player.nextBase = basePositions.first player.nextBase = bases.first
runners[#runners+1] = player runners[#runners+1] = player
end end
@ -312,32 +296,52 @@ function updateGameState()
updateRunners() updateRunners()
updateInfield() updateInfield()
end end
-- TODO: Show baserunning minimap when panning?
local ballBuffer = 5
if ballY < ballBuffer then
backgroundPan.y = math.max(ballBuffer, -1 * (ballY - ballBuffer))
else backgroundPan.y = 0
end
if ballX < ballBuffer then
backgroundPan.x = math.max(-400, -1 * (ballX - ballBuffer))
elseif ballX > (screenW - ballBuffer) then
backgroundPan.x = math.min(800, -1 * (ballX - ballBuffer))
end
if ballX > 0 and ballX < (screenW - ballBuffer) then
backgroundPan.x = 0
end
end end
function playdate.update() function playdate.update()
updateGameState() updateGameState()
grassBackground:draw(0, backgroundPan) gfx.clear()
grassBackground:draw(backgroundPan.x - 400, backgroundPan.y - 240)
gfx.setColor(gfx.kColorBlack) gfx.setColor(gfx.kColorBlack)
gfx.setLineWidth(2) gfx.setLineWidth(2)
gfx.drawCircleAtPoint(ballX, ballY, ballSize) gfx.drawCircleAtPoint(ballX + backgroundPan.x, ballY + backgroundPan.y, ballSize)
for title,fielder in pairs(fielders) do for title,fielder in pairs(fielders) do
gfx.fillRect(fielder.x, fielder.y, 14, 25) gfx.fillRect(fielder.x + backgroundPan.x, fielder.y + backgroundPan.y, 14, 25)
end end
gfx.setLineWidth(5) gfx.setLineWidth(5)
if currentMode == MODES.batting then if currentMode == MODES.batting then
gfx.drawLine(batBaseX, batBaseY, batTipX, batTipY) gfx.drawLine(
batBaseX + backgroundPan.x, batBaseY + backgroundPan.y,
batTipX + backgroundPan.x, batTipY + backgroundPan.y
)
end end
if playdate.isCrankDocked() then if playdate.isCrankDocked() then
playdate.ui.crankIndicator:draw() playdate.ui.crankIndicator:draw()
end end
playerImage:draw(player.x, player.y) playerImage:draw(player.x + backgroundPan.x, player.y + backgroundPan.y)
-- TODO: Use gfx.animation.blinker instead -- TODO: Use gfx.animation.blinker instead
if currentMode == MODES.running and playerFrameElapsed > secPerFrame then if currentMode == MODES.running and playerFrameElapsed > secPerFrame then

31
src/utils.lua Normal file
View File

@ -0,0 +1,31 @@
--- Returns the normalized vector as two values, plus the distance between the given points.
function normalizeVector(x1, y1, x2, y2)
local distance, a, b = distanceBetween(x1, y1, x2, y2)
return a / distance, b / distance, distance
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 pointDirectlyUnderLine(pointX, pointY, lineX1, lineY1, lineX2, lineY2, bottomBound)
-- This check currently assumes right-handedness.
-- I.e. it assumes the ball is to the right of batBaseX
if pointX < lineX1 or pointX > lineX2 or pointY > bottomBound then
return false
end
local m = (lineY2 - lineY1) / (lineX2 - lineX1)
-- y = mx + b
-- b = y1 - (m * x1)
local b = lineY1 - (m * lineX1)
local yOnLine = (m * pointX) + b
local yP = pointY
local yDelta = yOnLine - yP
return yDelta <= 0
end