mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-16 16:21:30 +02:00
97 lines
3.1 KiB
Lua
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")
|