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) => {