From a8fe77438286a6cc53131404f54522bf65dc9657 Mon Sep 17 00:00:00 2001 From: Admin Date: Thu, 17 Sep 2026 23:45:52 +0000 Subject: [PATCH] Sync helm sprite sheet to steering keys --- src/mobile-hud.js | 98 +++++++++++++---------------------------------- 1 file changed, 27 insertions(+), 71 deletions(-) diff --git a/src/mobile-hud.js b/src/mobile-hud.js index 3bc21d3..4f2d829 100644 --- a/src/mobile-hud.js +++ b/src/mobile-hud.js @@ -3,7 +3,7 @@ import topHudSrc from './assets/controller/top-hud.js'; import leftStatusSrc from './assets/controller/left-status.js'; import rightControlsSrc from './assets/controller/right-controls.js'; import cannonRoundelSrc from './assets/controller/cannon-roundel.js'; -import helmActionSrc from './assets/controller/helm-action.js'; +import helmSpriteSheetSrc from './assets/controller/helm-action.js'; const isDesktopPointer = window.matchMedia('(hover: hover) and (pointer: fine)'); @@ -433,7 +433,7 @@ if (!isDesktopPointer.matches) { const helmSprite = document.createElement('div'); helmSprite.className = 'steam-helm-sprite'; - helmSprite.style.backgroundImage = `url("${helmActionSrc}")`; + helmSprite.style.backgroundImage = `url("${helmSpriteSheetSrc}")`; radarPiece.appendChild(helmSprite); radarPiece.insertAdjacentHTML('beforeend', ` @@ -462,11 +462,12 @@ if (!isDesktopPointer.matches) { ); const radarContacts = radarPiece.querySelector('#steam-radar-contacts'); - const stick = document.querySelector('#drag-stick'); + // Drive the 3×3 helm sheet from the same arrow-key state emitted by the + // mobile drag control. This keeps the visual frame exactly in sync with + // movement and avoids a second, jitter-prone pointer-direction calculation. + const helmKeys = new Set(); let helmFrame = '1:1'; - let pendingHelmFrame = null; - let helmFrameTimer = null; const applyHelmFrame = (column, row) => { const key = `${column}:${row}`; @@ -475,80 +476,35 @@ if (!isDesktopPointer.matches) { helmSprite.style.backgroundPosition = `${column * 50}% ${row * 50}%`; }; - const resolveHelmFrame = (x, y) => { - const magnitude = Math.hypot(x, y); - if (magnitude < 0.28) return [1, 1]; + const updateHelmFromKeys = () => { + const left = helmKeys.has('ArrowLeft'); + const right = helmKeys.has('ArrowRight'); + const up = helmKeys.has('ArrowUp'); + const down = helmKeys.has('ArrowDown'); - const sector = Math.round(Math.atan2(y, x) / (Math.PI / 4)); - const frames = { - 0: [2, 1], - 1: [2, 2], - 2: [1, 2], - 3: [0, 2], - 4: [0, 1], - '-4': [0, 1], - '-3': [0, 0], - '-2': [1, 0], - '-1': [2, 0], - }; - return frames[sector] || [1, 1]; + const column = left && !right ? 0 : right && !left ? 2 : 1; + const row = up && !down ? 0 : down && !up ? 2 : 1; + applyHelmFrame(column, row); }; - const setHelmFrame = (x, y, immediate = false) => { - const [column, row] = resolveHelmFrame(x, y); - const key = `${column}:${row}`; - - if (key === helmFrame) { - pendingHelmFrame = null; - if (helmFrameTimer) clearTimeout(helmFrameTimer); - helmFrameTimer = null; - return; - } - - if (immediate) { - pendingHelmFrame = null; - if (helmFrameTimer) clearTimeout(helmFrameTimer); - helmFrameTimer = null; - applyHelmFrame(column, row); - return; - } - - if (pendingHelmFrame === key) return; - pendingHelmFrame = key; - if (helmFrameTimer) clearTimeout(helmFrameTimer); - helmFrameTimer = setTimeout(() => { - if (pendingHelmFrame === key) applyHelmFrame(column, row); - pendingHelmFrame = null; - helmFrameTimer = null; - }, 70); + const onHelmKeyDown = (event) => { + if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.code)) return; + helmKeys.add(event.code); + updateHelmFromKeys(); }; - let helmPointer = null; - const updateHelmFrame = (event) => { - if (!stick) return; - const rect = stick.getBoundingClientRect(); - const x = (event.clientX - (rect.left + rect.width / 2)) / (rect.width / 2); - const y = (event.clientY - (rect.top + rect.height / 2)) / (rect.height / 2); - setHelmFrame(x, y); + const onHelmKeyUp = (event) => { + if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.code)) return; + helmKeys.delete(event.code); + updateHelmFromKeys(); }; - stick?.addEventListener('pointerdown', (event) => { - helmPointer = event.pointerId; - updateHelmFrame(event); + window.addEventListener('keydown', onHelmKeyDown); + window.addEventListener('keyup', onHelmKeyUp); + window.addEventListener('blur', () => { + helmKeys.clear(); + applyHelmFrame(1, 1); }); - stick?.addEventListener('pointermove', (event) => { - if (event.pointerId === helmPointer) updateHelmFrame(event); - }); - - const resetHelmFrame = (event) => { - if (helmPointer !== null && event?.pointerId !== undefined && event.pointerId !== helmPointer) return; - helmPointer = null; - setHelmFrame(0, 0, true); - }; - - stick?.addEventListener('pointerup', resetHelmFrame); - stick?.addEventListener('pointercancel', resetHelmFrame); - stick?.addEventListener('lostpointercapture', resetHelmFrame); const radarDots = Array.from({ length: 10 }, () => { const dot = document.createElement('span'); dot.className = 'steam-radar-dot';