Files
Genarrative/src/components/match3d-runtime/match3dHotspot.test.ts
T
kdletters 387a1c26e3 完成全量检查整改
清理已跟踪原始日志与个人本地配置
修复前后端有效门禁、测试和构建问题
补齐生产 Jenkins、SpacetimeDB 本地命令与文档约束
收紧图片编辑器状态、附件与媒体引用测试
排除已下线旧创作入口测试并清理 warning
2026-07-17 16:56:46 +08:00

125 lines
3.2 KiB
TypeScript

import { expect, test } from 'vitest';
import type { Match3DRunSnapshot } from '../../../packages/shared/src/contracts/match3dRuntime';
import {
findMatch3DHitItem,
isPointInsideMatch3DItemAlphaHotspot,
type Match3DResolvedImageSourceEntry,
resolveMatch3DItemSizeScale,
} from './match3dHotspot';
import { resolveRenderableItemFrame } from './match3dRuntimePresentation';
function buildMatch3DHotspotRun(): Match3DRunSnapshot {
return {
runId: 'hotspot-run',
profileId: 'hotspot-profile',
status: 'Running',
snapshotVersion: 1,
startedAtMs: 1,
durationLimitMs: 600_000,
remainingMs: 600_000,
clearCount: 1,
totalItemCount: 1,
clearedItemCount: 0,
traySlots: Array.from({ length: 7 }, (_, slotIndex) => ({ slotIndex })),
items: [
{
clickable: true,
itemInstanceId: 'alpha-hotspot-item',
itemTypeId: 'match3d-type-01',
visualKey: 'block-red-2x2',
x: 0.5,
y: 0.5,
radius: 0.1,
layer: 1,
state: 'InBoard',
},
],
};
}
test('透明像素不作为抓大鹅物品点击热区', () => {
const run = buildMatch3DHotspotRun();
const item = run.items[0]!;
const mask = {
width: 4,
height: 4,
alpha: new Uint8ClampedArray([
0, 0, 0, 0,
0, 255, 255, 0,
0, 255, 255, 0,
0, 0, 0, 0,
]),
};
const imageSourceEntriesByType = new Map<string, Match3DResolvedImageSourceEntry[]>([
[
'match3d-type-01',
[
{
source: '/generated-match3d-assets/item-01.png',
resolvedSource: 'https://oss.example.com/item-01.png',
},
],
],
]);
const alphaHitMasks = new Map([
['/generated-match3d-assets/item-01.png', mask],
]);
const itemSizeByType = new Map([['match3d-type-01', '大' as const]]);
const frame = resolveRenderableItemFrame(item);
expect(
findMatch3DHitItem(run, frame.x - frame.radius * 0.6, 0.5, {
alphaHitMasks,
imageSourceEntriesByType,
itemSizeByType,
}),
).toBeUndefined();
expect(
findMatch3DHitItem(run, 0.5, 0.5, {
alphaHitMasks,
imageSourceEntriesByType,
itemSizeByType,
})?.itemInstanceId,
).toBe('alpha-hotspot-item');
});
test('小尺寸物品只在缩放后的非透明主体内命中', () => {
const item = buildMatch3DHotspotRun().items[0]!;
const mask = {
width: 2,
height: 2,
alpha: new Uint8ClampedArray([255, 255, 255, 255]),
};
expect(
isPointInsideMatch3DItemAlphaHotspot({
item,
pointX: 0.5,
pointY: 0.5,
mask,
itemSize: '小',
}),
).toBe(true);
expect(
isPointInsideMatch3DItemAlphaHotspot({
item,
pointX: 0.38,
pointY: 0.5,
mask,
itemSize: '小',
}),
).toBe(false);
});
test('抓大鹅生成物品大和中也会做一定程度缩小', () => {
expect(resolveMatch3DItemSizeScale('大')).toBeLessThan(1);
expect(resolveMatch3DItemSizeScale('中')).toBeLessThan(0.78);
expect(resolveMatch3DItemSizeScale('大')).toBeGreaterThan(
resolveMatch3DItemSizeScale('中'),
);
expect(resolveMatch3DItemSizeScale('中')).toBeGreaterThan(
resolveMatch3DItemSizeScale('小'),
);
});