关于 chat-pet-sprite-creation
用于在现有代码库中制作和审查聊天宠物像素图的 Skill,涵盖素材、动画、合成与交互约束,并以当前代码和测试为准。
主要功能
- 01基准精灵图与身体锚点
- 02逻辑像素和画布规则
- 03DOM 眼睛与眨眼合成
- 04Stable 与 Insiders 调色板一致
- 05精灵图表与减少动态效果素材
- 06配饰图集与连接框架
适用场景
- 01设计新的宠物反应状态
- 02添加或审查精灵动画
- 03检查眼睛覆盖层和朝向行为
- 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 的完整历史。规则发生冲突时,请按以下优先级处理:
- 当前代码和测试
- 最新的相关开放 PR
- 较新的已合并 PR
- 较早的历史行为
特别是,动画清理 PR #330399 已取代旧的复活标记流程及此前的若干精灵图和计时假设。
| PR | 持久有效的经验 |
|---|---|
| #327063 | 宠物是一个语义按钮;精灵图画布、图像、眼睛和特效仅用于视觉呈现,并设为 aria-hidden。通过 FileAccess 解析资源 URL。 |
| #327412 | 将反应建模为显式状态。不要立即重复普通的随机反应;罕见变形应单独抽样。 |
| #327588 | 对精灵图像使用双缓冲,并仅在待加载图像加载完成后切换。加载新来源时,绝不要清空当前活动精灵图。 |
| #327696 | Stable/Insiders 是一种有类型且持久化的外观选择。保持变体命名和几何形状的系统性。 |
| #327714 | 动画美术资源应采用水平精灵图表,并提供专门制作的静态减弱动态效果 PNG。计时属于运行时数据,而非图像元数据。 |
| #328334 | “逃跑中”等持久行为应放在服务状态中。多阶段动画应根据完成信号推进,而不是依赖猜测的延迟。 |
| #328480 | 拖动结束后不得同时触发点击反应。共享指针事件的手势需要明确的抑制或所有权机制。 |
| #328530 | 唤醒操作会消耗唤醒宠物的交互;不得同时触发随机反应。减弱动态效果时可以跳过唤醒过渡。 |
| #329121 | 合并注视更新;文档隐藏时暂停精灵图计时器,并根据经过的时间恢复,而不是重播错过的帧。 |
| #329347 | 将像素美术中的姿势变化保留在精灵图帧中,将空间运动放在布局、CSS 或物理逻辑中。根据过渡信号完成跌落。 |
| #329729 | 开始反应前先面向交互方向。为每种瞬态状态设置明确的持续时间,并使用真实的完成事件衔接后续阶段。 |
| #329852 | 指针和键盘手势需要产生等效结果。减弱动态效果时,应保留状态变化,同时移除位移动画。 |
| #329867 | 注意力动画应有时长限制;即使确认仍在等待中,拍手也应在确认注意力窗口结束后停止。 |
| #330160 | 眼睛是复合的运行时图层,具有跟踪和眨眼模式。快速改变朝向可能触发独立的眩晕状态。宽幅美术资源必须遵守实时边界。 |
| #330275 | 物理计算应使用身体占地范围、限制帧步长,并明确标记撞击时刻。飞行过程中布局变化时,重新计算几何信息。 |
| #330399 | 最新动画约定:宽幅睡眠/唤醒美术资源、考虑帧的眨眼合成、固定朝向的装饰,以及使用同一张特效精灵图先反向消失、再正向重现。 |
逻辑像素
规范的美术单位是一个逻辑像素:
8×8个源像素- 按照标准的
96×96源图 →48×48显示比例,对应4×4个 CSS 像素
核心轮廓、面部特征、道具和重复细节都必须使用相同的逻辑像素比例。不要仅为了容纳更多细节,就用更小或更大的色块绘制新对象。
特效可以有意细分逻辑像素,例如小星星、气泡或弧形运动效果,但细分必须:
- 用于无法在核心网格上清晰呈现的特定特效。
- 在整个特效中保持一致。
- 绝不能由抗锯齿或重采样产生。
仅使用最近邻渲染。保持背景透明、像素边缘清晰。不要引入模糊、羽化透明度、颜色插值或意外的非网格缩放。
从基准图开始
绝不要凭记忆重新绘制宠物身体。
- 静止、由指针驱动或嬉戏状态应以当前的静止精灵图为基准。
- 请求/处理状态应以当前的渲染中精灵图为基准。
- 先复制完整身体,然后只修改新状态所需的部分。
这样可以保持:
- 身体的宽度和高度
- 底部基线
- 天线根部和间距
- 高光与阴影色阶
- 眼窝
- 碰撞/交互范围
第一个和最后一个关键姿势必须能平滑过渡到静止或渲染中状态,不出现身体位置、轮廓、基线或缩放突变。
画布与锚定
默认源画布为 96×96,即 12×12 个逻辑像素。
仅当内容有意延伸至规范身体框之外时,才使用更大的画布:
- 终端或按钮可能需要额外宽度。
- 便签、星星或气泡可能需要额外高度。
- 身体必须保持锚定在基准精灵图中的准确位置。
不要将身体置于更宽画布的中央。让身体保持在规范的 96×96 区域内,并允许道具/特效超出边界。请在 chatPetWidget.ts 中声明每个非标准源尺寸,并更新宽精灵图的边界处理。
运行时的碰撞和移动框应对应宠物身体,而非装饰性溢出部分。
眼睛
标准睁眼尺寸为 1×2 个逻辑像素:
8×16个源像素4×8个 CSS 像素
只有当状态表达特殊表情时,才使用不同的眼睛形状,例如睡觉、头晕、喜爱、担忧或受到撞击。
DOM 眼睛图层
DOM 眼睛图层有两种独立模式:
- 追踪提供视线、朝向、眨眼和拖动表情。
- 眨眼可让非追踪状态暂时显示 DOM 眼睛,并可根据精灵图帧改变表现。
使用运行时视线的状态必须使用不含眼睛的 *-tracking-96 资源。使用 DOM 眨眼的状态(例如 PR #330399 中的打字、按下按钮或喜爱状态)也必须为叠加层留出相应的瞳孔区域。
添加或修改使用 DOM 眼睛的状态时:
- 保持精灵图中的眼窝为空。
- 视情况在
doesChatPetStateTrackCursor中添加光标行为。 - 视情况在
doesChatPetStateBlink(state, frameIndex)中添加眨眼行为。 - 验证两个朝向下的高眼位眨眼、状态专属眼睛高度和指针偏移。
- 验证有意停止眨眼的帧,例如保持终端姿势的帧。
绝不要将绘制在精灵图中的瞳孔与运行时眼睛叠加层结合使用。
绘制眼睛的状态
表情固定的状态应将眼睛绘制在美术资源中,并禁用光标追踪。除非表情有意改变眼睛位置,否则应保持标准眼睛位置。
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,但要限制积分步长,防止慢帧后发生穿透。 - 飞行过程中布局发生变化时,重新读取投掷几何信息。
运行时接线
添加状态时,更新所有适用的部分:
- 将状态添加到
ChatPetState。 - 在
getChatPetSpriteName中映射文件名。 - 在
getChatPetFrameDurations中添加帧时长。 - 声明非标准的源宽度/高度常量。
- 在
getSpriteSources中注册动画和减少动态效果的来源。 - 选择光标跟踪和基于帧的眨眼行为。
- 选择单次播放、循环、反向播放或静态迭代行为。
- 添加临时状态的持续时间和触发条件。
- 为多阶段状态添加确定性的完成转换。
- 添加朝向、悬垂、固定装饰、裁剪或 CSS 处理。
- 为用户触发的交互添加本地化 ARIA 状态播报。
- 手势可发现/实用时,更新无障碍帮助。
- 更新相关单元测试。
添加美术资源时,必须同时完成运行时约定。
保持视觉元素静默:图像、画布、眼睛和效果均使用空替代文本并设置 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 和浏览器缓存继续显示之前的动画。