滑鼠移到寵物身上時跳躍三次,hover 判定改用矩形
摘要:
把 hover 跳躍加回來,並把觸發判定從逐像素 alpha 改成人物方框。
根本原因:
1. hover 跳躍在「逐項對照 Codex」那次被換成 proximity 版面(理由是 Codex 的
respondToHover 全 app 沒有開啟),上一次移除浮出選單鈕時把整套版面拿掉,
跳躍也跟著沒了,變成 hover 完全沒有反應。
2. 先前的 hover 判定用 ctx.getImageData 逐像素測 alpha。sprite 每一格的輪廓不同,
游標停著不動時,人物身上同一點會隨著動畫在不透明與透明之間變化,
造成 setHovered 在 true/false 間高速抖動(實測 2 ms 內來回多次),
連帶 pet:ignore-mouse 也被瘋狂切換。
影響:
滑鼠移到寵物身上沒有任何反應;即使觸發也會因抖動而重複進出 hover 狀態。
修法:
- 還原 setHovered:進入時 play("jumping", STATE_REPEATS),對應 Codex 的
`respondToHover && hovered ? "jumping" : state` 走 f() 播 3 次後沉澱;
一次性動作或拖曳進行中不打斷,離開視窗時清除。
- 新增 overPetArea:hover 用 canvas 的矩形判定,與 Codex 的 pet-area-hover-changed
同樣是用 rect 算的。點穿判定維持逐像素 alpha,透明處仍然點得到底下的視窗。
- README 的日常使用、行為對照表、與 Codex 的對照三處同步更新,
對照表補上 jumping 與 hover 判定兩列。
驗證:
- 在 renderer 暫時加診斷 log 實測,確認進入人物區時
`setHovered true overlay=null` 之後 overlay 變成 jumping,觸發路徑正確;
同一份 log 也是抖動問題的證據來源。改成矩形判定後移除診斷。
- 以 ELECTRON_RUN_AS_NODE 讀打包後 app.asar:版本 2.0.0、hover 跳躍與矩形判定都在、
點穿仍用 alpha、診斷已移除、無選單鈕殘留、右鍵選單仍在,九項全過。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -124,6 +124,7 @@ function startAnim(anim, now) {
|
||||
let bubbleTimer = null;
|
||||
let bubbleSticky = false;
|
||||
let ignoringMouse = true;
|
||||
let hovered = false; // 游標是否壓在人物的不透明像素上
|
||||
let pressed = null;
|
||||
let lastReported = "";
|
||||
|
||||
@@ -552,6 +553,23 @@ function overSprite(x, y) {
|
||||
}
|
||||
}
|
||||
|
||||
// hover 判定用人物方框,不用逐像素 alpha:sprite 每一格的輪廓不同,逐像素會讓游標停著不動時
|
||||
// 也在 true/false 之間高速抖動。Codex 的 pet-area-hover 同樣是用矩形算的。
|
||||
function overPetArea(x, y) {
|
||||
const r = canvas.getBoundingClientRect();
|
||||
return x >= r.left && x < r.right && y >= r.top && y < r.bottom;
|
||||
}
|
||||
|
||||
// Codex 的寵物元件在 hover 時會把狀態換成 jumping(codex-pet-assets 的
|
||||
// `respondToHover && hovered ? "jumping" : state`),走 f() 的規則播 3 次後沉澱回慢速 idle。
|
||||
// 那個 prop 在 Codex 桌面寵物那層沒有開啟,這裡選擇打開它。
|
||||
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;
|
||||
@@ -569,11 +587,14 @@ window.addEventListener("mousemove", (e) => {
|
||||
}
|
||||
return;
|
||||
}
|
||||
setHovered(overPetArea(e.clientX, e.clientY));
|
||||
// 點穿判定仍看實際像素,透明處要能點到底下的視窗
|
||||
setIgnore(!(overSprite(e.clientX, e.clientY) || overBubble(e.clientX, e.clientY)));
|
||||
});
|
||||
|
||||
document.addEventListener("mouseout", (e) => {
|
||||
if (e.relatedTarget || pressed) return;
|
||||
setHovered(false);
|
||||
setIgnore(true);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user