滑鼠移到寵物身上時跳躍,對齊 Codex 的 hover 行為
摘要:
游標壓在人物像素上時播 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 <noreply@anthropic.com>
This commit is contained in:
@@ -85,6 +85,7 @@ npm run autostart:install # (可選)開機自動啟動
|
|||||||
| 左鍵點一下 | 揮手(若有非固定的氣泡,先關閉氣泡) |
|
| 左鍵點一下 | 揮手(若有非固定的氣泡,先關閉氣泡) |
|
||||||
| 左鍵拖曳 | 搬家;往左播 running-left、往右播 running-right;放開後位置寫入設定檔 |
|
| 左鍵拖曳 | 搬家;往左播 running-left、往右播 running-right;放開後位置寫入設定檔 |
|
||||||
| 右鍵 / 系統匣左鍵 | 開啟選單 |
|
| 右鍵 / 系統匣左鍵 | 開啟選單 |
|
||||||
|
| 滑鼠移到她身上 | 跳躍 3 次(Codex 的 hover 行為),離開後回到原本狀態 |
|
||||||
| 滑鼠靠近 | 盯著游標看(可在選單關閉) |
|
| 滑鼠靠近 | 盯著游標看(可在選單關閉) |
|
||||||
|
|
||||||
**選單功能**
|
**選單功能**
|
||||||
@@ -121,6 +122,7 @@ npm run autostart:install # (可選)開機自動啟動
|
|||||||
| `SessionEnd` | | 移除該 session | 最後一個結束時 👋 掰掰 |
|
| `SessionEnd` | | 移除該 session | 最後一個結束時 👋 掰掰 |
|
||||||
| (無事件) | 游標移動 | 16 方向 `look` | |
|
| (無事件) | 游標移動 | 16 方向 `look` | |
|
||||||
| (無事件) | 拖曳 | `running-left` / `running-right` | |
|
| (無事件) | 拖曳 | `running-left` / `running-right` | |
|
||||||
|
| (無事件) | 滑鼠移到人物像素上 | `jumping` × 3 | |
|
||||||
|
|
||||||
規則:
|
規則:
|
||||||
|
|
||||||
|
|||||||
+22
-6
@@ -110,6 +110,7 @@ function startAnim(anim, now) {
|
|||||||
let bubbleTimer = null;
|
let bubbleTimer = null;
|
||||||
let bubbleSticky = false;
|
let bubbleSticky = false;
|
||||||
let ignoringMouse = true;
|
let ignoringMouse = true;
|
||||||
|
let hovered = false;
|
||||||
let pressed = null;
|
let pressed = null;
|
||||||
let lastReported = "";
|
let lastReported = "";
|
||||||
|
|
||||||
@@ -519,11 +520,14 @@ setInterval(() => {
|
|||||||
|
|
||||||
// ---------- 滑鼠:點穿 / 拖曳 / 點擊 / 右鍵 ----------
|
// ---------- 滑鼠:點穿 / 拖曳 / 點擊 / 右鍵 ----------
|
||||||
|
|
||||||
function overOpaque(x, y) {
|
function overBubble(x, y) {
|
||||||
if (!bubble.classList.contains("hidden")) {
|
if (bubble.classList.contains("hidden")) return false;
|
||||||
const r = bubble.getBoundingClientRect();
|
const r = bubble.getBoundingClientRect();
|
||||||
if (x >= r.left && x <= r.right && y >= r.top && y <= r.bottom) return true;
|
return x >= r.left && x <= r.right && y >= r.top && y <= r.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 壓在人物的不透明像素上(透明處要讓滑鼠穿過去)
|
||||||
|
function overSprite(x, y) {
|
||||||
const r = canvas.getBoundingClientRect();
|
const r = canvas.getBoundingClientRect();
|
||||||
if (x < r.left || x >= r.right || y < r.top || y >= r.bottom) return false;
|
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));
|
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) {
|
function setIgnore(ignore) {
|
||||||
if (ignore === ignoringMouse) return;
|
if (ignore === ignoringMouse) return;
|
||||||
ignoringMouse = ignore;
|
ignoringMouse = ignore;
|
||||||
@@ -552,11 +564,15 @@ window.addEventListener("mousemove", (e) => {
|
|||||||
}
|
}
|
||||||
return;
|
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) => {
|
document.addEventListener("mouseout", (e) => {
|
||||||
if (!e.relatedTarget && !pressed) setIgnore(true);
|
if (e.relatedTarget || pressed) return;
|
||||||
|
setHovered(false);
|
||||||
|
setIgnore(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("mousedown", (e) => {
|
window.addEventListener("mousedown", (e) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user