桌面宠物 · 换形象技能(v8 单窗口合成架构)
把当前的「布丁店长」桌面宠物,换成任意其它动漫卡通造型。
使用者需要提供:
- 1 张空闲 GIF:宠物待机时展示(自动呼吸、可拖拽、点击冒爱心)
- 若干个动态 GIF(1~N 个):每 5 秒随机挑一个播放(如「眨眼 / 伸懒腰 / 招手 / 跳跃」)
本技能负责:抠白底 → 生成素材 → 注册特效 → 打包 exe。
〇、适用前提(给协作者)
- 本机需已有桌面宠物工程
E:\desktop-pet\,含desktop_pet.py、assets\、.venv\
(Python 3.12,已装 Pillow / pystray / pywin32 / opencv-python / numpy / PyInstaller)。 - 如需在另一台机器协作:把整个
E:\desktop-pet目录复制过去即可(.venv 随工程走)。 - 本技能附带的
references/gen_swap.py自包含(仅依赖 Pillow/opencv/numpy),用工程.venv运行。
一、触发条件
用户说类似:
- "把桌面宠物换成一只柴犬" / "换成一个二次元角色"
- "桌面宠物用我这套图:1 张待机 + N 张动作"
- "替换桌面宠物的形象" + 提交 1 个空闲 GIF + 若干个动作 GIF
二、向用户收集素材(必须齐)
用 AskUserQuestion 或对话确认,明确告诉用户需要:
| 序号 | 文件 | 说明 | 命名建议 |
|---|---|---|---|
| 1 | 空闲图 | GIF(或 PNG),待机展示 | idle.gif / idle.png |
| 2…N | 动作 | 若干个随机动作 GIF | 动作名.gif(如 眨眼.gif、伸懒腰.gif) |
> 动作名会作为特效 key 显示在日志,也决定随机池成员;用中文或英文都可(如 眨眼、stretch)。
> 建议至少包含一个「眨眼」类,让待机更有生气(当前布丁版就是眨眼 + 伸懒腰)。
> 数量不限(1 个也可以,只是随机性较低)。
收到文件后,集中放到一个工作目录,例如 E:\desktop-pet\swap_in\。
三、准备工程(每个形象一个独立副本,避免互相覆盖)
> E:\desktop-pet\assets\ 是布丁的素材,直接覆盖会丢失布丁。换形象请先复制整个工程:
cp -r E:/desktop-pet E:/desktop-pet-柴犬 # 每个形象一个目录
之后所有操作都在新目录(如 E:\desktop-pet-柴犬\)进行。
四、抠白底 + 生成素材(用附带的脚本)
脚本:references/gen_swap.py(需工程的 .venv,已含 Pillow / opencv-python / numpy)。
cd E:/desktop-pet-柴犬
/e/desktop-pet/.venv/Scripts/python.exe \
<本技能目录>/references/gen_swap.py \
--idle swap_in/idle.gif \
--action 眨眼=swap_in/眨眼.gif \
--action 伸懒腰=swap_in/伸懒腰.gif \
--action 招手=swap_in/招手.gif \
--out E:/desktop-pet-柴犬/assets \
--method light # 浅色/白底用 light;深色/纯色背景改用 flood
脚本会生成:
- cat.png / cat_blink.png / cat_side.png —— 都取自空闲图首帧(运行时待机固定显示;眨眼已由特效承担,故后两者等同首帧)
- effect_眨眼.png / effect_伸懒腰.png / effect_招手.png —— 对应动作动画(APNG)
抠图算法说明(脚本内置 remove_bg_light / remove_bg_flood,由 --method 选):
- light(默认):中性白连通分量法——背景=中性浅白且亮(B>210、近中性),猫身=暖色(B 偏低);
只把「接触图像边界」的连通分量判为外部背景,浅色角色内部不会被误删。适用于白底/浅色底。
- flood:从四角 floodFill 填充背景色(自动采样左上角像素)。适用于深色 / 纯色背景(light 法会抠不掉)。
- 脚本只负责抠透明,不缩放;缩放由 desktop_pet.py 加载时统一处理——默认动作按内容高度 PET_H=200,
空闲图与旧眨眼 blink 按宽度 PET_W=135(高约216)。
- alpha 二值化内置:np.where(bg,0,255),背景=0、角色=255,无半透明像素,杜绝紫边。
自检(可选,确认无紫边隐患)
/e/desktop-pet/.venv/Scripts/python.exe - <<'PY'
from PIL import Image; import numpy as np
for f in ["cat.png","effect_眨眼.png"]:
a = np.array(Image.open("assets/"+f).convert("RGBA"))[:,:,3]
print(f, "半透明像素数=", int(((a>0)&(a<255)).sum())) # 必须为 0
PY
五、注册这些特效(改 desktop_pet.py)
打开新工程里的 desktop_pet.py,把 effect_files 字典改成收集到的动作(key 与第四步文件名一致):
self.effect_files = {
"眨眼": _find_asset("effect_眨眼.png", ["effect_眨眼.gif"]),
"伸懒腰": _find_asset("effect_伸懒腰.png", ["effect_伸懒腰.gif"]),
"招手": _find_asset("effect_招手.png", ["effect_招手.gif"]),
}
_start_random_effect 会从 effect_cache 的 key 里随机选,加 key 即自动进入随机池,无需改其它代码。
空闲图已通过 CAT_OPEN_PATH = _find_asset("cat.png") 自动生效(无需额外注册)。
> 触发节奏:特效结束 → 冷却 SPECIAL_COOLDOWN_MS=5000(5 秒)→ 再随机播下一个,正好满足「5 秒后随机展示」。
六、打包
cd E:/desktop-pet-柴犬
tasklist | grep -i DesktopPet && taskkill /F /IM DesktopPet.exe
/e/desktop-pet-柴犬/.venv/Scripts/python.exe -m py_compile desktop_pet.py
/e/desktop-pet-柴犬/.venv/Scripts/python.exe build_pet.py # → dist/DesktopPet.exe
# 复制为正式名(绕开 safe-delete,用 Python)
/e/desktop-pet-柴犬/.venv/Scripts/python.exe - <<'PY'
import os, shutil
src="dist/DesktopPet.exe"; dst="dist/布丁店长.exe"
if os.path.exists(dst): os.remove(dst)
shutil.copy2(src, dst)
print("size=%.1fMB" % (os.path.getsize(dst)/1024/1024))
PY
双击 dist/布丁店长.exe(或 dist/DesktopPet.exe)验证。若形象大小与位置不对:
- 用本技能的 PET_H(动作高度)、PET_W(空闲/旧眨眼宽度)调首帧对齐;
- 或生成「修改前后」预览 PNG 对比(用 Pillow 把素材按比例贴到同一画布),确认无误再打包。
七、常见坑(换形象必读)
- 【最关键】素材里绝不能留半透明像素 —— 否则出现「紫边 / 紫块」
- 原理:宠物窗口靠-transparentcolor色键(品红#ff00fe)实现异形透明,而色键是二值的:
像素要么精确等于#ff00fe被完全抠掉,要么完全不透明,没有中间态。
- 后果:任何半透明像素(alpha 介于 1~254)都会与品红底混合成亮紫色且无法抠掉 → 角色周围一圈紫边;
成片半透明 → 一整块亮紫块。
- 做法:抠完背景后必须做 alpha 二值化,且必须放在 resize 之后。gen_swap.py已内置
(np.where(bg,0,255))。用户在 GIMP/PS 手修图时若留羽化边缘,仍会出紫边,需回脚本重抠或导出硬边。 - 背景颜色决定抠图方法:白底/浅色底用
--method light(默认);深色 / 纯色背景必须加--method flood,
否则 light 法识别不出背景、整张保留不透明。 - 「日志说宠物活着但看不见」= 被别的进程/窗口盖住了,不要往「为什么隐藏」方向查(当前单窗口架构已无此问题)。
- 空闲图与动作首帧务必同源:不同源会导致待机↔动作切换时忽胖忽瘦、位置跳变
(代码按「不透明内容底边中心」锚点对齐,同源才稳)。 - 打包前先杀干净旧进程:否则覆盖 exe 会报
PermissionError: [WinError 32] 另一个程序正在使用此文件。每次只保留唯一正式 exe,
旧构建移入dist/_old_builds/——留一堆测试 exe 会让用户反复跑错版本、白测好几轮。 - 每个形象独立工程目录:别直接覆盖
E:\desktop-pet\assets\,否则丢失布丁原素材(第三节)。
八、交付清单
完成后告诉用户:
1. exe 路径(如 E:\desktop-pet-柴犬\dist\布丁店长.exe)
2. 用了哪 1 张空闲图 + 哪 N 个动作
3. 如想换回布丁:E:\desktop-pet\dist\布丁店长.exe 仍在
4. 后续加动作/功能 → 用 布丁店长 技能(同一套代码架构)