制作一个像素吉祥物
一个吉祥物是一个包含CSS步进动画的像素艺术SVG文件。它可以有多个状态(空闲、开心、睡觉、行走、攻击……),每个状态是根元素上的一个类:<svg class="happy"> 会播放 happy 状态。通过代码构建吉祥物,永远不要手动编辑数百个<rect>:本技能的 scripts/ 文件夹(以下称为 <kit>)包含一个小工具包和一个工作示例。所有内容均使用Python标准库;无需安装任何东西。
在绘制任何内容之前,请阅读与该文件同目录下的 LESSONS.md。它列出了制作第一个吉祥物时出现的问题,包括症状、原因和修复方法,如果跳过阅读,大部分问题会再次出现。
文件存放位置
询问用户希望将吉祥物存放在哪里。如果他们不指定,则使用 ~/pixel-mascots/<name>/(在Windows上为 %USERPROFILE%\pixel-mascots\<name>\):
| 文件 | 说明 |
|---|---|
make_<name>.py | 构建脚本:每次修改都编辑此文件并重新运行 |
<name>.svg | 构建输出,即吉祥物本身 |
<name>_overrides.json | 用户在工作室中手动编辑的内容,由构建脚本最后应用 |
sheet.png | 预览图,每个状态一帧静态画面 |
<name> 由小写字母、数字和连字符组成。切勿将用户文件放入 <kit> 中:它属于已安装的插件,在更新时会被替换。
运行脚本
使用机器上可用的Python:python3(macOS、Linux),python(Windows),或在存在shim阻止裸python时使用uv run python。构建脚本会导入工具包,因此运行时需要将 <kit> 添加到 PYTHONPATH 环境变量:
PYTHONPATH="<kit>" python3 make_<name>.py <name>.svg
$env:PYTHONPATH = "<kit>"; python make_<name>.py <name>.svg
preview.py 和工作室不需要 PYTHONPATH;工作室会为它运行的构建脚本设置该变量。
SVG必须满足的要求
- 每个根类对应一个状态。使用
.<state> .part{...}选择器定义每个状态的样式;类名是用户定义的状态名(小写,连字符)。构建脚本会在根元素上写入一个默认状态(s.svg(..., state="idle")),因此该文件在浏览器或<img>标签中会自动播放动画;应用程序可以通过更改根元素的class来显示其他状态。如果用户没有命名任何状态,则创建一个:idle。 - 将所有颜色放入其自身
<style>中的CSS类中。CSS变量(var(--accent,#hex))只能在那里使用,绝不能用作fill=属性。 - 使用
steps(1)关键帧进行动画,并移动整个单元格(在单元格的viewBox中使用translateY(-1px))或闪烁不透明度。 - 包含一个
<title>(替代文本),并且没有<script>、on…=属性、外部图像、字体或链接,以确保可以在任何地方安全显示。 - 通过根元素上的
width/height设置绘制尺寸,必须是网格的整数倍:32个单元格对应128像素(每单元格4像素),20个单元格对应80像素。 - 除非用户另有说明,否则应尊重减少动效设置:
@media (prefers-reduced-motion:reduce){*{animation:none!important}}。
工作流程
-
明确吉祥物是什么、其状态以及3-5个核心特征。 询问哪些特征在128像素下具有辨识度,只夸大这些特征,并舍弃其他所有内容。询问需要哪些状态;如果没有答案,则制作一个空闲循环。由用户的想法决定,而不是这里的示例。如果用户分享了其他艺术家的作品,只能将其用于方向参考(比例、轮廓样式、特征的绘制方式):绝不能复制他们的像素,也绝不能将受版权保护的角色放入分享或发布的构建中。
-
在下表中找到其类型。 该表说明了要拆分哪些部分(每个部分独立动画)以及哪些部分可以携带次级运动,这正是让吉祥物感觉有生命而不是一个弹跳贴纸的关键。
类型 典型识别特征 部件,从后到前 次级运动 人形角色 发型和颜色、眼睛、一个配饰、服装、手持物品 hair-back(后发)、body(身体)、head(头部:面部、刘海、前发)、prop(道具)头部上下摆动/点头、头发跟随、道具摆动 动物 耳朵、花纹、尾巴、口鼻部、眼睛颜色 tail(尾巴)、body(身体)、ears(耳朵,嵌套在头部内)、head(头部)耳朵拍打、尾巴摇摆、头部倾斜 物体(灯、杯子、植物、扫地机器人) 轮廓、一个标志性细节 back(背部:线缆、支架)、body(身体)、face(画在它上面的脸)、moving bits(活动部件)蒸汽或叶子摆动、灯光闪烁、轮子步进 生物/团块/机器人 轮廓、一个奇特特征(角、触角、面罩、发光) back(背部)、body(身体)、head(头部)、appendage(附肢)挤压和拉伸、触角摆动、发光闪烁 没有脸部的吉祥物仍然需要可读的状态:改变姿势、特效和速度,而不是表情。
-
选择画布。 简单形状且特征少的用20×20;需要多个特征或有能表达情绪的脸部的用32×32。对于角色,裁剪至胸部或臀部:脸部特征和身份特征比腿部更需要空间。每单元格绘制4像素。
-
复制模板,
<kit>/example_mascot.py(Miso,一只具有三个状态的猫),到吉祥物文件夹中的make_<name>.py,设置NAME,并替换形状和状态。保留构建脚本:SVG是构建输出。保留模板的最后一步apply_overrides(...):它应用用户在工作室中的手动编辑(第10步),因此重新构建永远不会丢失它们。 -
从后到前绘制,每个独立运动的部分作为一个部件。将附肢嵌套在其所连接的部件内(耳朵在头部内),以便它跟随该部件的运动并仍能独立运动。工具包工具:
rect(矩形)、ellipse(椭圆)、polygon(多边形,用于耳朵、鳍、角)、path(路径,用于尾巴、线缆、茎)、line(线)、zigzag_bottom(锯齿底部,用于头发或刘海边缘)、paint(..., only=...)(在现有形状上绘制细节)、shade_edges(阴影和边缘)。最后调用一次s.outline(),以便每个部件都有自己的轮廓。对于有头发的角色,请遵循LESSONS.md中的“有头发的角色”。 -
每个状态一个面部(或姿势),作为通过不透明度规则切换的组:默认使用
f-open(眼睛睁开),再加上每个状态适合的内容。当反应在形状上不同而不是仅在颜色上不同时,效果最好:闭合的笑眼^ ^、半闭的眼睛、张开的嘴巴、阴影带。在有刘海的角色的脸上绘制时,跳过头发单元格。- 让每个状态适合角色。当某个状态不适合他们时,询问,并提供他们自己故事中的时刻:标志性的手势或场景。大的轮廓变化在128像素下可读;小的细节(2像素的宝石、一张开合的小嘴)则不可读。
- 一个状态可以交换整个部件,而不仅仅是面部:配饰戴上或摘下、睡觉时拉下的帽子。将每个可交换的部件作为独立的部件,并用
.<state> .part{opacity:…}隐藏或显示它。将每个此类规则限定在一个状态内,以便其他状态保留其部件。 - 当用户不确定时,构建替代方案而不是争论一个方案:让构建脚本接受一个变体名称作为参数,将每个变体构建到自己的文件,并并排显示。保留用户喜欢的变体:恢复应该只是一个参数的事情。
-
特效 使用
s.fx(name, cls, frames):闪光、速度线、Z字、晃动标记、汗滴。帧变为s1,s2… 以实现不同步的动画。 -
运动:使用
steps(1)关键帧和整单元格移动(像素艺术应该步进,而不是滑动)。整个图形位于一个.rig组中,该组可以跳跃或摇摆;在此基础上:- 头部独立摆动、倾斜或点头(最多2个单元格);
- 附肢(头发、耳朵、尾巴、触角)最多延迟四分之一周期跟随;半周期会使它们处于对立侧,看起来像拖尾;
- 道具和活动部件略微偏离节拍。 空闲循环应缓慢而微小:呼吸、眨眼、尾巴摆动。
-
构建并查看(在展示给任何人之前)。命令如“运行脚本”部分所示:
PYTHONPATH="<kit>" python3 make_<name>.py <name>.svg python3 <kit>/preview.py <name>.svg sheet.png然后查看
sheet.png:每状态一帧静态画面,从左到右排列。预览仅显示静止姿势。要查看动画,在后台启动工作室,并在浏览器中打开http://127.0.0.1:8765/(如果存在内置浏览器面板,则使用它):python3 <kit>/studio/server.py --svg <name>.svg --build make_<name>.py它会在各自的框架中显示每个状态的动画。
--states a,b用于选择和排序状态(默认:CSS使用的每个状态,按首次出现的顺序);--port更改端口。用户通过截图进行审查,并经常用红色标记问题:将标记与你已知的特征(眼睛行、嘴巴)对齐映射到单元格,然后沿着它们重新绘制。在进行不会改变可见内容的重构后,构建旧版本和新版本,并逐字节比较文件(cmp或fc /b)。 -
手动编辑。 当用户想要自己修复像素时,将他们引导至工作室的
/editor.html:绘画、擦除和拾取颜色(按状态),撤销,然后保存,这将写入<name>_overrides.json并重新构建。每个像素属于一个部件并随其移动;编辑器会显示该像素属于哪个部件以及哪些状态显示它。没有构建脚本的吉祥物也能工作(省略--build):工作室会在SVG旁边保留一个未修改的副本和编辑内容在<name>_studio/中,并将结果写入SVG。在用户编辑后,在更改任何其他内容之前,读取他们的覆盖文件和重新构建的预览,并判断编辑是否看起来是意外的(一个远离其他部分的孤立像素)。 -
交付:告知用户SVG的位置、默认播放的状态,以及如何显示其他状态(设置根元素的class;
<img>无法做到,因此切换状态的应用程序需要内联SVG或将其加载到<object>或<iframe>中)。
profile.json(用于显示吉祥物的应用程序)
应用程序可能不仅需要根类:根元素上的CSS变量、额外类、固定的状态标签。放置在 <kit> 中 preview.py 旁边的 profile.json 可以告知预览和工作室。每个键都是可选的:
{
"states": [{ "class": "happy", "name": "happy", "label": "happy · 成功时", "style": "--speed:.5s" }],
"rootClass": "always-animate",
"swatches": { "var": "--accent", "label": "强调色", "colors": ["#8FA8E8", "#ED93B1"] },
"workdir": "~/my-app/studio"
}
states 固定顺序、按钮名称、标题和每个状态的根样式;rootClass 在每个框架中添加到根元素;swatches 添加设置CSS变量的颜色按钮;workdir 对于没有构建脚本的吉祥物,替换 <name>_studio/。此插件不附带任何文件。
本技能中的文件
| 文件 | 说明 |
|---|---|
LESSONS.md | 哪些有效哪些无效,包括原因和修复方法。请先阅读。 |
scripts/pixelkit.py | 形状(矩形、椭圆、多边形、路径、线条)、部件、着色、逐部件轮廓、SVG输出。 |
scripts/example_mascot.py | Miso:一个32x32的猫,具有空闲、快乐和睡眠状态;需要复制的模板。 |
scripts/preview.py | PNG表,每状态一帧静态画面,仅使用标准库。 |
scripts/pixel_overrides.py | 将手动编辑应用于完成的SVG;构建脚本最后调用它。 |
scripts/studio/ | server.py + site/:每个状态动画,以及一个像素编辑器,适用于任何吉祥物。仅在本地运行(127.0.0.1)。 |