mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 05:32:07 -04:00
203 lines
7.6 KiB
Lua
203 lines
7.6 KiB
Lua
-- tests/game3_elevation_oam_priority_test.lua
|
|
-- Tests for Elevation tracking, elevation 0/15 preservation, and row-interleaved OAM priority rendering.
|
|
|
|
local Map = require("src.core.game3.map")
|
|
local Objects = require("src.core.game3.objects")
|
|
local Player = require("src.core.game3.player")
|
|
local Collision = require("src.core.game3.collision")
|
|
local FieldView = require("src.core.game3.field_view")
|
|
|
|
local CELL = 16
|
|
|
|
local function assert_eq(desc, actual, expected)
|
|
if actual == expected then
|
|
print(string.format("[ok] %s", desc))
|
|
else
|
|
error(string.format("[FAIL] %s: expected %s, got %s", desc, tostring(expected), tostring(actual)))
|
|
end
|
|
end
|
|
|
|
local function assert_true(desc, val)
|
|
assert_eq(desc, not not val, true)
|
|
end
|
|
|
|
print("[test] 1. Elevation tracking and 0/15 preservation on Player movement")
|
|
do
|
|
local cellElevs = {
|
|
["10,10"] = 3, -- ground
|
|
["10,11"] = 4, -- bridge / elevated platform
|
|
["10,12"] = 15, -- special: preserve elevation
|
|
["10,13"] = 0, -- special: preserve elevation
|
|
["10,14"] = 1, -- surf / water
|
|
}
|
|
Collision.elevationAt = function(cx, cy)
|
|
return cellElevs[cx .. "," .. cy]
|
|
end
|
|
|
|
Player.reset(10, 10, "down")
|
|
assert_eq("Player initial elevation at (10,10) is 3", Player.elevation, 3)
|
|
|
|
-- Move onto bridge (elevation 4)
|
|
Player.targetX, Player.targetY = 10, 11
|
|
Player.moving = true
|
|
Player.cellX, Player.cellY = 10, 11
|
|
Player.px, Player.py = 10 * CELL, 11 * CELL
|
|
Player.moving = false
|
|
local curElev = Collision.elevationAt(Player.cellX, Player.cellY)
|
|
if curElev and curElev ~= 0 and curElev ~= 15 then Player.elevation = curElev end
|
|
assert_eq("Player elevation on bridge (10,11) is 4", Player.elevation, 4)
|
|
|
|
-- Move onto elevation 15 tile (should preserve 4)
|
|
Player.cellX, Player.cellY = 10, 12
|
|
local e15 = Collision.elevationAt(Player.cellX, Player.cellY)
|
|
if e15 and e15 ~= 0 and e15 ~= 15 then Player.elevation = e15 end
|
|
assert_eq("Player elevation on elevation 15 tile (10,12) preserved as 4", Player.elevation, 4)
|
|
|
|
-- Move onto elevation 0 tile (should preserve 4)
|
|
Player.cellX, Player.cellY = 10, 13
|
|
local e0 = Collision.elevationAt(Player.cellX, Player.cellY)
|
|
if e0 and e0 ~= 0 and e0 ~= 15 then Player.elevation = e0 end
|
|
assert_eq("Player elevation on elevation 0 tile (10,13) preserved as 4", Player.elevation, 4)
|
|
|
|
-- Move onto water (elevation 1)
|
|
Player.cellX, Player.cellY = 10, 14
|
|
local e1 = Collision.elevationAt(Player.cellX, Player.cellY)
|
|
if e1 and e1 ~= 0 and e1 ~= 15 then Player.elevation = e1 end
|
|
assert_eq("Player elevation on water (10,14) updated to 1", Player.elevation, 1)
|
|
end
|
|
|
|
print("[test] 2. EventObject elevation tracking on spawn and movement")
|
|
do
|
|
local eo = {
|
|
localId = 1,
|
|
def = { x = 5, y = 5, elevation = 0 },
|
|
cellX = 5,
|
|
cellY = 5,
|
|
targetX = 5,
|
|
targetY = 6,
|
|
}
|
|
Collision.elevationAt = function(cx, cy)
|
|
if cx == 5 and cy == 5 then return 3 end
|
|
if cx == 5 and cy == 6 then return 4 end
|
|
return 3
|
|
end
|
|
|
|
eo.elevation = (Collision.elevationAt and Collision.elevationAt(eo.cellX, eo.cellY)) or 0
|
|
assert_eq("EventObject initial elevation at (5,5) is 3", eo.elevation, 3)
|
|
|
|
-- Move to (5,6)
|
|
eo.cellX = eo.targetX
|
|
eo.cellY = eo.targetY
|
|
local curElev = Collision.elevationAt(eo.cellX, eo.cellY)
|
|
if curElev and curElev ~= 0 and curElev ~= 15 then eo.elevation = curElev end
|
|
assert_eq("EventObject elevation at (5,6) is updated to 4", eo.elevation, 4)
|
|
end
|
|
|
|
print("[test] 3. GBA OAM Priority vs Overhead Layer partitioning")
|
|
do
|
|
local ELEVATION_TO_PRIORITY = {
|
|
[0] = 2, [1] = 2, [2] = 2, [3] = 2,
|
|
[4] = 1, [5] = 2, [6] = 1, [7] = 2,
|
|
[8] = 1, [9] = 2, [10] = 1, [11] = 2,
|
|
[12] = 1, [13] = 0, [14] = 0, [15] = 2,
|
|
}
|
|
|
|
local actorPriority = function(a)
|
|
if a.kind == "player" then
|
|
if a.jumping or a.surfHopping or a.escalatorActive or a.specialAnimActive then
|
|
return 1
|
|
end
|
|
local elev = a.elevation or 3
|
|
return ELEVATION_TO_PRIORITY[elev] or 2
|
|
else
|
|
local elev = a.elevation or (a.obj and a.obj.elevation) or 3
|
|
return ELEVATION_TO_PRIORITY[elev] or 2
|
|
end
|
|
end
|
|
|
|
local drawLog = {}
|
|
local function simulateDraw(actors)
|
|
local underActors = {}
|
|
local overActors = {}
|
|
for _, a in ipairs(actors) do
|
|
a.priority = actorPriority(a)
|
|
if a.priority < 2 then
|
|
overActors[#overActors + 1] = a
|
|
else
|
|
underActors[#underActors + 1] = a
|
|
end
|
|
end
|
|
|
|
local function sortActors(a, b)
|
|
local ay = a.sortY or a.y
|
|
local by = b.sortY or b.y
|
|
if ay == by then return (a.i or 0) < (b.i or 0) end
|
|
return ay < by
|
|
end
|
|
table.sort(underActors, sortActors)
|
|
table.sort(overActors, sortActors)
|
|
|
|
drawLog = {}
|
|
-- 1. Draw underActors (OAM Priority >= 2)
|
|
for _, a in ipairs(underActors) do
|
|
drawLog[#drawLog + 1] = a.tag
|
|
end
|
|
-- 2. Draw Overhead layer (BG1, Priority 1)
|
|
drawLog[#drawLog + 1] = "OVERHEAD_BG1_LAYER"
|
|
-- 3. Draw overActors (OAM Priority < 2, e.g. elevation 4 cliff/bridge, jumping, escalator)
|
|
for _, a in ipairs(overActors) do
|
|
drawLog[#drawLog + 1] = a.tag
|
|
end
|
|
end
|
|
|
|
-- Scenario A: Nurse Joy behind desk (row 5) and Player on ground (row 6)
|
|
-- Both have ground elevation 3 -> Priority 2. Both drawn BEFORE overhead BG1 layer.
|
|
-- The overhead desk covers Nurse Joy; the overhead roof covers player legs.
|
|
local testActors = {
|
|
{ tag = "NURSE_JOY_ROW_5", elevation = 3, y = 80, sortY = 80, kind = "npc" },
|
|
{ tag = "PLAYER_ON_GROUND_ROW_6", elevation = 3, y = 96, sortY = 96, kind = "player" },
|
|
{ tag = "PLAYER_ON_CLIFF_ELEV_4", elevation = 4, y = 272, sortY = 272, kind = "player" },
|
|
{ tag = "NPC_IN_WATER_ELEV_1", elevation = 1, y = 256, sortY = 256, kind = "npc" },
|
|
}
|
|
|
|
simulateDraw(testActors)
|
|
|
|
print("Draw order result:")
|
|
for idx, entry in ipairs(drawLog) do
|
|
print(string.format(" [%d] %s", idx, entry))
|
|
end
|
|
|
|
assert_eq("Under-actor 1 is Nurse Joy (behind desk)", drawLog[1], "NURSE_JOY_ROW_5")
|
|
assert_eq("Under-actor 2 is Player on ground (behind roof)", drawLog[2], "PLAYER_ON_GROUND_ROW_6")
|
|
assert_eq("Under-actor 3 is NPC in water", drawLog[3], "NPC_IN_WATER_ELEV_1")
|
|
assert_eq("Step 4 is Overhead BG1 layer (covers Nurse Joy and player on ground)", drawLog[4], "OVERHEAD_BG1_LAYER")
|
|
assert_eq("Step 5 is Player on cliff (elevation 4, drawn ON TOP of overhead layer)", drawLog[5], "PLAYER_ON_CLIFF_ELEV_4")
|
|
end
|
|
|
|
print("[test] 4. Player priority override states (jumping, escalator, surf hopping)")
|
|
do
|
|
local ELEVATION_TO_PRIORITY = {
|
|
[0] = 2, [1] = 2, [2] = 2, [3] = 2,
|
|
[4] = 1, [5] = 2, [6] = 1, [7] = 2,
|
|
[8] = 1, [9] = 2, [10] = 1, [11] = 2,
|
|
[12] = 1, [13] = 0, [14] = 0, [15] = 2,
|
|
}
|
|
|
|
local computePlayerPriority = function(opts)
|
|
if opts.jumping or opts.surfHopping or opts.escalatorActive or opts.specialAnimActive then
|
|
return 1
|
|
end
|
|
local elev = opts.elevation or 3
|
|
return ELEVATION_TO_PRIORITY[elev] or 2
|
|
end
|
|
|
|
assert_eq("Jumping player has Priority 1 (above BG1)", computePlayerPriority({ jumping = true, elevation = 3 }), 1)
|
|
assert_eq("Escalator player has Priority 1 (above BG1)", computePlayerPriority({ escalatorActive = true, elevation = 3 }), 1)
|
|
assert_eq("Surf hopping player has Priority 1 (above BG1)", computePlayerPriority({ surfHopping = true, elevation = 1 }), 1)
|
|
assert_eq("Bridge player has Priority 1 (above BG1)", computePlayerPriority({ elevation = 4 }), 1)
|
|
assert_eq("Normal walking player with animation offsets has Priority 2 (under BG1)", computePlayerPriority({ elevation = 3, spriteYOffset = -8 }), 2)
|
|
assert_eq("Water surfing player has Priority 2 (under BG1)", computePlayerPriority({ elevation = 1 }), 2)
|
|
end
|
|
|
|
print("[test] ALL ELEVATION AND OAM CONDITIONAL PRIORITY TESTS PASSED!")
|