135 lines
3.5 KiB
TypeScript
135 lines
3.5 KiB
TypeScript
import { describe, expect, test } from 'vitest';
|
|
|
|
import {
|
|
buildMatch3DItemSpritesheetViewRegions,
|
|
detectMatch3DSpritesheetRegions,
|
|
} from './match3dSpritesheetParser';
|
|
|
|
describe('match3dSpritesheetParser', () => {
|
|
test('按透明像素连通域检测素材并按从上到下从左到右排序', () => {
|
|
const width = 12;
|
|
const height = 10;
|
|
const alpha = new Uint8ClampedArray(width * height);
|
|
const paint = (x0: number, y0: number, x1: number, y1: number) => {
|
|
for (let y = y0; y <= y1; y += 1) {
|
|
for (let x = x0; x <= x1; x += 1) {
|
|
alpha[y * width + x] = 255;
|
|
}
|
|
}
|
|
};
|
|
|
|
paint(8, 1, 10, 3);
|
|
paint(1, 1, 3, 2);
|
|
paint(5, 6, 7, 8);
|
|
|
|
const regions = detectMatch3DSpritesheetRegions({
|
|
alpha,
|
|
width,
|
|
height,
|
|
labels: ['返回', '设置', '移出'],
|
|
});
|
|
|
|
expect(regions).toEqual([
|
|
{ height: 2, label: '返回', width: 3, x: 1, y: 1 },
|
|
{ height: 3, label: '设置', width: 3, x: 8, y: 1 },
|
|
{ height: 3, label: '移出', width: 3, x: 5, y: 6 },
|
|
]);
|
|
});
|
|
|
|
test('同一行图标高度错位时仍按行内横向顺序映射标签', () => {
|
|
const width = 36;
|
|
const height = 24;
|
|
const alpha = new Uint8ClampedArray(width * height);
|
|
const paint = (x0: number, y0: number, x1: number, y1: number) => {
|
|
for (let y = y0; y <= y1; y += 1) {
|
|
for (let x = x0; x <= x1; x += 1) {
|
|
alpha[y * width + x] = 255;
|
|
}
|
|
}
|
|
};
|
|
|
|
paint(2, 1, 5, 4);
|
|
paint(12, 1, 15, 4);
|
|
paint(22, 1, 25, 4);
|
|
paint(2, 15, 5, 20);
|
|
paint(12, 13, 15, 18);
|
|
paint(22, 10, 25, 15);
|
|
|
|
const regions = detectMatch3DSpritesheetRegions({
|
|
alpha,
|
|
width,
|
|
height,
|
|
labels: ['返回', '设置', '方格', '移出', '凑齐', '打乱'],
|
|
});
|
|
|
|
expect(regions.map((region) => `${region.label}:${region.x}`)).toEqual([
|
|
'返回:2',
|
|
'设置:12',
|
|
'方格:22',
|
|
'移出:2',
|
|
'凑齐:12',
|
|
'打乱:22',
|
|
]);
|
|
});
|
|
|
|
test('忽略小噪点,只返回可用矩形素材', () => {
|
|
const width = 8;
|
|
const height = 8;
|
|
const alpha = new Uint8ClampedArray(width * height);
|
|
alpha[0] = 255;
|
|
for (let y = 2; y <= 5; y += 1) {
|
|
for (let x = 2; x <= 5; x += 1) {
|
|
alpha[y * width + x] = 255;
|
|
}
|
|
}
|
|
|
|
const regions = detectMatch3DSpritesheetRegions({
|
|
alpha,
|
|
width,
|
|
height,
|
|
labels: ['方格'],
|
|
minArea: 4,
|
|
});
|
|
|
|
expect(regions).toEqual([
|
|
{ height: 4, label: '方格', width: 4, x: 2, y: 2 },
|
|
]);
|
|
});
|
|
|
|
test('按10行10列图集顺序把每行两种物品拆成五视角', () => {
|
|
const regions = Array.from({ length: 100 }, (_, index) => ({
|
|
label: `素材${index + 1}`,
|
|
x: (index % 10) * 10,
|
|
y: Math.floor(index / 10) * 10,
|
|
width: 8,
|
|
height: 8,
|
|
}));
|
|
|
|
const grouped = buildMatch3DItemSpritesheetViewRegions(regions, [
|
|
'草莓',
|
|
'苹果',
|
|
'毛肚',
|
|
]);
|
|
|
|
expect(grouped).toHaveLength(20);
|
|
expect(grouped[0]).toEqual({
|
|
itemIndex: 0,
|
|
itemName: '草莓',
|
|
regions: regions.slice(0, 5).map((region, index) => ({
|
|
...region,
|
|
label: `草莓-形态${index + 1}`,
|
|
})),
|
|
});
|
|
expect(grouped[1]).toEqual({
|
|
itemIndex: 1,
|
|
itemName: '苹果',
|
|
regions: regions.slice(5, 10).map((region, index) => ({
|
|
...region,
|
|
label: `苹果-形态${index + 1}`,
|
|
})),
|
|
});
|
|
expect(grouped[2]?.itemName).toBe('毛肚');
|
|
expect(grouped[19]?.regions).toHaveLength(5);
|
|
});
|
|
});
|