Use split frame and movable helm knob
This commit is contained in:
parent
4e2a4d7318
commit
c9beda6ea0
@ -3,8 +3,8 @@ import topHudSrc from './assets/controller/top-hud.js';
|
|||||||
import leftStatusSrc from './assets/controller/left-status.js';
|
import leftStatusSrc from './assets/controller/left-status.js';
|
||||||
import rightControlsSrc from './assets/controller/right-controls.js';
|
import rightControlsSrc from './assets/controller/right-controls.js';
|
||||||
import cannonRoundelSrc from './assets/controller/cannon-roundel.js';
|
import cannonRoundelSrc from './assets/controller/cannon-roundel.js';
|
||||||
|
import helmFrameSrc from './assets/controller/helm-frame.js';
|
||||||
const helmSpriteSheetSrc = '/assets/controller/helm-sheet.webp';
|
import helmKnobSrc from './assets/controller/helm-knob.js';
|
||||||
|
|
||||||
const isDesktopPointer = window.matchMedia('(hover: hover) and (pointer: fine)');
|
const isDesktopPointer = window.matchMedia('(hover: hover) and (pointer: fine)');
|
||||||
|
|
||||||
@ -162,22 +162,27 @@ if (!isDesktopPointer.matches) {
|
|||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.steam-helm-frame,
|
.steam-helm-frame {
|
||||||
.steam-helm-inner {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background-repeat: no-repeat;
|
width: 100%;
|
||||||
background-size: 300% 300%;
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.steam-helm-frame {
|
.steam-helm-knob {
|
||||||
background-position: 50% 50%;
|
position: absolute;
|
||||||
}
|
left: 50%;
|
||||||
|
top: 46%;
|
||||||
.steam-helm-inner {
|
width: 32%;
|
||||||
background-position: 50% 50%;
|
height: auto;
|
||||||
clip-path: circle(36% at 50% 48%);
|
object-fit: contain;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 3;
|
||||||
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
.steam-helm-label {
|
.steam-helm-label {
|
||||||
@ -201,6 +206,7 @@ if (!isDesktopPointer.matches) {
|
|||||||
height: 69%;
|
height: 69%;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.steam-radar-player,
|
.steam-radar-player,
|
||||||
@ -442,15 +448,19 @@ if (!isDesktopPointer.matches) {
|
|||||||
const radarPiece = document.createElement('div');
|
const radarPiece = document.createElement('div');
|
||||||
radarPiece.className = 'steam-piece steam-radar-wrap';
|
radarPiece.className = 'steam-piece steam-radar-wrap';
|
||||||
|
|
||||||
const helmFrame = document.createElement('div');
|
const helmFrame = document.createElement('img');
|
||||||
helmFrame.className = 'steam-helm-frame';
|
helmFrame.className = 'steam-helm-frame';
|
||||||
helmFrame.style.backgroundImage = `url("${helmSpriteSheetSrc}")`;
|
helmFrame.src = helmFrameSrc;
|
||||||
|
helmFrame.alt = '';
|
||||||
|
helmFrame.draggable = false;
|
||||||
radarPiece.appendChild(helmFrame);
|
radarPiece.appendChild(helmFrame);
|
||||||
|
|
||||||
const helmInner = document.createElement('div');
|
const helmKnob = document.createElement('img');
|
||||||
helmInner.className = 'steam-helm-inner';
|
helmKnob.className = 'steam-helm-knob';
|
||||||
helmInner.style.backgroundImage = `url("${helmSpriteSheetSrc}")`;
|
helmKnob.src = helmKnobSrc;
|
||||||
radarPiece.appendChild(helmInner);
|
helmKnob.alt = '';
|
||||||
|
helmKnob.draggable = false;
|
||||||
|
radarPiece.appendChild(helmKnob);
|
||||||
|
|
||||||
radarPiece.insertAdjacentHTML('beforeend', `
|
radarPiece.insertAdjacentHTML('beforeend', `
|
||||||
<div id="steam-radar-contacts">
|
<div id="steam-radar-contacts">
|
||||||
@ -479,48 +489,18 @@ if (!isDesktopPointer.matches) {
|
|||||||
|
|
||||||
const radarContacts = radarPiece.querySelector('#steam-radar-contacts');
|
const radarContacts = radarPiece.querySelector('#steam-radar-contacts');
|
||||||
|
|
||||||
// Drive the 3×3 helm sheet from the same arrow-key state emitted by the
|
const setHelmKnob = (x = 0, y = 0) => {
|
||||||
// mobile drag control. This keeps the visual frame exactly in sync with
|
const maxOffset = Math.min(radarPiece.clientWidth * 0.20, 32);
|
||||||
// movement and avoids a second, jitter-prone pointer-direction calculation.
|
const px = Math.max(-1, Math.min(1, x)) * maxOffset;
|
||||||
const helmKeys = new Set();
|
const py = Math.max(-1, Math.min(1, y)) * maxOffset;
|
||||||
let activeHelmFrame = '1:1';
|
helmKnob.style.transform = `translate(-50%, -50%) translate(${px}px, ${py}px)`;
|
||||||
|
|
||||||
const applyHelmFrame = (column, row) => {
|
|
||||||
const key = `${column}:${row}`;
|
|
||||||
if (key === activeHelmFrame) return;
|
|
||||||
activeHelmFrame = key;
|
|
||||||
helmInner.style.backgroundPosition = `${column * 50}% ${row * 50}%`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateHelmFromKeys = () => {
|
window.addEventListener('airship:helm-vector', (event) => {
|
||||||
const left = helmKeys.has('ArrowLeft');
|
setHelmKnob(event.detail?.x ?? 0, event.detail?.y ?? 0);
|
||||||
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('blur', () => setHelmKnob(0, 0));
|
||||||
const radarDots = Array.from({ length: 10 }, () => {
|
const radarDots = Array.from({ length: 10 }, () => {
|
||||||
const dot = document.createElement('span');
|
const dot = document.createElement('span');
|
||||||
dot.className = 'steam-radar-dot';
|
dot.className = 'steam-radar-dot';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user