refactor: 收口 BangDream 卡牌 SD 缩略图规格
This commit is contained in:
parent
c26aeeb921
commit
e48ea5100a
@ -392,6 +392,7 @@ export interface TsuguHook {
|
||||
- 已新增 `render-blocks/list-difficulty-detail-spec.ts`,收口玩家难度详情列表的徽章宽度/字号/圆角、正文宽度/行高、项画布高度和通用列表行高/间距;`list-difficulty-detail.ts` 改为消费 spec,玩家详情里的已通关/Full Combo/All Perfect 难度详情绘制顺序和输出结构保持不变;`list-difficulty-detail-spec.spec.ts` 覆盖徽章参数、正文绘制参数、项布局和列表框架参数,本地 `/查玩家 26591455 jp` 图片 smoke 输出非空。
|
||||
- 已新增 `render-blocks/list-band-detail-spec.ts`,收口玩家详情乐队等级、舞台挑战达成情况和乐队编成等级列表的 Logo 缩放、正文宽度/行高、项画布、通用列表框架和 Rank 等级图片布局;`list-band-detail.ts` 改为消费 spec,玩家详情里的乐队详情绘制顺序、资源 repository 和输出结构保持不变;`list-band-detail-spec.spec.ts` 覆盖 Logo/正文参数、项布局、列表框架、Rank 画布/图片位置和等级图片 Rank ID 封顶,本地 `/查玩家 26591455 jp` 图片 smoke 输出非空。
|
||||
- 已新增 `render-blocks/list-character-detail-spec.ts`,收口玩家详情角色等级列表的头像缩放、正文宽度/行高、项画布和通用列表框架;`list-character-detail.ts` 改为消费 spec,玩家详情角色等级绘制顺序、角色数据读取和输出结构保持不变;`list-character-detail-spec.spec.ts` 覆盖头像/正文参数、项布局和列表框架参数,本地 `/查玩家 26591455 jp` 图片 smoke 输出非空。
|
||||
- 已新增 `render-blocks/list-card-sd-character-spec.ts`,收口卡牌详情演出缩略图的 SD 角色 sprite 裁切网格、列表缩放行高、字号和间距;`list-card-sd-character.ts` 改为消费 spec,素材加载、四帧裁切和列表绘制顺序保持不变;`list-card-sd-character-spec.spec.ts` 覆盖四帧裁切坐标、单帧裁切计算和列表规格,本地 `/查卡 472` 图片 smoke 输出非空。
|
||||
- smoke/Jenkins/远程调试卡点继续按已固化规则处理:同一卡点第二次尝试前必须改变可验证变量;Jenkins 查询 URL 含方括号时用 `curl -g` 或改查 Jenkins home;线上图片 smoke 必须查询 `commandId`、拉回图片、展示图片、查日志并清理本轮临时目录;PowerShell 双引号 here-string 中不要写 JS `${...}` 模板字面量,避免被 PowerShell 提前插值;smoke 没有真实图片落盘时必须失败。
|
||||
|
||||
### Phase 6:策略 policy 和时间/档线规则
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
export interface CardSdCharacterCropRect {
|
||||
sourceX: number;
|
||||
sourceY: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export const BANGDREAM_CARD_SD_CHARACTER_SPEC = {
|
||||
sprite: {
|
||||
columns: 2,
|
||||
rows: 2,
|
||||
cropOffsetY: 84,
|
||||
cropWidth: 400,
|
||||
cropHeight: 470,
|
||||
},
|
||||
list: {
|
||||
targetWidth: 190,
|
||||
spacing: 0,
|
||||
},
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* 计算卡牌 SD 角色 sprite 裁切区域。
|
||||
*
|
||||
* @param index - 第几个 SD 动作帧。
|
||||
*/
|
||||
export function getCardSdCharacterCropRect(
|
||||
index: number,
|
||||
): CardSdCharacterCropRect {
|
||||
const { columns, cropHeight, cropOffsetY, cropWidth } =
|
||||
BANGDREAM_CARD_SD_CHARACTER_SPEC.sprite;
|
||||
|
||||
return {
|
||||
sourceX: (index % columns) * cropWidth,
|
||||
sourceY: cropOffsetY + Math.floor(index / columns) * cropHeight,
|
||||
width: cropWidth,
|
||||
height: cropHeight,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成卡牌 SD 角色列表需要展示的全部裁切区域。
|
||||
*/
|
||||
export function getCardSdCharacterCropRects(): CardSdCharacterCropRect[] {
|
||||
const { columns, rows } = BANGDREAM_CARD_SD_CHARACTER_SPEC.sprite;
|
||||
|
||||
return Array.from({ length: columns * rows }, (_, index) =>
|
||||
getCardSdCharacterCropRect(index),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算卡牌 SD 角色列表展示行高。
|
||||
*/
|
||||
export function getCardSdCharacterListLineHeight() {
|
||||
const { cropHeight, cropWidth } = BANGDREAM_CARD_SD_CHARACTER_SPEC.sprite;
|
||||
const { targetWidth } = BANGDREAM_CARD_SD_CHARACTER_SPEC.list;
|
||||
|
||||
return (cropHeight / cropWidth) * targetWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算卡牌 SD 角色列表展示字号。
|
||||
*/
|
||||
export function getCardSdCharacterListTextSize() {
|
||||
return getCardSdCharacterListLineHeight();
|
||||
}
|
||||
@ -2,6 +2,12 @@ import { Costume } from '@/qqbot/plugins/bangDream/tsugu/models/costume';
|
||||
import { Card } from '@/qqbot/plugins/bangDream/tsugu/models/card';
|
||||
import { Canvas } from 'skia-canvas';
|
||||
import { drawList } from './list-frame';
|
||||
import {
|
||||
BANGDREAM_CARD_SD_CHARACTER_SPEC,
|
||||
getCardSdCharacterCropRects,
|
||||
getCardSdCharacterListLineHeight,
|
||||
getCardSdCharacterListTextSize,
|
||||
} from '@/qqbot/plugins/bangDream/tsugu/render-blocks/list-card-sd-character-spec';
|
||||
|
||||
/**
|
||||
* 在图片布局层中绘制SD角色In列表。
|
||||
@ -14,22 +20,29 @@ export async function drawSdCharacterInList(card: Card): Promise<Canvas> {
|
||||
const costume = new Costume(costumeId);
|
||||
await costume.initFull();
|
||||
const sdCharacterImage = await costume.getSdCharacter();
|
||||
//从高度84开始,把sdCharaImage切成田字形的四分,大小都为400*470
|
||||
const sdCharacterImageList: Array<Canvas> = [];
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const canvas = new Canvas(400, 470);
|
||||
for (const cropRect of getCardSdCharacterCropRects()) {
|
||||
const canvas = new Canvas(cropRect.width, cropRect.height);
|
||||
const context = canvas.getContext('2d');
|
||||
const x = i % 2 === 0 ? 0 : 400;
|
||||
const y = i < 2 ? 84 : 554;
|
||||
|
||||
context.drawImage(sdCharacterImage, x, y, 400, 470, 0, 0, 400, 470);
|
||||
context.drawImage(
|
||||
sdCharacterImage,
|
||||
cropRect.sourceX,
|
||||
cropRect.sourceY,
|
||||
cropRect.width,
|
||||
cropRect.height,
|
||||
0,
|
||||
0,
|
||||
cropRect.width,
|
||||
cropRect.height,
|
||||
);
|
||||
sdCharacterImageList.push(canvas);
|
||||
}
|
||||
return drawList({
|
||||
key: '演出缩略图',
|
||||
content: sdCharacterImageList,
|
||||
lineHeight: (470 / 400) * 190,
|
||||
textSize: (470 / 400) * 190,
|
||||
spacing: 0,
|
||||
lineHeight: getCardSdCharacterListLineHeight(),
|
||||
textSize: getCardSdCharacterListTextSize(),
|
||||
spacing: BANGDREAM_CARD_SD_CHARACTER_SPEC.list.spacing,
|
||||
});
|
||||
}
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
import {
|
||||
BANGDREAM_CARD_SD_CHARACTER_SPEC,
|
||||
getCardSdCharacterCropRect,
|
||||
getCardSdCharacterCropRects,
|
||||
getCardSdCharacterListLineHeight,
|
||||
getCardSdCharacterListTextSize,
|
||||
} from '@/qqbot/plugins/bangDream/tsugu/render-blocks/list-card-sd-character-spec';
|
||||
|
||||
describe('BangDream card SD character list spec', () => {
|
||||
it('keeps the historical four-frame SD character crop grid', () => {
|
||||
expect(getCardSdCharacterCropRects()).toEqual([
|
||||
{ sourceX: 0, sourceY: 84, width: 400, height: 470 },
|
||||
{ sourceX: 400, sourceY: 84, width: 400, height: 470 },
|
||||
{ sourceX: 0, sourceY: 554, width: 400, height: 470 },
|
||||
{ sourceX: 400, sourceY: 554, width: 400, height: 470 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('computes individual crop rects from the shared sprite spec', () => {
|
||||
expect(getCardSdCharacterCropRect(3)).toEqual({
|
||||
sourceX: 400,
|
||||
sourceY: 554,
|
||||
width: 400,
|
||||
height: 470,
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps list line height, text size and spacing stable', () => {
|
||||
expect(BANGDREAM_CARD_SD_CHARACTER_SPEC.list.spacing).toBe(0);
|
||||
expect(getCardSdCharacterListLineHeight()).toBe(223.25);
|
||||
expect(getCardSdCharacterListTextSize()).toBe(223.25);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user