mcpField
C
chat-pet-sprite-creation

chat-pet-sprite-creation

github.com/microsoft创意与媒体194.4k48 次安装今天更新
代码仓库

关于 chat-pet-sprite-creation

用于在现有代码库中制作和审查聊天宠物像素图的 Skill,涵盖素材、动画、合成与交互约束,并以当前代码和测试为准。

主要功能

  1. 01基准精灵图与身体锚点
  2. 02逻辑像素和画布规则
  3. 03DOM 眼睛与眨眼合成
  4. 04Stable 与 Insiders 调色板一致
  5. 05精灵图表与减少动态效果素材
  6. 06配饰图集与连接框架

适用场景

  1. 01设计新的宠物反应状态
  2. 02添加或审查精灵动画
  3. 03检查眼睛覆盖层和朝向行为
  4. 04集成可穿戴配饰

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/microsoft/vscode --skill chat-pet-sprite-creation

安装后在 Claude Code 中输入/chat-pet-sprite-creation确认已加载。

详细介绍

聊天宠物精灵图创作

创建宠物精灵图,让它们看起来像同一个连续角色,而不是彼此独立的画作。从当前宠物身体开始,保留其视觉锚点,并确保每处差异都有明确目的。

事实来源

  • 精灵图:src/vs/workbench/contrib/chat/browser/widget/media/chatPet/
  • 运行时状态、尺寸、计时和过渡:src/vs/workbench/contrib/chat/browser/widget/chatPetWidget.ts
  • 眼睛几何形状、朝向、裁剪和动作 CSS:src/vs/workbench/contrib/chat/browser/widget/media/chatPet.css
  • 单元测试:src/vs/workbench/contrib/chat/test/browser/widget/chatPetWidget.test.ts

绘制前请先阅读当前实现。现有尺寸和计时可能已与编写本指南时不同。

PR 优先级与演进脉络

本指南提炼了宠物相关 PR 的完整历史。规则发生冲突时,请按以下优先级处理:

  1. 当前代码和测试
  2. 最新的相关开放 PR
  3. 较新的已合并 PR
  4. 较早的历史行为

特别是,动画清理 PR #330399 已取代旧的复活标记流程及此前的若干精灵图和计时假设。

PR持久有效的经验
#327063宠物是一个语义按钮;精灵图画布、图像、眼睛和特效仅用于视觉呈现,并设为 aria-hidden。通过 FileAccess 解析资源 URL。
#327412将反应建模为显式状态。不要立即重复普通的随机反应;罕见变形应单独抽样。
#327588对精灵图像使用双缓冲,并仅在待加载图像加载完成后切换。加载新来源时,绝不要清空当前活动精灵图。
#327696Stable/Insiders 是一种有类型且持久化的外观选择。保持变体命名和几何形状的系统性。
#327714动画美术资源应采用水平精灵图表,并提供专门制作的静态减弱动态效果 PNG。计时属于运行时数据,而非图像元数据。
#328334“逃跑中”等持久行为应放在服务状态中。多阶段动画应根据完成信号推进,而不是依赖猜测的延迟。
#328480拖动结束后不得同时触发点击反应。共享指针事件的手势需要明确的抑制或所有权机制。
#328530唤醒操作会消耗唤醒宠物的交互;不得同时触发随机反应。减弱动态效果时可以跳过唤醒过渡。
#329121合并注视更新;文档隐藏时暂停精灵图计时器,并根据经过的时间恢复,而不是重播错过的帧。
#329347将像素美术中的姿势变化保留在精灵图帧中,将空间运动放在布局、CSS 或物理逻辑中。根据过渡信号完成跌落。
#329729开始反应前先面向交互方向。为每种瞬态状态设置明确的持续时间,并使用真实的完成事件衔接后续阶段。
#329852指针和键盘手势需要产生等效结果。减弱动态效果时,应保留状态变化,同时移除位移动画。
#329867注意力动画应有时长限制;即使确认仍在等待中,拍手也应在确认注意力窗口结束后停止。
#330160眼睛是复合的运行时图层,具有跟踪和眨眼模式。快速改变朝向可能触发独立的眩晕状态。宽幅美术资源必须遵守实时边界。
#330275物理计算应使用身体占地范围、限制帧步长,并明确标记撞击时刻。飞行过程中布局变化时,重新计算几何信息。
#330399最新动画约定:宽幅睡眠/唤醒美术资源、考虑帧的眨眼合成、固定朝向的装饰,以及使用同一张特效精灵图先反向消失、再正向重现。

逻辑像素

规范的美术单位是一个逻辑像素:

  • 8×8 个源像素
  • 按照标准的 96×96 源图 → 48×48 显示比例,对应 4×4 个 CSS 像素

核心轮廓、面部特征、道具和重复细节都必须使用相同的逻辑像素比例。不要仅为了容纳更多细节,就用更小或更大的色块绘制新对象。

特效可以有意细分逻辑像素,例如小星星、气泡或弧形运动效果,但细分必须:

  1. 用于无法在核心网格上清晰呈现的特定特效。
  2. 在整个特效中保持一致。
  3. 绝不能由抗锯齿或重采样产生。

仅使用最近邻渲染。保持背景透明、像素边缘清晰。不要引入模糊、羽化透明度、颜色插值或意外的非网格缩放。

从基准图开始

绝不要凭记忆重新绘制宠物身体。

  • 静止、由指针驱动或嬉戏状态应以当前的静止精灵图为基准。
  • 请求/处理状态应以当前的渲染中精灵图为基准。
  • 先复制完整身体,然后只修改新状态所需的部分。

这样可以保持:

  • 身体的宽度和高度
  • 底部基线
  • 天线根部和间距
  • 高光与阴影色阶
  • 眼窝
  • 碰撞/交互范围

第一个和最后一个关键姿势必须能平滑过渡到静止或渲染中状态,不出现身体位置、轮廓、基线或缩放突变。

画布与锚定

默认源画布为 96×96,即 12×12 个逻辑像素。

仅当内容有意延伸至规范身体框之外时,才使用更大的画布:

  • 终端或按钮可能需要额外宽度。
  • 便签、星星或气泡可能需要额外高度。
  • 身体必须保持锚定在基准精灵图中的准确位置。

不要将身体置于更宽画布的中央。让身体保持在规范的 96×96 区域内,并允许道具/特效超出边界。请在 chatPetWidget.ts 中声明每个非标准源尺寸,并更新宽精灵图的边界处理。

运行时的碰撞和移动框应对应宠物身体,而非装饰性溢出部分。

眼睛

标准睁眼尺寸为 1×2 个逻辑像素:

  • 8×16 个源像素
  • 4×8 个 CSS 像素

只有当状态表达特殊表情时,才使用不同的眼睛形状,例如睡觉、头晕、喜爱、担忧或受到撞击。

DOM 眼睛图层

DOM 眼睛图层有两种独立模式:

  • 追踪提供视线、朝向、眨眼和拖动表情。
  • 眨眼可让非追踪状态暂时显示 DOM 眼睛,并可根据精灵图帧改变表现。

使用运行时视线的状态必须使用不含眼睛的 *-tracking-96 资源。使用 DOM 眨眼的状态(例如 PR #330399 中的打字、按下按钮或喜爱状态)也必须为叠加层留出相应的瞳孔区域。

添加或修改使用 DOM 眼睛的状态时:

  1. 保持精灵图中的眼窝为空。
  2. 视情况在 doesChatPetStateTrackCursor 中添加光标行为。
  3. 视情况在 doesChatPetStateBlink(state, frameIndex) 中添加眨眼行为。
  4. 验证两个朝向下的高眼位眨眼、状态专属眼睛高度和指针偏移。
  5. 验证有意停止眨眼的帧,例如保持终端姿势的帧。

绝不要将绘制在精灵图中的瞳孔与运行时眼睛叠加层结合使用。

绘制眼睛的状态

表情固定的状态应将眼睛绘制在美术资源中,并禁用光标追踪。除非表情有意改变眼睛位置,否则应保持标准眼睛位置。

Stable 与 Insiders 保持一致

Stable 和 Insiders 是同一动画的两种调色板变体。

两者必须完全一致:

  • 画布尺寸
  • 帧数和顺序
  • Alpha 蒙版和几何形状
  • 身体锚点和悬伸部分
  • 静态回退姿势
  • 时间和迭代行为

创建一个几何母版,再应用两种既定调色板。不要分别重绘各个变体。

并排检查这两个变体。除非产品明确要求存在差异,否则任何形状差异都是 bug。

朝向和镜像

制作一个规范朝向,并让运行时将其镜像为另一个朝向。

测试两个朝向,因为镜像也会改变宽精灵图的悬伸位置。在左右边缘附近留出足够空间,以便进行边界校正。

必须保持屏幕朝向的装饰元素(例如文字、乐谱符号或方向符号)不得烘焙到会被运行时镜像的图层中。应将它们建模为朝向固定的装饰元素,或单独渲染。

静态资源和精灵图集

每个动画状态都需要以下两种变体:

  • 用于减少动态效果的静态 PNG:buddy-<state>-<variant>-<height>.png
  • 水平精灵图集:buddy-<state>-<variant>-<height>.spritesheet.png

精灵图集规范如下:

sheet width = frame width × frame count
sheet height = frame height

每一帧都使用相同的矩形。绝不要移动帧边界或添加逐帧内边距。

选择一个有意义的静态姿势,让人无需动画也能理解该状态。不要默认认为动画的第一帧就是减少动态效果时的最佳回退图。

分层配饰

可穿戴配饰使用由身体拥有的附着装配,并在 media/chatPet/accessories/ 下为每种外观使用一个与调色板无关的图集。不要为单独的运行时状态或帧导出副本。身体动画元数据负责控制附着物的移动;配饰图集只包含身体几何形状发生变化时所需的少量规范形状。

默认图集为 256×192,划分为 64×64 的单元格。如果帽子的实际轮廓确实需要完整的 12 逻辑像素身体宽度,则可以声明 atlasCellSize: 96,并使用包含 96×96 单元格的 384×288 图集。不要仅仅为了增加细节而选择更宽的规格;两种规格仍使用相同的完整 8×8 逻辑像素。

columns: upright | sleeping | impact | splat
row 0:   head back layers
row 1:   head front layers
row 2:   right-eye front layers

外观可以让任意单元格保持透明。例如,普通帽子会留空眼睛所在的行,而组合式礼帽与单片眼镜外观会使用头部的两行和眼睛所在行。腾空装配姿势会复用直立列。只有当现有姿势加上由身体控制的平移无法保留预期轮廓时,才添加另一个规范列。

附着轨迹位于 chatPetAccessoryRig.ts 中。每条轨迹使用经过压缩的帧跨度,其中包含规范姿势以及独立的头部/右眼锚点。当由身体绘制的表情、道具或完整轮廓替换项(例如晕眩的眼睛、太阳镜或罕见的图标变形)占用了相同几何区域时,会省略相应插槽。如果同一图集中的帧烘焙了不同朝向,轨迹会标记这些帧,使头部配饰在应用整个宠物的外部朝向变换前,先与身体一起镜像。只有在身体几何形状发生变化时才更新由身体控制的轨迹。添加普通配饰不应需要编辑轨迹或渲染器代码。

头部插槽锚点包含 1 个逻辑像素的佩戴偏移,使帽子能覆盖头顶,而不是搁在头部轮廓上。爱心动画会隐藏头部配饰,因为变形后的头部/触角轮廓就是该反应的表现。插槽的可见性和贴合方式应视为由身体控制的行为,而非针对单顶帽子的例外规则。

将触角收进较大帽子下方的外观应启用 coversAntennae。合成器会先应用由身体控制的遮挡边界,再绘制帽子正面,因此该行为会随动画轨迹和镜像变化,无需在每个图集中绘制身体颜色的遮盖像素。 定向头饰以面向右侧的标准身体为基础绘制,并随完整宠物画布一起镜像。带有方向性结构的帽子应在头部上方保持视觉平衡,同时通过帽檐、遮阳板、倾斜、护鼻或其他不对称细节中克制地使用一个逻辑像素来表现朝向;不要让整个轮廓大幅偏离中心。镜像后,不对称部分仍须正确呈现。与身份绑定的眼部配饰可以选择不镜像,并使用特定方向的眼部锚点,使其始终位于同一只眼睛上;Top Hat & Monocle 是参考示例。宽画幅的固定眼部锚点必须包含身体原点偏移量(frameWidth - 96)。使用朝向测试夹具检查每个外观在两个方向下的效果。

静态减弱动态效果的美术资源可以呈现动画图集中的后续帧。让 getChatPetReducedMotionRigFrame() 与代表性的身体帧保持一致;不要仅因静态 PNG 只有一帧,就假定装配帧为零。

所有可穿戴部件都必须绘制在与身体相同的 8×8 逻辑像素网格上。帽檐、帽冠、饰带、边缘、链条、高光和阴影都必须由完整且对齐的逻辑像素组成;不要使用斜边多边形或源像素阶梯来表现曲线。小型特效的例外不适用于可穿戴配饰。使用当前的 Stable 身体图集作为几何参考,并验证每个 alpha 值都完全透明或完全不透明。运行时会将图层与身体一起镜像;固定朝向的身体装饰会在不擦除配饰像素的情况下恢复。

运行时更换配饰源时,在替换图像加载完成并通过精确尺寸验证之前,保持当前合成图像可见。重绘当前帧,但不要重启身体动画。配饰源加载失败或格式错误时,应回退为仅显示身体,且不得反复重试。

动画设计

动画关键姿势,而不是噪点。

  • 触发动作应清晰易辨。
  • 动作应有明确的顶点或最突出姿势。
  • 返回基准姿势前,结果应清晰可辨。
  • 停顿很有用;重复动作没有必要。

帧时长也是美术设计的一部分。在 chatPetWidget.ts 中对应的 *_FRAME_DURATIONS 数组里定义时长;不要在 PNG 中编码时长或据此推断时长。

让瞬态状态的持续时间与预期的循环播放或单次播放保持一致。明确选择图集采用以下哪种播放方式:

  • 播放一次并停留在最终姿势
  • 循环播放,直到瞬态状态结束
  • 作为另一种转场的一部分反向播放
可逆特效

如果同一图集会反向复用,例如重生 → 消失:

  • 设计图集的首尾姿势,使其都适合作为起始和结束姿势。
  • 检查特效在两个方向下的效果。
  • 避免使用反向播放时会变得不合情理的单向视觉提示。
  • 在特效实际到达的位置验证反向效果,而不只是检查中性画布上的表现。

PR #330399 是参考模式:重生爆发在底部反向播放以实现消失,然后在顶部正向播放以实现重生。旧的复活标志插入动画已被取代。

将姿势动画与空间运动分开

使用精灵帧表现宠物或道具轮廓的变化。以下效果使用 CSS 变换或物理循环:

  • 平移
  • 旋转
  • 进入/退出运动
  • 拖动阻力
  • 搜索显示/隐藏
  • 跌落、投掷、反弹和撞击

不要将每个平移/旋转姿势都重新绘制到图集中。反过来,也不要用 CSS 变换来伪造本应在像素美术中清晰呈现的身体形变。

根据确定性的完成信号推进多阶段行为:

  • 单次播放图集的精灵动画完成
  • CSS 关键帧的 animationend
  • 跌落的 transitionend/transitioncancel
  • 投掷的物理运动稳定

不要用无关的超时来猜测完成时间。

帧调度与重启行为

Sprite 计时使用帧边界的经过时间调度,而非显示刷新轮询循环。回调延迟时,会重新计算正确的帧,并缩短下一次延迟。

  • 文档隐藏时暂停帧计时器。
  • 文档重新可见时,根据经过时间重新计算。
  • 有限动画停留在最后一帧。
  • 反向播放必须使用反转后的帧时长,而不只是反转帧索引。
  • 重新启动已加载的状态时,不要触发多余的图像获取。
  • 闪烁或动作需要重新开始时,在重新添加 CSS 动画类之前强制刷新样式。

环境与分层

在 Sprite 实际运行的同一环境中检查它:

  • 平台/输入边缘
  • 透明背景
  • 工作台左右边界
  • 平台裁剪与遮挡
  • 拖动、下落、投掷和重生动作
  • 任何对话气泡或固定装饰

本应从平台后方经过的像素必须进行裁剪,或分层放置在平台后方。不要让身体/效果像素显示在遮挡平台的下方。

在物理效果有意移动整个宠物之前,移动时应保持身体锚点不变。装饰帧的尺寸不得改变物理目标。

状态与手势归属

渲染状态有明确的优先级。忙碌/任务状态不得被装饰性反应意外隐藏。保留 getChatPetBaseState 中当前的顺序,以及 getChatPetRenderedState 中的临时状态保护逻辑。

交互规则:

  • 拖动会一直占用指针,直到释放,并抑制随后的点击。
  • 唤醒交互只负责唤醒。
  • 碎碎念或其他仅限空闲状态的反应应让位于非空闲基础状态。
  • 宠物死亡、受指针控制、处于空中或正在奔跑时,禁用键盘交互。
  • 眩晕状态会消耗触发它的方向变化手势。
  • 确认时的鼓掌是注意力提示,不是永久的待处理状态动画。

罕见交互应独立于普通非重复池进行抽样,这样添加常见反应时,不会悄然改变彩蛋的触发概率。

渲染与性能

保留当前渲染架构:

  • 使用两个 Sprite 元素实现加载时双缓冲。
  • 将图像的原始来源与 getAttribute('src') 进行比较;.src 可能会规范化 VS Code 资源 URL。
  • 将画布尺寸设为源图像的原生帧尺寸,将 CSS 盒子尺寸设为显示尺寸。
  • 保持 imageSmoothingEnabled = false 和 image-rendering: pixelated。
  • 按变体缓存已解析的 Sprite 来源描述符。
  • 将指针视线更新合并到每个动画帧一次。
  • 物理运算使用 requestAnimationFrame,但要限制积分步长,防止慢帧后发生穿透。
  • 飞行过程中布局发生变化时,重新读取投掷几何信息。

运行时接线

添加状态时,更新所有适用的部分:

  1. 将状态添加到 ChatPetState。
  2. 在 getChatPetSpriteName 中映射文件名。
  3. 在 getChatPetFrameDurations 中添加帧时长。
  4. 声明非标准的源宽度/高度常量。
  5. 在 getSpriteSources 中注册动画和减少动态效果的来源。
  6. 选择光标跟踪和基于帧的眨眼行为。
  7. 选择单次播放、循环、反向播放或静态迭代行为。
  8. 添加临时状态的持续时间和触发条件。
  9. 为多阶段状态添加确定性的完成转换。
  10. 添加朝向、悬垂、固定装饰、裁剪或 CSS 处理。
  11. 为用户触发的交互添加本地化 ARIA 状态播报。
  12. 手势可发现/实用时,更新无障碍帮助。
  13. 更新相关单元测试。

添加美术资源时,必须同时完成运行时约定。

保持视觉元素静默:图像、画布、眼睛和效果均使用空替代文本并设置 aria-hidden。按钮负责无障碍标签、可聚焦性和本地化的 status() 播报。隐藏、死亡或不可交互的状态必须从 Tab 顺序中移除。

验证清单

艺术
  • 核心美术使用相同的 8×8 源像素逻辑单位。
  • 身体基于当前的待机或渲染美术。
  • 身体基线和标准锚点保持固定。
  • 标准眼睛为 1×2 个逻辑像素。
  • DOM 眼睛精灵在叠加层下方不含预绘制的瞳孔。
  • Stable 和 Insiders 的几何形状与 Alpha 遮罩一致。
  • 透明区域保持完全透明。
  • 不出现插值或抗锯齿。
动画
  • 首尾姿势衔接自然,不会突然跳变。
  • 静态减少动态效果姿势能传达状态。
  • 两种变体的帧尺寸和数量一致。
  • 时间数组符合预期的停留时长和循环方式。
  • 使用反向播放时,播放效果正确。
  • 两个朝向下都能正确呈现。
  • 多阶段过渡使用完成信号,而非猜测的延迟。
  • 减少动态效果时,静态回退方案能传达相同结果。
集成
  • 已更新横向/纵向源常量和边界逻辑。
  • 平台裁剪和图层顺序正确。
  • 交互/碰撞几何形状仍以身体为基准。
  • 拖动/点击、唤醒/点击以及指针/键盘手势的归属明确。
  • 用户触发的行为提供本地化屏幕阅读器输出。
  • 视觉子元素设置为 aria-hidden;按钮负责语义和 Tab 键顺序。
  • ChatPetWidget 测试覆盖状态名称、精确时序、几何形状、状态优先级和减少动态效果。
  • 每个运行时状态都映射到预期的、由身体控制的附件轨道。
  • 图集符合其声明的紧凑型(256×192)或宽幅(384×288)单元规格,以及文档规定的列/行约定。
  • 每个配件的颜色/Alpha 区块都与 8×8 逻辑像素网格对齐。
  • 应用文档规定的枢轴点和锚点后,图集美术内容仍位于身体画布范围内。
  • 头部配件按共享穿戴偏移与头部重叠,并在爱心状态期间隐藏。
  • 非对称美术在标准和镜像朝向下都能正确呈现。
  • 添加配件无需导出特定状态的资源或修改渲染器。
  • 减少动态效果的源图使用与其静态身体美术对应的骨架帧。
  • 身体定义的眼睛表情和道具会抑制不兼容的眼睛槽配件。
  • 切换配件时保留当前身体帧和动画计时器。
  • 配件加载失败时,身体仍保持可见,且不会持续重试。

使用 chat/chatPetAccessoryRig/chatPetAccessoryRig/CriticalPoses 组件夹具检查关键动画姿势和减少动态效果姿势,并使用 AllAccessoriesFacing 对比每种外观在两个朝向下的效果。

使用仓库的 unit-tests 技能运行有针对性的单元测试。至少运行 ChatPetWidget 测试套件。

优先导出用于时序、几何形状、随机选择和状态优先级的纯函数辅助工具,然后直接测试这些函数。调度器行为使用虚拟计时器。断言精确的帧时长数组,确保美术和运行时的时序不会各自偏离。

可选:更新公开预览

公开展示页面位于同级的 vscode-chat-pet 仓库中。生产精灵图定稿后,使用其中的 update-pet-previews 技能。

替换现有 APNG 时,优先在 README 中使用新的版本化文件名,以免 GitHub 和浏览器缓存继续显示之前的动画。

评论

支持 Markdown