@@ -12,6 +12,8 @@ export type QwenSpriteActionTemplate = {
defaultFps : number ;
bodyTravel : string ;
weaponRule : string ;
stagingDirection? : string ;
defaultDetailText? : string ;
sequenceLines : [ string , string , string , string ] ;
ending : string ;
} ;
@@ -48,6 +50,14 @@ const THEME_APPLICATION_BOUNDARY_TEXT =
const CHIBI_CHARACTER_TEXT =
'即使角色带有怪物或海洋主题,也优先做成 Q版可爱的人形动作角色, 方便读图和后续动画化。' ;
const SETTING_AND_ROLE_ALIGNMENT_TEXT =
'先从角色设定中提炼世界设定、时代氛围、阵营身份、职业职责、战斗习惯、装备结构、材质配色和情绪气质,再把这些信息落实到发型、服装层次、护具、武器、饰品、轮廓和动作节奏里,不要混入与设定无关的现代服饰、写实摄影镜头、枪械体系或其他世界观元素。' ;
const CHARACTER_DETAIL_COVERAGE_TEXT =
'角色描述需要尽量落到可视化细节:发型与脸部识别点、年龄层与气质、服装层次、护具与配饰、武器/法器类型、主色与材质、职业姿态与世界观痕迹,避免只有抽象身份词。' ;
export const DEFAULT_CHARACTER_BRIEF =
'魔潮复苏边境城邦中的少女遗迹冒险者, Q版大头身, 约 2 到 3 头身,金棕色微卷短发,琥珀色眼睛,额前碎发与侧边发束清晰,表情明亮但带警觉;穿分层轻甲、短披风和旅行短裙,皮革护腕、金属护膝、系带短靴完整可见;腰间挂药剂包、地图筒与小型护符,右手持单手短剑,主色为蜂蜜金、墨绿和旧银,轮廓利落,像长期在遗迹与荒野间行动的年轻探索者。' ;
export const PLAYABLE_CHARACTER_STYLE_REFERENCE_SOURCES = [
'/character/Sword Princess/Original/Hero/idle/Idle01.png' ,
'/character/Archer Hero/Original/Hero/idle/idle01.png' ,
@@ -134,11 +144,50 @@ export const QWEN_SPRITE_ACTION_TEMPLATES: QwenSpriteActionTemplate[] = [
} ,
] ;
const ACTION_TEMPLATE_DETAILS : Record <
QwenSpriteActionTemplateId ,
{ stagingDirection : string ; defaultDetailText : string }
> = {
idle : {
stagingDirection :
'演出重点是轻呼吸、微幅重心起伏、戒备感和可循环衔接。' ,
defaultDetailText :
'保持与角色设定一致的戒备气质和职业站姿,重心稳在脚下,呼吸起伏轻微,披风、衣摆、发梢和小型饰品只有细小摆动,武器安静跟随身体微动,像角色在所属世界里随时准备探索、交涉或开战的待机瞬间。' ,
} ,
run : {
stagingDirection :
'演出重点是持续推进、步点清楚、上身稳定和装备惯性。' ,
defaultDetailText :
'跑动时要体现角色职业和世界设定中的装备重量感,身体略微前压,步幅清晰,手臂与武器顺势摆动,披风、衣摆和挂件跟着惯性后甩,像角色正穿过战场、街巷或遗迹通道迅速移动,节奏连续稳定。' ,
} ,
attack_slash : {
stagingDirection :
'演出重点是收身蓄力、爆发斩击、武器轨迹和收招稳定。' ,
defaultDetailText :
'攻击前先有短暂收身蓄力,再顺着主手武器做干净利落的前踏斩击,爆发点明确,武器轨迹贴合角色职业习惯与世界观武器设定,衣摆和挂件随发力甩动,收招后还能稳住重心,像久经战斗训练的真实角色动作。' ,
} ,
hurt : {
stagingDirection :
'演出重点是冲击反馈、短暂失衡、惯性摆动和重新稳住。' ,
defaultDetailText :
'受击瞬间要有明确冲击反馈,肩背后仰或身体侧偏,表情短促吃痛但不夸张,武器和手臂因惯性发生合理摆动,服装层次和挂件跟着抖动一下,随后努力稳住姿态,像这个角色在其世界观里真实挨到一击后的反应。' ,
} ,
die : {
stagingDirection :
'演出重点是失衡下坠、动作逐渐停尽和终止姿态清晰。' ,
defaultDetailText :
'死亡动作要先表现失衡与力量被抽离,再完成明显倒下或瘫落,武器和四肢随惯性下坠,披风、衣摆和饰品有最后一次明显摆动,最终停在清晰的终止姿态,符合角色身份、装备重量和世界氛围,不要轻飘或喜剧化。' ,
} ,
} ;
export function getActionTemplateById ( id : QwenSpriteActionTemplateId ) {
return (
QWEN_SPRITE_ACTION_TEMPLATES . find ( ( templ ate) = > templ ate. id === id ) ? ?
QWEN_SPRITE_ACTION_TEMPLATES [ 0 ]
) ;
const template =
QWEN_SPRITE_ACTION_TEMPLATES . find ( ( candid ate) = > candid ate. id === id ) ? ?
QWEN_SPRITE_ACTION_TEMPLATES [ 0 ] ;
return {
. . . template ,
. . . ACTION_TEMPLATE_DETAILS [ template . id ] ,
} ;
}
export function readFileAsDataUrl ( file : File ) {
@@ -423,11 +472,13 @@ export async function buildPlayableCharacterStyleReferenceBoard(
export function buildMasterPrompt ( characterBrief : string ) {
return [
'单人, 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 } 高可读性游戏角色设定图,偏像素动画前置设计稿,形体清晰,服装层次明确,道具/权杖/武器如有则存在关系合理,便于后续连续动作生成。 ` ,
'???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 } ?????????????????????????????????????/??/??????????????????????? ` ,
SETTING_AND_ROLE_ALIGNMENT_TEXT ,
CHARACTER_DETAIL_COVERAGE_TEXT ,
CONCEPT_INTERPRETATION_TEXT ,
HUMANLIKE_PRIORITY_TEXT ,
CONCEPT_HIERARCHY_TEXT ,
@@ -444,20 +495,22 @@ export function buildSheetPrompt(options: {
extraDirection : string ;
} ) {
return [
` 使用图1作为风格参考。生成一张 4x4 的 sprite sheet,共 16 帧,展示同一个角色的连续动作。角色保持右向斜侧身动作视角,主体完整出现在每一个格子里,底部轮廓稳定,角色在每一格中的尺度基本一致,镜头固定不变,不要切换景别,不要切换视角,不要左右翻转,也不要退化成完全 90 度纯右视图。 ${ CHIBI_STYLE_TEXT } ${ CHIBI_CHARACTER_TEXT } ${ PIXEL_STYLE_TEXT } ${ STYLE_REFERENCE_SCOPE_TEXT } ` ,
` ???1??????????? 4x4 ? sprite sheet?? 16 ????????????????????????????????????????????????????????????????????????????????????????????????????? 90 ?????? ${ CHIBI_STYLE_TEXT } ${ CHIBI_CHARACTER_TEXT } ${ PIXEL_STYLE_TEXT } ${ STYLE_REFERENCE_SCOPE_TEXT } ` ,
SETTING_AND_ROLE_ALIGNMENT_TEXT ,
CONCEPT_INTERPRETATION_TEXT ,
HUMANLIKE_PRIORITY_TEXT ,
CONCEPT_HIERARCHY_TEXT ,
THEME_APPLICATION_BOUNDARY_TEXT ,
` 动作名: ${ options . actionTemplate . label } ` ,
` 是否循环: ${ options . actionTemplate . loop ? '是' : '否' } ` ,
` 身体位移: ${ options . actionTemplate . bodyTravel } ` ,
` 武器规则: ${ options . actionTemplate . weaponRule } ` ,
` ???? ${ options . actionTemplate . label } ` ,
` ??????? ${ options . actionTemplate . stagingDirection ? ? ACTION_TEMPLATE_DETAILS [ options . actionTemplate . id ] . stagingDirection } ` ,
` ????? ${ options . actionTemplate . loop ? '?' : '?' } ` ,
` ????? ${ options . actionTemplate . bodyTravel } ` ,
` ????? ${ options . actionTemplate . weaponRule } ` ,
. . . options . actionTemplate . sequenceLines ,
` 结尾要求: ${ options . actionTemplate . ending } ` ,
'输出要求:每一格都要清晰分开,网格顺序从左到右、从上到下,动作连续,首尾关系明确,轮廓稳定,发型稳定,服装结构稳定,武器始终在正确的手中,背景为纯浅色,适合后续切成 sprite frames。 ' ,
` ????? ${ options . actionTemplate . ending } ` ,
'?????????????????????????????????????????????????????????????????????????????????? sprite frames? ' ,
options . characterBrief . trim ( ) ,
options . extraDirection . trim ( ) ,
` ??????? ${ options . extraDirection . trim ( ) || options . actionTemplate . defaultDetailText || ACTION_TEMPLATE_DETAILS [ options . actionTemplate . id ] . defaultDetailText } ` ,
]
. filter ( Boolean )
. join ( '\n' ) ;
@@ -465,13 +518,13 @@ export function buildSheetPrompt(options: {
export function buildRepairPrompt ( options : {
issueText : string ;
useNeighborLabel : '上一帧 ' | '下一帧 ' ;
useNeighborLabel : '??? ' | '??? ' ;
} ) {
return [
` 使用图1作为风格参考, 参考图2的动作连续性, 修复图3这一个单帧。图2代表 ${ options . useNeighborLabel } 。 ` ,
` 要求输出一张单独的动作帧图片, 不要网格, 不要背景细节。角色保持右向斜侧身动作视角, 主体完整, 底部结构稳定, 保持与图2连续, 并且与图1是同一个角色, 不要退化成完全 90 度纯右视图。 ${ CHIBI_STYLE_TEXT } ${ CHIBI_CHARACTER_TEXT } ${ PIXEL_STYLE_TEXT } ${ STYLE_REFERENCE_SCOPE_TEXT } ${ CONCEPT_INTERPRETATION_TEXT } ${ HUMANLIKE_PRIORITY_TEXT } ${ CONCEPT_HIERARCHY_TEXT } ${ THEME_APPLICATION_BOUNDARY_TEXT } 修复图3中的错误, 使这一帧适合插回原来的 sprite sheet 中。 ` ,
'保持不变:发型、服装结构、主配色、武器类型、朝向。 ' ,
` 重点修复: ${ options . issueText . trim ( ) || '修复手脚畸形、武器错误或朝向不一致问题。 ' } ` ,
` ???1??????????2??????????3???????2?? ${ options . useNeighborLabel } ? ` ,
` ?????????????????????????????????????????????????????????2???????1?????????????? 90 ?????? ${ CHIBI_STYLE_TEXT } ${ CHIBI_CHARACTER_TEXT } ${ PIXEL_STYLE_TEXT } ${ STYLE_REFERENCE_SCOPE_TEXT } ${ SETTING_AND_ROLE_ALIGNMENT_TEXT } ${ CONCEPT_INTERPRETATION_TEXT} ${ HUMANLIKE_PRIORITY_TEXT } ${ CONCEPT_HIERARCHY_TEXT } ${ THEME_APPLICATION_BOUNDARY_TEXT } ???3???????????????? sprite sheet ?? ` ,
'????????????????????????? ' ,
` ????? ${ options . issueText . trim ( ) || '???????????????????? ' } ` ,
] . join ( '\n' ) ;
}
@@ -482,19 +535,21 @@ export function buildVideoActionPrompt(options: {
characterBrief : string ;
} ) {
return [
` 单人全身角色动作视频,动作主题是 ${ options . actionTemplate . label } 。 ` ,
` 角色固定为图1同一角色, 保持右向斜侧身动作视角, 镜头稳定, 轮廓清晰, 不要退化成完全 90 度纯右视图。 ${ CHIBI_STYLE_TEXT } ${ CHIBI_CHARACTER_TEXT } ${ PIXEL_STYLE_TEXT } ${ STYLE_REFERENCE_SCOPE_TEXT } ` ,
` ???????????????? ${ options . actionTemplate . label } ? ` ,
` ??????1??????????????????????????????????? 90 ?????? ${ CHIBI_STYLE_TEXT } ${ CHIBI_CHARACTER_TEXT } ${ PIXEL_STYLE_TEXT } ${ STYLE_REFERENCE_SCOPE_TEXT } ` ,
SETTING_AND_ROLE_ALIGNMENT_TEXT ,
CONCEPT_INTERPRETATION_TEXT ,
HUMANLIKE_PRIORITY_TEXT ,
CONCEPT_HIERARCHY_TEXT ,
THEME_APPLICATION_BOUNDARY_TEXT ,
` 动作结构: ${ options . actionTemplate . sequenceLines . join ( '; ' ) } 。结尾要求: ${ options . actionTemplate . ending } 。 ` ,
` ??????? ${ options . actionTemplate . stagingDirection ? ? ACTION_TEMPLATE_DETAILS [ options . actionTemplate . id ] . stagingDirection } ` ,
` ????? ${ options . actionTemplate . sequenceLines . join ( '?' ) } ?????? ${ options . actionTemplate . ending } ? ` ,
options . useChromaKey
? '背景为纯绿色绿幕,无其他人物和场景元素,方便后期抽帧与抠像。 '
: '背景简洁纯净,无复杂场景。 ' ,
` 动作补充细节: ${ options . actionDetailText . trim ( ) || '保持动作清晰、节奏明确、适合后续抽帧为 sprite sheet。' } ` ,
` 角色设定: ${ options . characterBrief . trim ( ) } ` ,
'目标是后续抽帧为横版动作游戏精灵表,因此不要镜头切换,不要景别变化,不要角色漂移。 ' ,
? '?????????????????????????????? '
: '????????????? ' ,
` ??????? ${ options . actionDetailText . trim ( ) || options . actionTemplate . defaultDetailText || ACTION_TEMPLATE_DETAILS [ options . actionTemplate . id ] . defaultDetailText } ` ,
` ????? ${ options . characterBrief . trim ( ) } ` ,
'????????????????????????????????????????? ' ,
] . join ( ' ' ) ;
}