西南政法大学——猫咪陪伴学习桌宠
> 一只固定在桌面上、会陪你学习说话、还能帮你收纳文件/图片到桌面的校园猫。
> 整套引擎基于 PySide6,已在 macOS 上反复跑通并修过若干关键 bug。框架在 references/framework/。
🚨 代理行为准则(首次调用必读)
当用户第一次调用本 skill,且尚未提供「开做前收集清单」里的材料时:
- 不要直接写代码、不要复制框架、不要生成图片。 先逐项向用户索取缺失内容。
- 明确告知用户「✅ 收到 XX。还差 YY,下一步你需要做的是……」。
- 全部必需材料到齐后再进入正文「完整工作流」。
- 做完后明确告诉用户「下一步你需要做什么来验证」(跑
run_pet.sh/python run_pet.py/ 看日志)。
📋 开做前收集清单
| 项目 | 必需 | 说明 / 格式 |
|---|---|---|
| ⭐ 猫咪形象图 | 必需 | · PNG 透明背景最佳(直接可用)<br>· JPG/照片 → 用 references/framework/scripts/remove_bg.py 或在线工具抠成透明 PNG<br>· 主体单一(猫+马桶一类),背景简洁最好抠<br>· 尺寸建议 ≥256px |
| ⭐ 宠物名字 | 必需 | 显示在右键菜单、通知、以及桌面收纳目录「{名字}暂存处」 |
| 目标平台 | 可选 | macOS(已验证)/ Windows(已支持,见 references/windows-packaging.md) |
| 说话主题 | 可选 | 默认「上学/学习陪伴」;要换主题改 commands.py |
> ⚠️ 铁律 1(抠图):AI 生成的图背景若不干净(白边/灰雾/场景背景),不得硬修或继续用,
> 必须明确告知用户「背景没抠干净」,提醒用户手动抠图,并提供一张干净透明 PNG,收到后再继续。
🎯 完整工作流
> ⚠️ 严格按顺序。每步都有可验证产出物。
Phase 0:环境(一次性)
cd references/framework
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt # PySide6 + Pillow + numpy
> 🪟 Windows:同 macOS 步骤建 venv + 装依赖,然后 python run_pet.py 启动、python stop_pet.py 关闭。详见 references/windows-packaging.md。
Phase 1:准备猫咪素材(关键,易踩坑)
- 用户提供猫照 → 若要动漫化,用 ImageGen image-to-image 生成 3D 黏土风 +
transparent background。 - 目视检查背景是否透明干净(这是最容易翻车的一步,见铁律 1)。
- ❌ 不干净 → 提醒用户手动抠图,提供干净透明 PNG。
- ✅ 干净 → 进入下一步。 - 把干净透明 PNG 放进
references/framework/samples/,命名如maipian_up.png(仰望款)、maipian_bored.png(不耐烦款)。 - 若有多只造型,在
app.py的_CAT_VARIANT_LABELS和launch_campus里登记文件名与造型名。
Phase 2:起名 + 收纳目录
- 名字在调用
launch_campus时传入;代码会在桌面自动建~/Desktop/{名字}暂存处。 - 左半拖入 → 秒收进「暂存处」根目录;右半拖入 → 弹框在「暂存处」内新建/选子文件夹。
- 收纳是 移动(shutil.move),原文件不再保留。
Phase 3:启动
./run_pet.sh 140 samples/maipian_up.png samples/maipian_bored.png
# 或直接:python run_pet.py
> 🪟 Windows 用户:python run_pet.py 启动、python stop_pet.py 关闭(需先建 venv + 装依赖)。
> 完整部署 / 打包成 exe 见 references/windows-packaging.md。
Phase 4:调参(可选)
references/framework/desktop_pet/app.py 顶部 / 相关常量:
DEFAULT_PET_SIZE = 140 # 猫身尺寸(px)
# 光环
HALO_MAX = 3.5 # 文件靠近时光环最大放大倍数(350%)
# 待机光环 200%(cat_r*2.0);靠近呼吸 280%~350%(缩0~20%)
SPEAK_INTERVAL_MS = 8_000 # 每 8 秒弹一条学习主题气泡
SPEAK_HOLD_MS = 5_000 # 每条停留 5 秒后淡出
Phase 5:验证清单
- [ ] 小猫出现在桌面、固定不动(鼠标可拖)
- [ ] 每隔约 8 秒弹一条萌系气泡,停留 5 秒后消失,循环不息
- [ ] 待机时猫周围有 200% 暖橙光环
- [ ] 拖文件靠近 → 光环放大到 350% 并一鼓一吸呼吸、出现扩散圆环
- [ ] 左拖文件 → 文件被移进桌面「{名字}暂存处」根目录(原位不留)
- [ ] 右拖文件 → 弹框居中桌面,可在「暂存处」内命名收纳
- [ ] 右键切换造型可来回切(不被卡死)
📂 框架结构(references/framework/)
framework/
├── desktop_pet/ ← 引擎(一般不需改,换皮/换话即可)
│ ├── __init__.py
│ ├── __main__.py ← CLI 入口(加载 samples)
│ ├── app.py ← 桌宠窗口 + 光环 + 拖拽收纳 + 说话节奏 + 切换菜单
│ ├── pet.py ← 精灵渲染(加载透明 PNG、呼吸/眨眼、固定不游走)
│ ├── bubble.py ← 萌系奶油气泡(独立顶层窗口,自动淡出自毁)
│ ├── collector.py ← 文件收纳(move 进「{名字}暂存处」、弹框命名)
│ ├── commands.py ← 说话内容(上学/学习主题,改这里)
│ ├── hotspots.py ← 热点编辑器(双击开关,可选)
│ ├── obstacles.py ← macOS 窗口枚举(可选,本桌宠默认关闭游走)
│ └── desktop_icons.py ← 桌面图标枚举(可选)
├── samples/ ← 用户放入透明 PNG 猫咪素材(部署时自行准备,见 Phase 1)
├── cases/ai-failure/ ← AI 生成失败案例说明(印证「铁律 1」,图片需用户自行查看)
├── scripts/remove_bg.py ← 代码兜底去白底(仅纯白底输入有效)
├── requirements.txt ← PySide6 + Pillow + numpy
├── run_pet.py / stop_pet.py← 跨平台启停(PID 精确配对,Windows 走 taskkill)
├── run_pet.sh ← macOS 快速启动脚本
└── packaging/
├── macos/ ← macOS 打包目录(.app 需本地 PyInstaller 构建,不含预编译二进制)
└── windows/ ← PyInstaller 打包成独立 exe(launcher.py + 用户自建 build 脚本)
⚠️ 关键陷阱(我们踩过并修好的,必须避免)
| 坑 | 现象 | 解决(已在代码里) |
|---|---|---|
| AI 背景抠不干净 | 要求 transparent 却得到白墙/灰雾/场景 | 铁律 1:不硬修,提醒用户手动抠图给干净 PNG |
| 切换猫只切一次 | 切完一次后再点切换没反应 | set_image 不再就地改共享 PetDefinition;菜单用 deepcopy 隔离 + 只刷 pixmap |
| 收纳变复制而非移动 | 原文件还在原位 | collector.py 用 shutil.move(不是 copy2) |
| 光环被窗口裁切 | 大光环看不到完整圆 | 窗口按 HALO_MAX 自动算 halo_margin,保证最大光环不裁切 |
| 弹窗太靠桌面下 | 右拖弹框位置偏低 | _open_collect_dialog 用 setParent(None) + 屏幕中心定位(避开 macOS sheet) |
| 气泡不显示 | 气泡被父窗口裁到边界外 | 气泡 parent=None 独立顶层窗口 |
| 气泡只弹一次 | 定时器到点后 C++ 对象已删,再建抛异常 | _speak_bubble 先清引用 + try/except + 自毁发 closed 信号 |
| 代码抠图误删主体 | 白毛被吃 / 背景残留 | remove_bg.py flood-fill 去白底 + 边连通性保护;仅纯白底有效 |
🧪 自排查清单(结果与预期不符时逐条过)
当桌宠表现 / 图片效果与预期不一致,按此顺序排查:
- 图片背景是否干净透明? → 不干净 → 执行铁律 1(提醒手动抠图)
- 代码抠图是否吃掉主体? → 检查输入是否纯白底;非纯白底跳过代码抠图,直接用用户手动抠好的透明 PNG
- 文件/路径是否正确? → samples 目录层级 + 文件名与
__main__.py的parent.parent定位 +_CAT_VARIANT_LABELS匹配 - 切换猫能来回切吗? → 检查
deepcopy隔离是否生效 - 收纳是移动还是复制? → 确认
collector用move - 光环裁切了吗? → 检查
halo_margin是否 ≥HALO_MAX光环半径 - 弹窗居中了吗? → 检查
setParent(None)+ 屏幕中心 - 改完重启了吗? → 必须
python stop_pet.py→ 重新python run_pet.py
📋 自定义参数速查
# app.py
DEFAULT_PET_SIZE = 140 # 猫身尺寸
HALO_MAX = 3.5 # 靠近时最大光环倍数;窗口留白按它算
SPEAK_INTERVAL_MS = 8_000 # 气泡间隔
SPEAK_HOLD_MS = 5_000 # 单条停留
# pet.py —— 固定型桌宠:sprite._allow_somersault = False(不游走/不翻筋斗)
# commands.py —— 学习/上学主题闲聊池 + 功能型回复,改这里换话术
# collector.py —— BASE_DIR = ~/Desktop/{名字}暂存处;shutil.move 收纳
🤝 给同事导出 / 复用说明
- 本 skill 不含预置图片素材(大赛平台限制,无法上传二进制图片文件)。部署时用户需按「Phase 1」准备透明 PNG 猫咪图放入
samples/目录。 cases/ai-failure/case_readme.md保留失败案例的文字说明(印证「铁律 1」),对应图片需用户自行查看本地副本。- 具体项目 config(路径、名字)不打包,同事按本机环境写。