Files
kidgo/tools/map-test.mjs
T
2026-10-22 21:42:43 +08:00

72 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 回归测试:多面地图的跨面传送门 + 存档点带面 + 内置关卡兼容
const handlers = {};
const addL = (t, fn) => { (handlers[t] = handlers[t] || []).push(fn); };
globalThis.addEventListener = addL;
globalThis.window = { addEventListener: addL };
const key = (type, code) => (handlers[type] || []).forEach(fn => fn({ code, preventDefault() { }, repeat: false }));
const { Level } = await import('../js/level.js');
const { Player } = await import('../js/player.js');
const { Input } = await import('../js/input.js');
const W = 20, TILE = 32;
let fail = 0;
const err = m => { console.log(' ✗ ' + m); fail++; };
const ok = m => console.log(' ✓ ' + m);
// 两面临门地图:A 面门 col5 指向 B 面门;B 面门 col10 指回 A 面门
const gridA = ['#'.repeat(W), '#' + 'S' + '.'.repeat(W - 3) + '#', '#' + '.'.repeat(4) + 'W' + '.'.repeat(W - 6) + '#', '#'.repeat(W), '#X' + '.'.repeat(W - 3) + '#', '#'.repeat(W), '#'.repeat(W), '#'.repeat(W), '#'.repeat(W), '#'.repeat(W)];
const gridB = ['#'.repeat(W), '#' + 'S' + '.'.repeat(W - 3) + '#', '#' + '.'.repeat(9) + 'W' + '.'.repeat(W - 11) + '#', '#'.repeat(W), '#X' + '.'.repeat(W - 3) + '#', '#'.repeat(W), '#'.repeat(W), '#'.repeat(W), '#'.repeat(W), '#'.repeat(W)];
const doorA = { id: 1, tx: 5, ty: 2, to: { face: 1, door: 1 } };
const doorB = { id: 1, tx: 10, ty: 2, to: { face: 0, door: 1 } };
const L0 = new Level({ name: 'A', type: 'custom', width: W, grid: gridA, doors: [doorA] }); L0.faceIndex = 0;
const L1 = new Level({ name: 'B', type: 'custom', width: W, grid: gridB, doors: [doorB] }); L1.faceIndex = 1;
// 1) 门目标正确挂接
{
const w0 = L0.entities.find(e => e.type === 'warp');
const w1 = L1.entities.find(e => e.type === 'warp');
if (!w0 || !w1) err('门实体未生成');
else {
if (w0.to && w0.to.face === 1 && w0.to.door === 1 && w0.doorId === 1) ok('A 面门挂上跨面目标 {face:1,door:1}');
else err('A 面门目标错误: ' + JSON.stringify(w0.to));
if (w1.to && w1.to.face === 0 && w1.to.door === 1 && w1.doorId === 1) ok('B 面门挂上跨面目标 {face:0,door:1}');
else err('B 面门目标错误: ' + JSON.stringify(w1.to));
}
}
// 2) 踩门触发 onPortal 钩子(main 据此切面)
{
const P = new Player(L0);
let captured = null; P.onPortal = (e) => { captured = e; };
const w0 = L0.entities.find(e => e.type === 'warp');
P.x = w0.x; P.y = w0.y; P.vx = 0; P.vy = 0;
L0.update(1, P, null); P.update(1); Input.endFrame();
if (captured && captured.to && captured.to.face === 1) ok('踩到门触发 onPortal,目标面=1');
else err('踩门未触发跨面 onPortal');
}
// 3) 存档点带 faceIndex
{
const gridC = ['#'.repeat(W), '#' + 'S' + '.'.repeat(W - 3) + '#', '#' + 'G' + '.'.repeat(W - 3) + '#', '#X' + '.'.repeat(W - 3) + '#'];
const LC = new Level({ name: 'C', type: 'custom', width: W, grid: gridC, doors: [] }); LC.faceIndex = 2;
const P = new Player(LC);
const g = LC.entities.find(e => e.type === 'save');
P.x = g.x; P.y = g.y;
LC.update(1, P, null); P.update(1); Input.endFrame();
if (P.savePoint && P.savePoint.face === 2) ok('存档点记录 face=2');
else err('存档点未带 face,得到 ' + (P.savePoint && P.savePoint.face));
}
// 4) 兼容:无 doors 的内置风格关卡,门仍走原有 pair 逻辑(to 为 null)
{
const gridD = ['#'.repeat(W), '#' + 'S' + '.'.repeat(W - 3) + '#', '#' + '.'.repeat(4) + 'W' + '.'.repeat(W - 6) + '#', '#'.repeat(W), '#' + '.'.repeat(4) + 'W' + '.'.repeat(W - 6) + '#', '#X' + '.'.repeat(W - 3) + '#'];
const LD = new Level({ name: 'D', type: 'jump', width: W, grid: gridD });
const ws = LD.entities.filter(e => e.type === 'warp');
if (ws.length === 2 && ws[0].to === null && ws[1].to === null) ok('无 doors 时门 to=null(走原有 pair 逻辑,不退化)');
else err('无 doors 时门目标异常: ' + JSON.stringify(ws.map(w => w.to)));
}
console.log(fail ? `\n❌ ${fail} 项失败` : '\n✅ 多面地图/传送门 全部通过');
process.exit(fail ? 1 : 0);