Try to cluster global state together.
Start peeling out fielder functions into a new file. A bit more constant use. In Makefile, parse main.lua imports for source files.
This commit is contained in:
parent
324673ea98
commit
66bd97499a
2
Makefile
2
Makefile
|
@ -1,4 +1,4 @@
|
|||
SOURCE_FILES := src/utils.lua src/constants.lua src/assets.lua src/draw/* src/dbg.lua src/npc.lua src/announcer.lua src/graphics.lua src/main.lua
|
||||
SOURCE_FILES := $(shell grep "import '" src/main.lua | grep -v CoreLibs | sed "s/.*'\(.*\)'.*/\1/") main.lua
|
||||
GENERATED_FILES := src/assets.lua
|
||||
|
||||
all:
|
||||
|
|
|
@ -98,3 +98,5 @@ C.CrankPower = 10
|
|||
|
||||
--- How fast baserunners move after a walk
|
||||
C.WalkedRunnerSpeed = 10
|
||||
|
||||
C.ResetFieldersAfterSeconds = 3
|
||||
|
|
|
@ -21,9 +21,9 @@ end
|
|||
-- Only works if called with the bases empty (i.e. the only runner should be the batter.
|
||||
-- selene: allow(unused_variable)
|
||||
function dbg.loadTheBases(runners)
|
||||
newRunner()
|
||||
newRunner()
|
||||
newRunner()
|
||||
utils.newRunner()
|
||||
utils.newRunner()
|
||||
utils.newRunner()
|
||||
runners[2].x = C.Bases[C.First].x
|
||||
runners[2].y = C.Bases[C.First].y
|
||||
runners[2].nextBase = C.Bases[C.Second]
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
---@param name string
|
||||
---@param speed number
|
||||
---@return Fielder
|
||||
function newFielder(name, speed)
|
||||
return {
|
||||
name = name,
|
||||
speed = speed,
|
||||
}
|
||||
end
|
||||
|
||||
-- selene: allow(unscoped_variables)
|
||||
Field = {
|
||||
fielders = {
|
||||
first = newFielder("First", 40),
|
||||
second = newFielder("Second", 40),
|
||||
shortstop = newFielder("Shortstop", 40),
|
||||
third = newFielder("Third", 40),
|
||||
pitcher = newFielder("Pitcher", 30),
|
||||
catcher = newFielder("Catcher", 35),
|
||||
left = newFielder("Left", 40),
|
||||
center = newFielder("C.Center", 40),
|
||||
right = newFielder("Right", 40),
|
||||
},
|
||||
}
|
||||
|
||||
--- Actually only benches the infield, because outfielders are far away!
|
||||
---@param position XYPair
|
||||
function Field.benchTo(self, position)
|
||||
self.fielders.first.target = position
|
||||
self.fielders.second.target = position
|
||||
self.fielders.shortstop.target = position
|
||||
self.fielders.third.target = position
|
||||
self.fielders.pitcher.target = position
|
||||
self.fielders.catcher.target = position
|
||||
end
|
||||
|
||||
--- Resets the target positions of all fielders to their defaults (at their field positions).
|
||||
---@param fromOffTheField XYPair | nil If provided, also sets all runners' current position to one centralized location.
|
||||
function Field.resetFielderPositions(self, fromOffTheField)
|
||||
if fromOffTheField then
|
||||
for _, fielder in pairs(self.fielders) do
|
||||
fielder.x = fromOffTheField.x
|
||||
fielder.y = fromOffTheField.y
|
||||
end
|
||||
end
|
||||
|
||||
self.fielders.first.target = utils.xy(C.Screen.W - 65, C.Screen.H * 0.48)
|
||||
self.fielders.second.target = utils.xy(C.Screen.W * 0.70, C.Screen.H * 0.30)
|
||||
self.fielders.shortstop.target = utils.xy(C.Screen.W * 0.30, C.Screen.H * 0.30)
|
||||
self.fielders.third.target = utils.xy(C.Screen.W * 0.1, C.Screen.H * 0.48)
|
||||
self.fielders.pitcher.target = utils.xy(C.PitcherStartPos.x, C.PitcherStartPos.y)
|
||||
self.fielders.catcher.target = utils.xy(C.Screen.W * 0.475, C.Screen.H * 0.92)
|
||||
self.fielders.left.target = utils.xy(C.Screen.W * -1, C.Screen.H * -0.2)
|
||||
self.fielders.center.target = utils.xy(C.Center.x, C.Screen.H * -0.4)
|
||||
self.fielders.right.target = utils.xy(C.Screen.W * 2, self.fielders.left.target.y)
|
||||
end
|
|
@ -2,19 +2,19 @@
|
|||
--- 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(ballX, ballY)
|
||||
local offsetX, offsetY
|
||||
if ballY > screenH then
|
||||
if ballY > C.Screen.H or ballX >= C.BallOffscreen then
|
||||
return 0, 0
|
||||
end
|
||||
offsetY = math.max(0, -1 * ballY)
|
||||
|
||||
if ballX > 0 and ballX < screenW then
|
||||
if ballX > 0 and ballX < C.Screen.W then
|
||||
offsetX = 0
|
||||
elseif ballX < 0 then
|
||||
offsetX = math.max(-1 * screenW, ballX * -1)
|
||||
elseif ballX > screenW then
|
||||
offsetX = math.min(screenW * 2, (ballX * -1) + screenW)
|
||||
offsetX = math.max(-1 * C.Screen.W, ballX * -1)
|
||||
elseif ballX > C.Screen.W then
|
||||
offsetX = math.min(C.Screen.W * 2, (ballX * -1) + C.Screen.W)
|
||||
end
|
||||
|
||||
return offsetX * 1.3, offsetY * 1.5
|
||||
|
|
250
src/main.lua
250
src/main.lua
|
@ -30,10 +30,11 @@ import 'assets.lua'
|
|||
|
||||
import 'announcer.lua'
|
||||
import 'dbg.lua'
|
||||
import 'field.lua'
|
||||
import 'graphics.lua'
|
||||
import 'npc.lua'
|
||||
import 'draw/overlay'
|
||||
import 'draw/fielder'
|
||||
import 'draw/overlay.lua'
|
||||
import 'draw/fielder.lua'
|
||||
-- stylua: ignore end
|
||||
|
||||
-- selene: allow(shadowing)
|
||||
|
@ -44,16 +45,72 @@ local PlayerImageBlipper <const> = blipper.new(100, Player, PlayerLowHat)
|
|||
local FielderDanceAnimator <const> = gfx.animator.new(1, 10, 0, utils.easingHill)
|
||||
FielderDanceAnimator.repeatCount = C.DanceBounceCount - 1
|
||||
|
||||
function fieldersDance()
|
||||
FielderDanceAnimator:reset(C.DanceBounceMs)
|
||||
end
|
||||
|
||||
local ballAnimatorY = gfx.animator.new(0, C.BallOffscreen, C.BallOffscreen, playdate.easingFunctions.linear)
|
||||
local ballAnimatorX = gfx.animator.new(0, C.BallOffscreen, C.BallOffscreen, playdate.easingFunctions.linear)
|
||||
|
||||
---@alias PseudoAnimator { currentValue: fun(self): number; reset: fun(self, durationMs: number | nil) }
|
||||
---@alias Pitch { x: PseudoAnimator, y: PseudoAnimator, z: PseudoAnimator | nil }
|
||||
|
||||
local ballAnimatorX = utils.staticAnimator(C.BallOffscreen)
|
||||
local ballAnimatorY = utils.staticAnimator(C.BallOffscreen)
|
||||
local ballSizeAnimator = utils.staticAnimator(C.SmallestBallRadius)
|
||||
|
||||
-- TODO? Replace this AND ballSizeAnimator with a ballAnimatorZ?
|
||||
-- ...that might lose some of the magic of both. Compromise available? idk
|
||||
local ballFloatAnimator = gfx.animator.new(2000, -60, 0, utils.easingHill)
|
||||
|
||||
local deltaSeconds = 0
|
||||
|
||||
local BatterHandPos <const> = utils.xy(10, 25)
|
||||
|
||||
local batBase <const> = utils.xy(C.Center.x - 34, 215)
|
||||
local batTip <const> = utils.xy(0, 0)
|
||||
|
||||
local ball <const> = {
|
||||
x = C.Center.x --[[@as number]],
|
||||
y = C.Center.y --[[@as number]],
|
||||
z = 0,
|
||||
size = C.SmallestBallRadius,
|
||||
heldBy = nil --[[@type Runner | nil]],
|
||||
}
|
||||
|
||||
---@alias Team { score: number, benchPosition: XYPair }
|
||||
|
||||
---@type table<string, Team>
|
||||
local teams <const> = {
|
||||
home = {
|
||||
score = 0,
|
||||
benchPosition = utils.xy(C.Screen.W + 10, C.Center.y),
|
||||
},
|
||||
away = {
|
||||
score = 0,
|
||||
benchPosition = utils.xy(-10, C.Center.y),
|
||||
},
|
||||
}
|
||||
|
||||
local PlayerTeam <const> = teams.away
|
||||
local battingTeam = teams.away
|
||||
local outs = 0
|
||||
local inning = 1
|
||||
local offenseMode = C.Offense.batting
|
||||
|
||||
--- @type Runner[]
|
||||
local runners <const> = {}
|
||||
|
||||
--- @type Runner[]
|
||||
local outRunners <const> = {}
|
||||
|
||||
---@type Runner | nil
|
||||
local batter = utils.newRunner(runners)
|
||||
|
||||
local throwMeter = 0
|
||||
|
||||
-- TODO: Replace with a timer, repeatedly reset, instead of setting to 0
|
||||
local secondsSinceLastRunnerMove = 0
|
||||
|
||||
-- TODO: Replace with a timer, repeatedly reset instead of setting to 0
|
||||
local secondsSincePitchAllowed = -5
|
||||
local catcherThrownBall = false
|
||||
|
||||
local batAngleDeg = C.CrankOffsetDeg
|
||||
|
||||
---@type Pitch[]
|
||||
local Pitches <const> = {
|
||||
-- Fastball
|
||||
|
@ -83,39 +140,6 @@ local Pitches <const> = {
|
|||
},
|
||||
}
|
||||
|
||||
local BatterHandPos <const> = utils.xy(10, 25)
|
||||
|
||||
local batBase <const> = utils.xy(C.Center.x - 34, 215)
|
||||
local batTip <const> = utils.xy(0, 0)
|
||||
|
||||
local ball <const> = {
|
||||
x = C.Center.x --[[@as number]],
|
||||
y = C.Center.y --[[@as number]],
|
||||
z = 0,
|
||||
size = C.SmallestBallRadius,
|
||||
heldBy = nil --[[@type Runner | nil]],
|
||||
}
|
||||
|
||||
---@alias Team { score: number, benchPosition: XYPair }
|
||||
|
||||
---@type table<string, Team>
|
||||
local teams <const> = {
|
||||
home = {
|
||||
score = 0,
|
||||
benchPosition = utils.xy(C.Screen.W + 10, C.Center.y),
|
||||
},
|
||||
away = {
|
||||
score = 0,
|
||||
benchPosition = utils.xy(-10, C.Center.y),
|
||||
},
|
||||
}
|
||||
|
||||
local PlayerTeam <const> = teams.home
|
||||
local battingTeam = teams.away
|
||||
local outs = 0
|
||||
local inning = 1
|
||||
local offenseMode = C.Offense.batting
|
||||
|
||||
---@return boolean playerIsOnSide, boolean playerIsOnOtherSide
|
||||
function playerIsOn(side)
|
||||
local ret
|
||||
|
@ -127,93 +151,6 @@ function playerIsOn(side)
|
|||
return ret, not ret
|
||||
end
|
||||
|
||||
-- TODO? Replace this AND ballSizeAnimator with a ballHeightAnimator
|
||||
-- ...that might lose some of the magic of both. Compromise available? idk
|
||||
local ballFloatAnimator = gfx.animator.new(2000, -60, 0, utils.easingHill)
|
||||
local BallSizeMs = 2000
|
||||
local ballSizeAnimator = gfx.animator.new(BallSizeMs, 9, C.SmallestBallRadius, utils.easingHill)
|
||||
|
||||
local deltaSeconds = 0
|
||||
|
||||
---@param name string
|
||||
---@param speed number
|
||||
---@return Fielder
|
||||
function newFielder(name, speed)
|
||||
return {
|
||||
name = name,
|
||||
speed = speed,
|
||||
}
|
||||
end
|
||||
|
||||
---@type table<string, Fielder>
|
||||
local fielders <const> = {
|
||||
first = newFielder("First", 40),
|
||||
second = newFielder("Second", 40),
|
||||
shortstop = newFielder("Shortstop", 40),
|
||||
third = newFielder("Third", 40),
|
||||
pitcher = newFielder("Pitcher", 30),
|
||||
catcher = newFielder("Catcher", 35),
|
||||
left = newFielder("Left", 40),
|
||||
center = newFielder("C.Center", 40),
|
||||
right = newFielder("Right", 40),
|
||||
}
|
||||
|
||||
--- Actually only benches the infield, because outfielders are far away!
|
||||
---@param position XYPair
|
||||
function benchAllFielders(position)
|
||||
fielders.first.target = position
|
||||
fielders.second.target = position
|
||||
fielders.shortstop.target = position
|
||||
fielders.third.target = position
|
||||
fielders.pitcher.target = position
|
||||
fielders.catcher.target = position
|
||||
end
|
||||
|
||||
--- Resets the target positions of all fielders to their defaults (at their field positions).
|
||||
---@param fromOffTheField XYPair | nil If provided, also sets all runners' current position to one centralized location.
|
||||
function resetFielderPositions(fromOffTheField)
|
||||
if fromOffTheField then
|
||||
for _, fielder in pairs(fielders) do
|
||||
fielder.x = fromOffTheField.x
|
||||
fielder.y = fromOffTheField.y
|
||||
end
|
||||
end
|
||||
|
||||
fielders.first.target = utils.xy(C.Screen.W - 65, C.Screen.H * 0.48)
|
||||
fielders.second.target = utils.xy(C.Screen.W * 0.70, C.Screen.H * 0.30)
|
||||
fielders.shortstop.target = utils.xy(C.Screen.W * 0.30, C.Screen.H * 0.30)
|
||||
fielders.third.target = utils.xy(C.Screen.W * 0.1, C.Screen.H * 0.48)
|
||||
fielders.pitcher.target = utils.xy(C.PitcherStartPos.x, C.PitcherStartPos.y)
|
||||
fielders.catcher.target = utils.xy(C.Screen.W * 0.475, C.Screen.H * 0.92)
|
||||
fielders.left.target = utils.xy(C.Screen.W * -1, C.Screen.H * -0.2)
|
||||
fielders.center.target = utils.xy(C.Center.x, C.Screen.H * -0.4)
|
||||
fielders.right.target = utils.xy(C.Screen.W * 2, fielders.left.target.y)
|
||||
end
|
||||
|
||||
--- @type Runner[]
|
||||
local runners <const> = {}
|
||||
|
||||
--- @type Runner[]
|
||||
local outRunners <const> = {}
|
||||
|
||||
---@return Runner
|
||||
function newRunner()
|
||||
local new = {
|
||||
x = C.RightHandedBattersBox.x - 60,
|
||||
y = C.RightHandedBattersBox.y + 60,
|
||||
nextBase = C.RightHandedBattersBox,
|
||||
prevBase = nil,
|
||||
forcedTo = C.Bases[C.First],
|
||||
}
|
||||
runners[#runners + 1] = new
|
||||
return new
|
||||
end
|
||||
|
||||
---@type Runner | nil
|
||||
local batter = newRunner()
|
||||
|
||||
local throwMeter = 0
|
||||
|
||||
--- "Throws" the ball from its current position to the given destination.
|
||||
---@param destX number
|
||||
---@param destY number
|
||||
|
@ -242,10 +179,6 @@ function throwBall(destX, destY, easingFunc, flyTimeMs, floaty, customBallScaler
|
|||
end
|
||||
end
|
||||
|
||||
-- TODO: Replace with a timer, repeatedly reset instead of setting to 0
|
||||
local secondsSincePitchAllowed = -5
|
||||
local catcherThrownBall = false
|
||||
|
||||
---@param pitchFlyTimeMs number | nil
|
||||
---@param pitchTypeIndex number | nil
|
||||
function pitch(pitchFlyTimeMs, pitchTypeIndex)
|
||||
|
@ -316,10 +249,6 @@ function updateForcedRunners()
|
|||
end
|
||||
end
|
||||
|
||||
local ResetFieldersAfterSeconds <const> = 5
|
||||
-- TODO: Replace with a timer, repeatedly reset, instead of setting to 0
|
||||
local secondsSinceLastRunnerMove = 0
|
||||
|
||||
---@param runner integer | Runner
|
||||
function outRunner(runner, message)
|
||||
if type(runner) ~= "number" then
|
||||
|
@ -346,9 +275,9 @@ function outRunner(runner, message)
|
|||
local currentlyFieldingTeam = battingTeam == teams.home and teams.away or teams.home
|
||||
local gameOver = inning == 9 and teams.away.score ~= teams.home.score
|
||||
if not gameOver then
|
||||
fieldersDance()
|
||||
FielderDanceAnimator:reset(C.DanceBounceMs)
|
||||
secondsSinceLastRunnerMove = -7
|
||||
benchAllFielders(currentlyFieldingTeam.benchPosition)
|
||||
Field:benchTo(currentlyFieldingTeam.benchPosition)
|
||||
announcer:say("SWITCHING SIDES...")
|
||||
end
|
||||
while #runners > 0 do
|
||||
|
@ -361,7 +290,7 @@ function outRunner(runner, message)
|
|||
if gameOver then
|
||||
announcer:say("AND THAT'S THE BALL GAME!")
|
||||
else
|
||||
resetFielderPositions()
|
||||
Field:resetFielderPositions()
|
||||
if battingTeam == teams.home then
|
||||
inning = inning + 1
|
||||
end
|
||||
|
@ -427,7 +356,7 @@ end
|
|||
function tryToMakeAnOut(fielder)
|
||||
local targetX, targetY = getNextOutTarget()
|
||||
if targetX ~= nil and targetY ~= nil then
|
||||
local nearestFielder = utils.getNearestOf(fielders, targetX, targetY)
|
||||
local nearestFielder = utils.getNearestOf(Field.fielders, targetX, targetY)
|
||||
nearestFielder.target = utils.xy(targetX, targetY)
|
||||
if nearestFielder == fielder then
|
||||
ball.heldBy = fielder
|
||||
|
@ -461,7 +390,7 @@ function buttonControlledThrow(thrower, throwFlyMs, forbidThrowHome)
|
|||
return false
|
||||
end
|
||||
|
||||
local closestFielder = utils.getNearestOf(fielders, targetBase.x, targetBase.y, function(fielder)
|
||||
local closestFielder = utils.getNearestOf(Field.fielders, targetBase.x, targetBase.y, function(fielder)
|
||||
return fielder ~= thrower
|
||||
end)
|
||||
|
||||
|
@ -524,7 +453,7 @@ function updateFielder(fielder)
|
|||
if playerIsOn(C.Sides.defense) then
|
||||
local throwFly = readThrow()
|
||||
if throwFly then
|
||||
buttonControlledThrow(fielders.pitcher, throwFly)
|
||||
buttonControlledThrow(Field.fielders.pitcher, throwFly)
|
||||
end
|
||||
else
|
||||
updateNpcFielder(fielder, outedSomeRunner)
|
||||
|
@ -586,22 +515,19 @@ function updateRunner(runner, runnerIndex, appliedSpeed)
|
|||
return prevX ~= runner.x or prevY ~= runner.y
|
||||
end
|
||||
|
||||
---@type number
|
||||
local batAngleDeg
|
||||
|
||||
function nextBatter()
|
||||
batter = nil
|
||||
playdate.timer.new(2000, function()
|
||||
pitchTracker:reset()
|
||||
if not batter then
|
||||
batter = newRunner()
|
||||
batter = utils.newRunner(runners)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function walk()
|
||||
announcer:say("Walk!")
|
||||
fielders.first.target = C.Bases[C.First]
|
||||
Field.fielders.first.target = C.Bases[C.First]
|
||||
batter.nextBase = C.Bases[C.First]
|
||||
batter.prevBase = C.Bases[C.Home]
|
||||
offenseMode = C.Offense.walking
|
||||
|
@ -653,14 +579,14 @@ function updateBatting(batDeg, batSpeed)
|
|||
local hitBallScaler = gfx.animator.new(2000, 9 + (mult * mult * 0.5), C.SmallestBallRadius, utils.easingHill)
|
||||
throwBall(ballDestX, ballDestY, playdate.easingFunctions.outQuint, 2000, nil, hitBallScaler)
|
||||
|
||||
fielders.first.target = C.Bases[C.First]
|
||||
Field.fielders.first.target = C.Bases[C.First]
|
||||
batter.nextBase = C.Bases[C.First]
|
||||
batter.prevBase = C.Bases[C.Home]
|
||||
updateForcedRunners()
|
||||
batter.forcedTo = C.Bases[C.First]
|
||||
batter = nil -- Demote batter to a mere runner
|
||||
|
||||
local chasingFielder = utils.getNearestOf(fielders, ballDestX, ballDestY)
|
||||
local chasingFielder = utils.getNearestOf(Field.fielders, ballDestX, ballDestY)
|
||||
chasingFielder.target = { x = ballDestX, y = ballDestY }
|
||||
end
|
||||
end
|
||||
|
@ -721,10 +647,12 @@ function updateGameState()
|
|||
if ball.heldBy then
|
||||
ball.x = ball.heldBy.x
|
||||
ball.y = ball.heldBy.y
|
||||
ball.size = C.SmallestBallRadius
|
||||
else
|
||||
ball.x = ballAnimatorX:currentValue()
|
||||
ball.z = ballFloatAnimator:currentValue()
|
||||
ball.y = ballAnimatorY:currentValue() + ball.z
|
||||
ball.size = ballSizeAnimator:currentValue()
|
||||
end
|
||||
|
||||
local playerOnOffense, playerOnDefense = playerIsOn(C.Sides.offense)
|
||||
|
@ -741,7 +669,7 @@ function updateGameState()
|
|||
pitchTracker.recordedPitchX = ball.x
|
||||
end
|
||||
|
||||
local pitcher = fielders.pitcher
|
||||
local pitcher = Field.fielders.pitcher
|
||||
if utils.distanceBetween(pitcher.x, pitcher.y, C.PitchStartX, C.PitchStartY) < C.BaseHitbox then
|
||||
secondsSincePitchAllowed = secondsSincePitchAllowed + deltaSeconds
|
||||
end
|
||||
|
@ -787,12 +715,12 @@ function updateGameState()
|
|||
secondsSinceLastRunnerMove = 0
|
||||
else
|
||||
secondsSinceLastRunnerMove = secondsSinceLastRunnerMove + deltaSeconds
|
||||
if secondsSinceLastRunnerMove > ResetFieldersAfterSeconds then
|
||||
if secondsSinceLastRunnerMove > C.ResetFieldersAfterSeconds then
|
||||
throwBall(C.PitchStartX, C.PitchStartY, playdate.easingFunctions.linear, nil, true)
|
||||
resetFielderPositions()
|
||||
Field:resetFielderPositions()
|
||||
offenseMode = C.Offense.batting
|
||||
if not batter then
|
||||
batter = newRunner()
|
||||
batter = utils.newRunner(runners)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -803,7 +731,7 @@ function updateGameState()
|
|||
end
|
||||
end
|
||||
|
||||
for _, fielder in pairs(fielders) do
|
||||
for _, fielder in pairs(Field.fielders) do
|
||||
updateFielder(fielder)
|
||||
end
|
||||
walkAwayOutRunners()
|
||||
|
@ -817,17 +745,14 @@ function playdate.update()
|
|||
gfx.clear()
|
||||
gfx.setColor(gfx.kColorBlack)
|
||||
|
||||
local offsetX, offsetY = 0, 0
|
||||
if ball.x < C.BallOffscreen then
|
||||
offsetX, offsetY = getDrawOffset(C.Screen.W, C.Screen.H, ball.x, ball.y)
|
||||
gfx.setDrawOffset(offsetX, offsetY)
|
||||
end
|
||||
local offsetX, offsetY = getDrawOffset(ball.x, ball.y)
|
||||
gfx.setDrawOffset(offsetX, offsetY)
|
||||
|
||||
GrassBackground:draw(-400, -240)
|
||||
|
||||
local fielderDanceHeight = FielderDanceAnimator:currentValue()
|
||||
local ballIsHeld = false
|
||||
for _, fielder in pairs(fielders) do
|
||||
for _, fielder in pairs(Field.fielders) do
|
||||
ballIsHeld = drawFielder(ball, fielder.x, fielder.y + fielderDanceHeight) or ballIsHeld
|
||||
end
|
||||
|
||||
|
@ -853,6 +778,7 @@ function playdate.update()
|
|||
PlayerImageBlipper:draw(false, runner.x, runner.y)
|
||||
end
|
||||
end
|
||||
|
||||
for _, runner in pairs(outRunners) do
|
||||
PlayerFrown:draw(runner.x, runner.y)
|
||||
end
|
||||
|
@ -880,7 +806,7 @@ function init()
|
|||
playdate.display.setRefreshRate(50)
|
||||
gfx.setBackgroundColor(gfx.kColorWhite)
|
||||
playdate.setMenuImage(gfx.image.new("images/game/menu-image.png"))
|
||||
resetFielderPositions(teams.home.benchPosition)
|
||||
Field:resetFielderPositions(teams.home.benchPosition)
|
||||
playdate.getSystemMenu():addMenuItem("Restart game", function() end) -- TODO?
|
||||
|
||||
playdate.timer.new(2000, function()
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
-- selene: allow(unscoped_variables)
|
||||
utils = {}
|
||||
|
||||
--- @alias XYPair {
|
||||
--- x: number,
|
||||
--- y: number,
|
||||
--- }
|
||||
|
||||
local sqrt <const> = math.sqrt
|
||||
|
||||
function utils.easingHill(t, b, c, d)
|
||||
c = c + 0.0 -- convert to float to prevent integer overflow
|
||||
t = t / d
|
||||
|
@ -9,10 +16,18 @@ function utils.easingHill(t, b, c, d)
|
|||
return (c * t) + b
|
||||
end
|
||||
|
||||
--- @alias XYPair {
|
||||
--- x: number,
|
||||
--- y: number,
|
||||
--- }
|
||||
--- Build an "animator" whose `:currentValue()` always returns the given value.
|
||||
--- Essentially an "empty object" pattern for initial object positions.
|
||||
---@param value number
|
||||
---@return PseudoAnimator
|
||||
function utils.staticAnimator(value)
|
||||
return {
|
||||
currentValue = function(_)
|
||||
return value
|
||||
end,
|
||||
reset = function(_) end
|
||||
}
|
||||
end
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
|
@ -84,7 +99,7 @@ end
|
|||
function utils.distanceBetween(x1, y1, x2, y2)
|
||||
local x = x1 - x2
|
||||
local y = y1 - y2
|
||||
return math.sqrt((x * x) + (y * y)), x, y
|
||||
return sqrt((x * x) + (y * y)), x, y
|
||||
end
|
||||
|
||||
---@return number distance, number x, number y, number z
|
||||
|
@ -92,7 +107,20 @@ function utils.distanceBetweenZ(x1, y1, z1, x2, y2, z2)
|
|||
local x = x1 - x2
|
||||
local y = y1 - y2
|
||||
local z = z1 - z2
|
||||
return math.sqrt((x * x) + (y * y) + (z * z)), x, y, z
|
||||
return sqrt((x * x) + (y * y) + (z * z)), x, y, z
|
||||
end
|
||||
|
||||
---@return Runner
|
||||
function utils.newRunner(runners)
|
||||
local new = {
|
||||
x = C.RightHandedBattersBox.x - 60,
|
||||
y = C.RightHandedBattersBox.y + 60,
|
||||
nextBase = C.RightHandedBattersBox,
|
||||
prevBase = nil,
|
||||
forcedTo = C.Bases[C.First],
|
||||
}
|
||||
runners[#runners + 1] = new
|
||||
return new
|
||||
end
|
||||
|
||||
--- Returns true only if the point is below the given line, within the x bounds of said line, and above the bottomBound
|
||||
|
|
Loading…
Reference in New Issue