11
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-04-16 21:47:20 +08:00
parent 2456c10c63
commit 09d4c0c31b
79 changed files with 11873 additions and 2341 deletions

View File

@@ -95,19 +95,25 @@ export const QWEN_SPRITE_ACTION_TEMPLATES: QwenSpriteActionTemplate[] = [
];
const CHIBI_STYLE_TEXT =
'Q版大头身动作角色头部占比明显更大,约 2 到 3 头身,类似横版像素 RPG 可扮演角色的比例,不要写实长身比例。';
'Q版大头身动作角色身比固定控制在 2 到 3 头身,头部占比明显更大,类似横版像素 RPG 可扮演角色的比例,不要写实长身比例。';
const PIXEL_STYLE_TEXT =
'参考项目内可扮演角色的像素风动作角色画风,整体是像素游戏角色设计方向,身体始终朝右,适合横版动作 sprite 资产。';
const SIDE_FACING_RIGHT_TEXT =
'角色采用横版动作素材常用的右向斜侧身站姿,身体整体朝右,但保留少量正面信息,能读到面部轮廓与胸肩结构,不是完全 90 度纯右视图,也不是正面立绘。';
const SUBJECT_ONLY_TEXT =
'画面中只保留单个角色主体,不要额外人物、动物、召唤物、载具或陪体。';
const CLEAN_BACKGROUND_TEXT =
'背景固定为纯绿色绿幕,只作为抠像底色,不出现建筑、室内布景、风景、地面道具、漂浮物、烟雾叙事元素或其他角色以外的场景内容。';
const STYLE_REFERENCE_SCOPE_TEXT =
'参考图不仅用于约束像素画风、颜色组织、头身比例、右朝向和镜头语言,还要严格约束身体结构骨架。生成结果必须优先沿用参考图的人形动作角色身体结构,包括头、躯干、双臂、双腿、站姿重心和整体头身比;可以变化发型、服装、主题配饰和材质,但不要脱离参考图的人形身体结构。';
const CONCEPT_INTERPRETATION_TEXT =
'请先拆解设定中的“身份词、主题词、身体结构词”。如果文字设定没有明确要求非人身体结构,默认优先生成人形拟人化角色,让主题词主要体现在服装、头饰、冠冕、权杖、纹样、材质和发光装饰上。';
const HUMANLIKE_PRIORITY_TEXT =
'默认优先使用参考图对应的人类或类人动作角色骨架,保持清楚的头、躯干、手臂和双腿轮廓,这样更适合横版动作 sprite。只有当文字设定明确要求鱼尾、触手身体、伞盖头部、无双腿、漂浮体、凝胶体或其他非人结构时才改为对应非人身体。';
const JELLYFISH_THEME_EXAMPLE_TEXT =
'示例:“水母国王”默认应理解为严格沿用参考图人形身体结构的国王角色,再穿带有水母主题的服装和配饰,例如半透明蓝紫色披肩或裙摆、像水母伞盖的王冠、荧光斑点、海洋质感袖摆、水母权杖,而不是完整水母怪物本体。';
const CONCEPT_HIERARCHY_TEXT =
'视觉优先级应当是:身体结构词第一,身份词第二,主题词第三。没有明确身体结构词时,默认用人形拟人化表现,再把主题词转译成服装和装饰。';
const THEME_APPLICATION_BOUNDARY_TEXT =
'主题词默认只作用在角色自身的服装剪裁、材质、纹样、饰品、武器和发光细节上,不要把主题词自动扩写成背景建筑、自然场景、漂浮装饰或额外环境物件。';
const CHIBI_CHARACTER_TEXT =
'即使角色带有怪物或海洋主题,也优先做成 Q版可爱的人形动作角色方便读图和后续动画化。';
@@ -120,13 +126,15 @@ export function getActionTemplateById(id: QwenSpriteActionTemplateId) {
export function buildMasterPrompt(characterBrief: string) {
return [
'单人2D 横版游戏角色标准设定图,角色始终朝右侧,侧视角为主,主体完整可见,底部轮廓完整,身体比例稳定,轮廓清楚,适合后续制作 sprite sheet 动画。',
'画面要求1:1 正方形画布,纯色浅背景,画面中心构图,角色主体完整置于画面中央,不要裁切主体顶部和底部,不要多角色,不要复杂环境,不要镜头透视,不要特写。',
'单人2D 横版游戏角色标准设定图,主体完整可见,底部轮廓完整,身体比例稳定,轮廓清楚,适合后续制作 sprite sheet 动画。',
`视角要求:${SIDE_FACING_RIGHT_TEXT}`,
`主体要求:${SUBJECT_ONLY_TEXT}`,
`画面要求1:1 正方形画布,画面中心构图,角色主体完整置于画面中央,不要裁切主体顶部和底部,不要镜头透视,不要特写。${CLEAN_BACKGROUND_TEXT}`,
`风格要求:${CHIBI_STYLE_TEXT} ${CHIBI_CHARACTER_TEXT} ${PIXEL_STYLE_TEXT} ${STYLE_REFERENCE_SCOPE_TEXT} 高可读性游戏角色设定图,偏像素动画前置设计稿,形体清晰,服装层次明确,道具/权杖/武器如有则存在关系合理,便于后续连续动作生成。`,
CONCEPT_INTERPRETATION_TEXT,
HUMANLIKE_PRIORITY_TEXT,
CONCEPT_HIERARCHY_TEXT,
JELLYFISH_THEME_EXAMPLE_TEXT,
THEME_APPLICATION_BOUNDARY_TEXT,
characterBrief.trim(),
]
.filter(Boolean)
@@ -141,11 +149,11 @@ export function buildVideoActionPrompt(options: {
}) {
return [
`单人全身角色动作视频,动作主题是 ${options.actionTemplate.label}`,
`角色固定为图1同一角色始终侧身朝右,镜头稳定,轮廓清晰${CHIBI_STYLE_TEXT} ${CHIBI_CHARACTER_TEXT} ${PIXEL_STYLE_TEXT} ${STYLE_REFERENCE_SCOPE_TEXT}`,
`角色固定为图1同一角色保持右向斜侧身动作视角,镜头稳定,轮廓清晰,不要退化成完全 90 度纯右视图${CHIBI_STYLE_TEXT} ${CHIBI_CHARACTER_TEXT} ${PIXEL_STYLE_TEXT} ${STYLE_REFERENCE_SCOPE_TEXT}`,
CONCEPT_INTERPRETATION_TEXT,
HUMANLIKE_PRIORITY_TEXT,
CONCEPT_HIERARCHY_TEXT,
JELLYFISH_THEME_EXAMPLE_TEXT,
THEME_APPLICATION_BOUNDARY_TEXT,
`动作结构:${options.actionTemplate.sequenceLines.join('')}。结尾要求:${options.actionTemplate.ending}`,
options.useChromaKey
? '背景为纯绿色绿幕,无其他人物和场景元素,方便后期抽帧与抠像。'

View File

@@ -34,6 +34,45 @@ export type BasicOkResult = {
ok: true;
};
export type ProfileDashboardCardKey = 'wallet' | 'playTime' | 'playedWorks';
export type ProfileDashboardSummary = {
walletBalance: number;
totalPlayTimeMs: number;
playedWorldCount: number;
updatedAt: string | null;
};
export type ProfileWalletLedgerEntry = {
id: string;
amountDelta: number;
balanceAfter: number;
sourceType: 'snapshot_sync';
createdAt: string;
};
export type ProfileWalletLedgerResponse = {
entries: ProfileWalletLedgerEntry[];
};
export type ProfilePlayedWorkSummary = {
worldKey: string;
ownerUserId: string | null;
profileId: string | null;
worldType: string | null;
worldTitle: string;
worldSubtitle: string;
firstPlayedAt: string;
lastPlayedAt: string;
lastObservedPlayTimeMs: number;
};
export type ProfilePlayStatsResponse = {
totalPlayTimeMs: number;
playedWorks: ProfilePlayedWorkSummary[];
updatedAt: string | null;
};
export type CustomWorldPublicationStatus = 'draft' | 'published';
export type CustomWorldThemeMode =
| 'martial'
@@ -47,9 +86,7 @@ export type CustomWorldProfileRecord = JsonObject & {
id?: string;
};
export type CustomWorldLibraryEntry<
TProfile = CustomWorldProfileRecord,
> = {
export type CustomWorldLibraryEntry<TProfile = CustomWorldProfileRecord> = {
ownerUserId: string;
profileId: string;
profile: TProfile;
@@ -71,9 +108,7 @@ export type CustomWorldGalleryCard = Omit<
'profile'
>;
export type CustomWorldLibraryResponse<
TProfile = CustomWorldProfileRecord,
> = {
export type CustomWorldLibraryResponse<TProfile = CustomWorldProfileRecord> = {
entries: CustomWorldLibraryEntry<TProfile>[];
};
@@ -94,6 +129,33 @@ export type CustomWorldGalleryDetailResponse<
entry: CustomWorldLibraryEntry<TProfile>;
};
export type PlatformBrowseHistoryEntry = {
ownerUserId: string;
profileId: string;
worldName: string;
subtitle: string;
summaryText: string;
coverImageSrc: string | null;
themeMode: CustomWorldThemeMode;
authorDisplayName: string;
visitedAt: string;
};
export type PlatformBrowseHistoryWriteEntry = Omit<
PlatformBrowseHistoryEntry,
'visitedAt'
> & {
visitedAt?: string;
};
export type PlatformBrowseHistoryResponse = {
entries: PlatformBrowseHistoryEntry[];
};
export type PlatformBrowseHistoryBatchSyncRequest = {
entries: PlatformBrowseHistoryWriteEntry[];
};
export const CUSTOM_WORLD_GENERATION_MODES = ['fast', 'full'] as const;
export type CustomWorldGenerationMode =
(typeof CUSTOM_WORLD_GENERATION_MODES)[number];