Desktop Pet(桌寵產生器)
把一張圖片變成會在桌面上活動的互動式桌寵。流程:分析圖片 → 去背製作 sprite → 產生個性 config → 啟動 Electron 引擎。
目錄結構
desktop-pet/
├── engine/ # Electron 桌寵引擎(共用,只需 npm install 一次)
├── scripts/
│ └── prepare_sprite.py # 去背 + 裁切 + 縮放
└── pets/<slug>/ # 每隻寵物一個資料夾
├── sprite.png # 去背後的圖
└── config.json # 名字、個性、台詞
建立新桌寵的流程
1. 確認環境(第一次才需要)
engine/node_modules不存在 → 在engine/執行npm installpython -c "import rembg"失敗 →pip install rembg onnxruntime pillow
2. 取得並分析圖片
需要圖片的檔案路徑(使用者只貼圖沒給路徑時,請他提供路徑)。 用 Read 工具看圖,判斷:
- 物種與個性:決定名字(向使用者提議,可自訂)、叫聲、食物 emoji、台詞風格
- facing:圖中角色面向哪邊(
left/right,正面朝前就填right) - 適合的
callSound:bark(狗)/meow(貓)/chirp(鳥)/squeak(小動物、史萊姆等)
3. 製作 sprite
python scripts/prepare_sprite.py <輸入圖片> pets/<slug>/sprite.png
- 輸出 JSON:
width、height、skipped_rembg(圖片本身已有透明背景時會跳過去背) - 第一次執行會下載 u2net 模型(約 170MB),需要一點時間
- 去背品質差(主體破碎)時,建議使用者換一張主體清晰、背景乾淨的圖
4. 撰寫 config.json
{
"name": "小柴",
"species": "dog",
"sprite": "sprite.png",
"scale": 0.6,
"facing": "right",
"food": "🍖",
"callSound": "bark",
"phrases": {
"greet": ["嗨!主人~"],
"call": ["主人~我在這裡!"],
"lonely": ["主人…你在忙嗎?"],
"arrive": ["我來了!"],
"feedStart": ["哇!有吃的!"],
"feedDone": ["好好吃~謝謝主人!"],
"petted": ["好舒服~"],
"sleep": ["晚安…"],
"wake": ["醒來了!"]
}
}
- scale:目標是螢幕上高度約 120~180px →
scale = 150 / sprite高度(取一位小數) - phrases:用使用者慣用的語言撰寫(跟使用者對話是中文就寫繁中,英文就寫英文),依角色個性撰寫(每類 2~3 句更生動);省略的類別有預設值(繁中)
5. 啟動
Set-Location <skill目錄>\engine
npm start -- --pet "<pets/<slug> 的絕對路徑>"
用 run_in_background 啟動。多隻桌寵 = 啟動多個 process(各指定不同 --pet)。
也可以告訴使用者不靠指令的啟動方式:雙擊 skill 根目錄的 start-pet.bat(啟動第一隻寵物)或 start-pet.bat <寵物名>;把它的捷徑放到 shell:startup 資料夾可開機自動啟動。
6. 告訴使用者怎麼玩
| 互動 | 操作 |
|---|---|
| 撫摸 | 滑鼠移到寵物身上輕輕來回移動(會冒愛心) |
| 餵食 | 在寵物身上按右鍵 → 🍽️ 餵食(食物掉下來,牠會走過去吃) |
| 呼喚主人 | 右鍵 → 📣 呼喚主人(講話+叫聲) |
| 召喚過來 | Ctrl + 左鍵點桌面任意處;備用熱鍵 Ctrl+Alt+P(叫到滑鼠位置) |
| 拖曳 | 按住左鍵把牠拎起來,放開會掉回地面 |
| 睡覺/離開 | 右鍵選單 |
牠也會自己閒逛、無聊時呼喚主人、太久沒人理會睡著。
疑難排解
- Ctrl+點擊沒反應:uiohook-napi 載入失敗(主程序 console 有警告),改用 Ctrl+Alt+P;或重新
npm install - 寵物擋住桌面點擊:只有滑鼠懸停在寵物上時視窗才攔截滑鼠,其餘區域皆穿透;若異常,重啟該寵物
- 關閉某隻寵物:右鍵選單「離開」,或結束對應的 electron process
- 除錯:設環境變數
PET_DEBUG=1再啟動,會開 DevTools 並輸出狀態轉換 log,renderer 提供window.__pet(state/feed/call/summon)