Files
gen1recomp/tests/engine/npc_walk_cadence_bug1303.lua
T

97 lines
3.1 KiB
Lua

-- The walking-NPC animation cadence, which the port ran at half the cart's
-- rate (#1303). UpdateSpriteInWalkingAnimation advances one animation frame
-- every 4 fixed steps regardless of how long the whole cell takes
-- (engine/overworld/movement.asm:301), so a 32-frame NPC cell must show the
-- same two-pulse cadence Player:pose already shows across its own 16.
-- luajit tests/engine/npc_walk_cadence_bug1303.lua
package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.harness")
local check, eq = T.check, T.eq
love = require("tests.love_stub")
local NPC = require("src.world.NPC")
local DATA = {
sprites = {
SPRITE_TEST_NPC = { image = "fixture_npc.png", frames = 6, walker = true },
},
}
local function newNpc()
return NPC.new(DATA, "TEST_MAP", {
index = 1, x = 5, y = 5, sprite = "SPRITE_TEST_NPC", range = "ANY_DIR",
movement = "STAY",
})
end
-- ---- the pure cadence: two walk pulses across one 32-frame NPC step ------
do
local npc = newNpc()
npc.moving = true
local phases = {}
for clock = 0, 31 do
npc.animClock = clock
phases[clock] = npc:walkPhase()
end
local risingEdges = 0
for clock = 1, 31 do
if phases[clock] == 1 and phases[clock - 1] == 0 then
risingEdges = risingEdges + 1
end
end
eq(risingEdges, 2, "a 32-frame NPC cell shows two walk pulses, not one")
eq(phases[0], 0, "frame 0 stands")
eq(phases[4], 1, "frame 4 opens the first walk pulse")
eq(phases[11], 1, "frame 11 is still the first pulse")
eq(phases[12], 0, "frame 12 closes it back to standing")
eq(phases[20], 1, "frame 20 opens the second walk pulse")
eq(phases[27], 1, "frame 27 is still the second pulse")
eq(phases[28], 0, "frame 28 closes the cycle back to standing")
end
-- ---- the flip half-cycle: one flip per 16-frame half, not per whole cell -
do
local npc = newNpc()
npc.moving = true
npc.animClock = 0
local _, _, _, _, _, flip0 = npc:pose()
npc.animClock = 15
local _, _, _, _, _, flip15 = npc:pose()
npc.animClock = 16
local _, _, _, _, _, flip16 = npc:pose()
npc.animClock = 31
local _, _, _, _, _, flip31 = npc:pose()
check(not flip0, "the first half of the cell is unflipped")
check(not flip15, "still unflipped just before frame 16")
check(flip16, "frame 16 flips, matching Player:pose's own half-cycle")
check(flip31, "and stays flipped through the second half")
end
-- ---- standing keeps the externally-written flip (Pikachu idle contract) --
do
local npc = newNpc()
npc.moving = false
npc.stepFlip = true
local _, _, _, _, phase, flip = npc:pose()
eq(phase, 0, "a standing NPC has no walk phase")
check(flip, "and pose() reads stepFlip back exactly, not the moving formula")
end
-- ---- the wiring: NPC:update advances animClock alongside progress -------
do
local npc = newNpc()
npc.facing = "down"
npc.moving = true
npc.targetX, npc.targetY = npc.cellX, npc.cellY + 1
local map = {}
for i = 1, 16 do
npc:update(map, {})
eq(npc.animClock, i, "animClock ticks once per update, step " .. i)
end
check(npc.moving, "still mid-cell at 16 of the 32 ticks")
end
T.finish("npc walk cadence bug1303")