Use split frame and movable helm knob

This commit is contained in:
Admin 2026-09-18 00:29:25 +00:00
parent 4e2a4d7318
commit c9beda6ea0

View File

@ -3,8 +3,8 @@ 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';
const helmSpriteSheetSrc = '/assets/controller/helm-sheet.webp';
import helmFrameSrc from './assets/controller/helm-frame.js';
import helmKnobSrc from './assets/controller/helm-knob.js';
const isDesktopPointer = window.matchMedia('(hover: hover) and (pointer: fine)');
@ -162,22 +162,27 @@ if (!isDesktopPointer.matches) {
aspect-ratio: 1;
}
.steam-helm-frame,
.steam-helm-inner {
.steam-helm-frame {
position: absolute;
inset: 0;
background-repeat: no-repeat;
background-size: 300% 300%;
width: 100%;
height: 100%;
object-fit: contain;
pointer-events: none;
z-index: 1;
}
.steam-helm-frame {
background-position: 50% 50%;
}
.steam-helm-inner {
background-position: 50% 50%;
clip-path: circle(36% at 50% 48%);
.steam-helm-knob {
position: absolute;
left: 50%;
top: 46%;
width: 32%;
height: auto;
object-fit: contain;
transform: translate(-50%, -50%);
pointer-events: none;
z-index: 3;
will-change: transform;
}
.steam-helm-label {
@ -201,6 +206,7 @@ if (!isDesktopPointer.matches) {
height: 69%;
border-radius: 50%;
overflow: hidden;
z-index: 2;
}
.steam-radar-player,
@ -442,15 +448,19 @@ if (!isDesktopPointer.matches) {
const radarPiece = document.createElement('div');
radarPiece.className = 'steam-piece steam-radar-wrap';
const helmFrame = document.createElement('div');
const helmFrame = document.createElement('img');
helmFrame.className = 'steam-helm-frame';
helmFrame.style.backgroundImage = `url("${helmSpriteSheetSrc}")`;
helmFrame.src = helmFrameSrc;
helmFrame.alt = '';
helmFrame.draggable = false;
radarPiece.appendChild(helmFrame);
const helmInner = document.createElement('div');
helmInner.className = 'steam-helm-inner';
helmInner.style.backgroundImage = `url("${helmSpriteSheetSrc}")`;
radarPiece.appendChild(helmInner);
const helmKnob = document.createElement('img');
helmKnob.className = 'steam-helm-knob';
helmKnob.src = helmKnobSrc;
helmKnob.alt = '';
helmKnob.draggable = false;
radarPiece.appendChild(helmKnob);
radarPiece.insertAdjacentHTML('beforeend', `
<div id="steam-radar-contacts">
@ -479,48 +489,18 @@ if (!isDesktopPointer.matches) {
const radarContacts = radarPiece.querySelector('#steam-radar-contacts');
// 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 activeHelmFrame = '1:1';
const applyHelmFrame = (column, row) => {
const key = `${column}:${row}`;
if (key === activeHelmFrame) return;
activeHelmFrame = key;
helmInner.style.backgroundPosition = `${column * 50}% ${row * 50}%`;
const setHelmKnob = (x = 0, y = 0) => {
const maxOffset = Math.min(radarPiece.clientWidth * 0.20, 32);
const px = Math.max(-1, Math.min(1, x)) * maxOffset;
const py = Math.max(-1, Math.min(1, y)) * maxOffset;
helmKnob.style.transform = `translate(-50%, -50%) translate(${px}px, ${py}px)`;
};
const updateHelmFromKeys = () => {
const left = helmKeys.has('ArrowLeft');
const right = helmKeys.has('ArrowRight');
const up = helmKeys.has('ArrowUp');
const down = helmKeys.has('ArrowDown');
const column = left && !right ? 0 : right && !left ? 2 : 1;
const row = up && !down ? 0 : down && !up ? 2 : 1;
applyHelmFrame(column, row);
};
const onHelmKeyDown = (event) => {
if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.code)) return;
helmKeys.add(event.code);
updateHelmFromKeys();
};
const onHelmKeyUp = (event) => {
if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.code)) return;
helmKeys.delete(event.code);
updateHelmFromKeys();
};
window.addEventListener('keydown', onHelmKeyDown);
window.addEventListener('keyup', onHelmKeyUp);
window.addEventListener('blur', () => {
helmKeys.clear();
applyHelmFrame(1, 1);
window.addEventListener('airship:helm-vector', (event) => {
setHelmKnob(event.detail?.x ?? 0, event.detail?.y ?? 0);
});
window.addEventListener('blur', () => setHelmKnob(0, 0));
const radarDots = Array.from({ length: 10 }, () => {
const dot = document.createElement('span');
dot.className = 'steam-radar-dot';