Add minimap.

Some other small refactors.
This commit is contained in:
Sage Vaillancourt 2025-02-06 13:34:03 -05:00
parent eb28a628f2
commit 4fc49d3631
3 changed files with 72 additions and 53 deletions

BIN
src/images/game/minimap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -54,6 +54,7 @@ local BootTune <const> = playdate.sound.sampleplayer.new("sounds/boot-tune.wav")
local TinnyBackground <const> = playdate.sound.sampleplayer.new("sounds/tinny-background.wav") local TinnyBackground <const> = playdate.sound.sampleplayer.new("sounds/tinny-background.wav")
local BatCrackSound <const> = playdate.sound.sampleplayer.new("sounds/bat-crack-reverb.wav") local BatCrackSound <const> = playdate.sound.sampleplayer.new("sounds/bat-crack-reverb.wav")
local GrassBackground <const> = gfx.image.new("images/game/grass.png") --[[@as pd_image]] local GrassBackground <const> = gfx.image.new("images/game/grass.png") --[[@as pd_image]]
local Minimap <const> = gfx.image.new("images/game/minimap.png") --[[@as pd_image]]
local PlayerFrown <const> = gfx.image.new("images/game/player-frown.png") --[[@as pd_image]] local PlayerFrown <const> = gfx.image.new("images/game/player-frown.png") --[[@as pd_image]]
local PlayerSmile <const> = gfx.image.new("images/game/player.png") --[[@as pd_image]] local PlayerSmile <const> = gfx.image.new("images/game/player.png") --[[@as pd_image]]
local PlayerBack <const> = gfx.image.new("images/game/player-back.png") --[[@as pd_image]] local PlayerBack <const> = gfx.image.new("images/game/player-back.png") --[[@as pd_image]]
@ -327,7 +328,7 @@ function pitch(pitchFlyTimeMs, pitchTypeIndex)
catcherThrownBall = false catcherThrownBall = false
offenseMode = Offense.batting offenseMode = Offense.batting
local current = Pitches[pitchTypeIndex or math.random(#Pitches)] local current = Pitches[pitchTypeIndex]
ballAnimatorX = current.x ballAnimatorX = current.x
ballAnimatorY = current.y or Pitches[1].y ballAnimatorY = current.y or Pitches[1].y
@ -355,13 +356,9 @@ local BaseHitbox = 10
---@param y number ---@param y number
---@return Base | nil ---@return Base | nil
function isTouchingBase(x, y) function isTouchingBase(x, y)
for _, base in ipairs(Bases) do return utils.first(Bases, function(base)
if utils.distanceBetween(x, y, base.x, base.y) < BaseHitbox then return utils.distanceBetween(x, y, base.x, base.y) < BaseHitbox
return base end)
end
end
return nil
end end
local BallCatchHitbox = 3 local BallCatchHitbox = 3
@ -377,19 +374,16 @@ end
---@param base Base ---@param base Base
---@return Runner | nil ---@return Runner | nil
function getRunnerTargeting(base) function getRunnerWithNextBase(base)
for _, runner in pairs(runners) do return utils.first(runners, function(runner)
if runner.nextBase == base then return runner.nextBase == base
return runner end)
end
end
return nil
end end
function updateForcedRunners() function updateForcedRunners()
local stillForced = true local stillForced = true
for _, base in ipairs(Bases) do for _, base in ipairs(Bases) do
local runnerTargetingBase = getRunnerTargeting(base) local runnerTargetingBase = getRunnerWithNextBase(base)
if runnerTargetingBase then if runnerTargetingBase then
if stillForced then if stillForced then
runnerTargetingBase.forcedTo = base runnerTargetingBase.forcedTo = base
@ -453,7 +447,7 @@ end
function getForcedOutTargets() function getForcedOutTargets()
local targets = {} local targets = {}
for _, base in ipairs(Bases) do for _, base in ipairs(Bases) do
local runnerTargetingBase = getRunnerTargeting(base) local runnerTargetingBase = getRunnerWithNextBase(base)
if runnerTargetingBase then if runnerTargetingBase then
targets[#targets + 1] = base targets[#targets + 1] = base
else else
@ -490,7 +484,6 @@ function getNextOutTarget()
end end
local baseCloseToStrandedRunner = getBaseOfStrandedRunner() local baseCloseToStrandedRunner = getBaseOfStrandedRunner()
-- TODO: If another fielder is closer, throw it to them, instead
if baseCloseToStrandedRunner then if baseCloseToStrandedRunner then
return baseCloseToStrandedRunner.x, baseCloseToStrandedRunner.y return baseCloseToStrandedRunner.x, baseCloseToStrandedRunner.y
end end
@ -510,28 +503,10 @@ function tryToMakeAnOut(fielder)
end end
end end
--- Push the given obect at the given speed toward a target. Speed should be pre-multiplied by the frame's delta time.
--- Stops when within 1. Returns true only if the object did actually move.
---@param mover { x: number, y: number }
---@param speed number
---@param target { x: number, y: number }
---@return boolean
function moveAtSpeed(mover, speed, target)
local x, y, distance = utils.normalizeVector(mover.x, mover.y, target.x, target.y)
if distance > 1 then
mover.x = mover.x - (x * speed)
mover.y = mover.y - (y * speed)
return true
end
return false
end
---@param fielder Fielder ---@param fielder Fielder
function updateFielder(fielder) function updateFielder(fielder)
if fielder.target ~= nil then if fielder.target ~= nil then
if not moveAtSpeed(fielder, fielder.speed * deltaSeconds, fielder.target) then if not utils.moveAtSpeed(fielder, fielder.speed * deltaSeconds, fielder.target) then
fielder.target = nil fielder.target = nil
end end
end end
@ -540,7 +515,6 @@ function updateFielder(fielder)
return return
end end
-- TODO: Check for double-plays or other available outs.
local touchedBase = isTouchingBase(fielder.x, fielder.y) local touchedBase = isTouchingBase(fielder.x, fielder.y)
for i, runner in pairs(runners) do for i, runner in pairs(runners) do
local runnerOnBase = isTouchingBase(runner.x, runner.y) local runnerOnBase = isTouchingBase(runner.x, runner.y)
@ -570,7 +544,7 @@ function updateFielders()
end end
-- if offenseMode == Offense.batting then -- if offenseMode == Offense.batting then
-- moveAtSpeed( -- utils.moveAtSpeed(
-- fielders.catcher, -- fielders.catcher,
-- fielders.catcher.speed * 2 * deltaSeconds, -- fielders.catcher.speed * 2 * deltaSeconds,
-- { x = math.min(Center.x + 15, ball.x), y = fielders.catcher.y } -- { x = math.min(Center.x + 15, ball.x), y = fielders.catcher.y }
@ -623,7 +597,6 @@ function updateRunner(runner, runnerIndex, appliedSpeed)
end end
end end
-- TODO: Also move if forced to 😅
local autoRun = (nearestBaseDistance > 40 or runner.forcedTo) and mult * autoRunSpeed local autoRun = (nearestBaseDistance > 40 or runner.forcedTo) and mult * autoRunSpeed
or nearestBaseDistance < 5 and 0 or nearestBaseDistance < 5 and 0
or (nearestBase == runner.nextBase and autoRunSpeed or -1 * autoRunSpeed) or (nearestBase == runner.nextBase and autoRunSpeed or -1 * autoRunSpeed)
@ -698,16 +671,14 @@ end
function updateRunning(appliedSpeed) function updateRunning(appliedSpeed)
ball.size = ballSizeAnimator:currentValue() ball.size = ballSizeAnimator:currentValue()
local nonBatterRunners = utils.filter(runners, function(runner)
return runner ~= batter
end)
local runnerMoved = false local runnerMoved = false
-- TODO: Filter for the runner closest to the currently-held direction button -- TODO: Filter for the runner closest to the currently-held direction button
for runnerIndex, runner in ipairs(nonBatterRunners) do for runnerIndex, runner in ipairs(runners) do
if runner ~= batter then
runnerMoved = updateRunner(runner, runnerIndex, appliedSpeed) or runnerMoved runnerMoved = updateRunner(runner, runnerIndex, appliedSpeed) or runnerMoved
end end
end
return runnerMoved return runnerMoved
end end
@ -768,7 +739,7 @@ function buttonControlledThrow(thrower, throwFlyMs, forbidThrowHome)
if playdate.buttonIsPressed(playdate.kButtonLeft) then if playdate.buttonIsPressed(playdate.kButtonLeft) then
targetBase = Bases[Third] targetBase = Bases[Third]
elseif playdate.buttonIsPressed(playdate.kButtonUp) then elseif playdate.buttonIsPressed(playdate.kButtonUp) then
targetBase = Bases[Second] -- TODO - or shortstop - whoever's closer targetBase = Bases[Second]
elseif playdate.buttonIsPressed(playdate.kButtonRight) then elseif playdate.buttonIsPressed(playdate.kButtonRight) then
targetBase = Bases[First] targetBase = Bases[First]
elseif not forbidThrowHome and playdate.buttonIsPressed(playdate.kButtonDown) then elseif not forbidThrowHome and playdate.buttonIsPressed(playdate.kButtonDown) then
@ -820,7 +791,7 @@ function updateGameState()
if secondsSincePitchAllowed > PitchAfterSeconds then if secondsSincePitchAllowed > PitchAfterSeconds then
if playerOnOffense then if playerOnOffense then
pitch(PitchFlyMs) pitch(PitchFlyMs, math.random(#Pitches))
else else
local throwFly = readThrow() local throwFly = readThrow()
if throwFly and not buttonControlledThrow(fielders.pitcher, throwFly, true) then if throwFly and not buttonControlledThrow(fielders.pitcher, throwFly, true) then
@ -864,8 +835,25 @@ function updateGameState()
walkAwayOutRunners() walkAwayOutRunners()
end end
-- TODO local MinimapSizeX, MinimapSizeY <const> = Minimap:getSize()
function drawMinimap() end local MinimapPosX, MinimapPosY = Screen.W - MinimapSizeX, Screen.H - MinimapSizeY
local FieldHeight <const> = Bases[Home].y - Bases[Second].y
local MinimapMultX <const> = 0.75 * MinimapSizeX / Screen.W
local MinimapOffsetX <const> = MinimapPosX + 5
local MinimapMultY <const> = 0.70 * MinimapSizeY / FieldHeight
local MinimapOffsetY <const> = MinimapPosY - 15
function drawMinimap()
Minimap:draw(MinimapPosX, MinimapPosY)
gfx.setColor(gfx.kColorBlack)
for _, runner in pairs(runners) do
local x = (MinimapMultX * runner.x) + MinimapOffsetX
local y = (MinimapMultY * runner.y) + MinimapOffsetY
gfx.fillRect(x, y, 8, 8)
end
end
---@param fielder Fielder ---@param fielder Fielder
---@return boolean isHoldingBall ---@return boolean isHoldingBall
@ -916,7 +904,7 @@ function playdate.update()
playdate.ui.crankIndicator:draw() playdate.ui.crankIndicator:draw()
end end
-- TODO? Change blip speed depending on runner speed? -- TODO? Scale sprites down as y increases
for _, runner in pairs(runners) do for _, runner in pairs(runners) do
if runner == batter then if runner == batter then
if batAngleDeg > 50 and batAngleDeg < 200 then if batAngleDeg > 50 and batAngleDeg < 200 then
@ -925,7 +913,7 @@ function playdate.update()
PlayerSmile:draw(runner.x, runner.y) PlayerSmile:draw(runner.x, runner.y)
end end
else else
-- TODO? Scale sprites down as y increases -- TODO? Change blip speed depending on runner speed?
PlayerImageBlipper:draw(false, runner.x, runner.y) PlayerImageBlipper:draw(false, runner.x, runner.y)
end end
end end

View File

@ -47,6 +47,24 @@ function utils.normalizeVector(x1, y1, x2, y2)
return x / distance, y / distance, distance return x / distance, y / distance, distance
end end
--- Push the given obect at the given speed toward a target. Speed should be pre-multiplied by the frame's delta time.
--- Stops when within 1. Returns true only if the object did actually move.
---@param mover { x: number, y: number }
---@param speed number
---@param target { x: number, y: number }
---@return boolean
function utils.moveAtSpeed(mover, speed, target)
local x, y, distance = utils.normalizeVector(mover.x, mover.y, target.x, target.y)
if distance > 1 then
mover.x = mover.x - (x * speed)
mover.y = mover.y - (y * speed)
return true
end
return false
end
---@generic T ---@generic T
---@param array T[] ---@param array T[]
---@param condition fun(T): boolean ---@param condition fun(T): boolean
@ -61,6 +79,19 @@ function utils.filter(array, condition)
return newArray return newArray
end end
---@generic T
---@param array T[]
---@param condition fun(T): boolean
---@return T | nil
function utils.first(array, condition)
for _, element in ipairs(array) do
if condition(element) then
return element
end
end
return nil
end
---@return number distance, number x, number y ---@return number distance, number x, number y
function utils.distanceBetween(x1, y1, x2, y2) function utils.distanceBetween(x1, y1, x2, y2)
local x = x1 - x2 local x = x1 - x2
@ -102,7 +133,7 @@ end
---@param array T[] ---@param array T[]
---@param x number ---@param x number
---@param y number ---@param y number
---@return T,number|nil ---@return T nearest,number |nil distance
function utils.getNearestOf(array, x, y, extraCondition) function utils.getNearestOf(array, x, y, extraCondition)
local nearest, nearestDistance = nil, nil local nearest, nearestDistance = nil, nil
for _, element in pairs(array) do for _, element in pairs(array) do