From 7d4c5d849ce586430ab5e1fd61c24047a5876170 Mon Sep 17 00:00:00 2001 From: JianMiau Date: Fri, 21 Aug 2026 14:49:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=BB=91=E9=BC=A0=E7=A7=BB=E5=88=B0=E5=AF=B5?= =?UTF-8?q?=E7=89=A9=E8=BA=AB=E4=B8=8A=E6=99=82=E8=B7=B3=E8=BA=8D=EF=BC=8C?= =?UTF-8?q?=E5=B0=8D=E9=BD=8A=20Codex=20=E7=9A=84=20hover=20=E8=A1=8C?= =?UTF-8?q?=E7=82=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 摘要: 游標壓在人物像素上時播 jumping 3 次再沉澱回慢速 idle,離開後回到原本狀態。 根本原因: Codex 的寵物元件(codex-pet-assets)在 hover 時會把顯示狀態換成 jumping (respondToHover && hovered ? "jumping" : state),桌面寵物那層透過 pet-area-hover-changed 事件驅動它。本程式只有點擊會揮手,滑鼠停上去沒有反應。 影響: 滑鼠移到她身上沒有任何回饋,與 Codex 的手感不同。 修法: - 把 overOpaque 拆成 overBubble 與 overSprite:點穿判定兩者都算,hover 反應只看人物像素, 游標停在氣泡上不會觸發跳躍。 - 新增 setHovered:進入人物像素時 play("jumping", STATE_REPEATS),與 Codex 的 f("jumping") 相同是播 3 次;一次性動作或拖曳進行中不打斷。mouseout 離開視窗時清除 hover 狀態。 - 移除已無人使用的 overOpaque。 驗證: 以 ELECTRON_RUN_AS_NODE 讀打包後 app.asar 內的 renderer.js,確認 setHovered、 play("jumping", STATE_REPEATS)、mousemove/mouseout 的呼叫都在出貨檔案裡,overOpaque 已不存在。 Co-Authored-By: Claude Fable 5 --- README.md | 2 ++ renderer/renderer.js | 30 +++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 279f617..92ce24a 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ npm run autostart:install # (可選)開機自動啟動 | 左鍵點一下 | 揮手(若有非固定的氣泡,先關閉氣泡) | | 左鍵拖曳 | 搬家;往左播 running-left、往右播 running-right;放開後位置寫入設定檔 | | 右鍵 / 系統匣左鍵 | 開啟選單 | +| 滑鼠移到她身上 | 跳躍 3 次(Codex 的 hover 行為),離開後回到原本狀態 | | 滑鼠靠近 | 盯著游標看(可在選單關閉) | **選單功能** @@ -121,6 +122,7 @@ npm run autostart:install # (可選)開機自動啟動 | `SessionEnd` | | 移除該 session | 最後一個結束時 👋 掰掰 | | (無事件) | 游標移動 | 16 方向 `look` | | | (無事件) | 拖曳 | `running-left` / `running-right` | | +| (無事件) | 滑鼠移到人物像素上 | `jumping` × 3 | | 規則: diff --git a/renderer/renderer.js b/renderer/renderer.js index 794e3cd..82420e5 100644 --- a/renderer/renderer.js +++ b/renderer/renderer.js @@ -110,6 +110,7 @@ function startAnim(anim, now) { let bubbleTimer = null; let bubbleSticky = false; let ignoringMouse = true; +let hovered = false; let pressed = null; let lastReported = ""; @@ -519,11 +520,14 @@ setInterval(() => { // ---------- 滑鼠:點穿 / 拖曳 / 點擊 / 右鍵 ---------- -function overOpaque(x, y) { - if (!bubble.classList.contains("hidden")) { - const r = bubble.getBoundingClientRect(); - if (x >= r.left && x <= r.right && y >= r.top && y <= r.bottom) return true; - } +function overBubble(x, y) { + if (bubble.classList.contains("hidden")) return false; + const r = bubble.getBoundingClientRect(); + return x >= r.left && x <= r.right && y >= r.top && y <= r.bottom; +} + +// 壓在人物的不透明像素上(透明處要讓滑鼠穿過去) +function overSprite(x, y) { const r = canvas.getBoundingClientRect(); if (x < r.left || x >= r.right || y < r.top || y >= r.bottom) return false; const px = Math.floor((x - r.left) * (canvas.width / r.width)); @@ -535,6 +539,14 @@ function overOpaque(x, y) { } } +// Codex 的寵物 hover 時會把狀態換成 jumping(codex-pet-assets 的 respondToHover ? "jumping" : state), +// 跳 STATE_REPEATS 次後沉澱回慢速 idle,滑鼠離開再回到原本的狀態。 +function setHovered(on) { + if (on === hovered) return; + hovered = on; + if (on && !overlay && !drag) play("jumping", STATE_REPEATS); +} + function setIgnore(ignore) { if (ignore === ignoringMouse) return; ignoringMouse = ignore; @@ -552,11 +564,15 @@ window.addEventListener("mousemove", (e) => { } return; } - setIgnore(!overOpaque(e.clientX, e.clientY)); + const onSprite = overSprite(e.clientX, e.clientY); + setHovered(onSprite); + setIgnore(!(onSprite || overBubble(e.clientX, e.clientY))); }); document.addEventListener("mouseout", (e) => { - if (!e.relatedTarget && !pressed) setIgnore(true); + if (e.relatedTarget || pressed) return; + setHovered(false); + setIgnore(true); }); window.addEventListener("mousedown", (e) => {