Use transparent health sprite sheets in mobile HUD
This commit is contained in:
parent
1473bf80df
commit
9ae626d5f8
@ -1,7 +1,7 @@
|
||||
import Phaser from 'phaser';
|
||||
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 playerHealthSrc from './assets/controller/player-health.js';
|
||||
import enemyHealthSrc from './assets/controller/enemy-health.js';
|
||||
import cannonRoundelSrc from './assets/controller/cannon-roundel.js';
|
||||
import helmFrameSrc from './assets/controller/helm-frame.js';
|
||||
import helmKnobSrc from './assets/controller/helm-knob.js';
|
||||
@ -51,8 +51,9 @@ if (!isDesktopPointer.matches) {
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: min(21.1vw, 95px);
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
aspect-ratio: 960 / 246;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.steam-top-value {
|
||||
@ -74,15 +75,24 @@ if (!isDesktopPointer.matches) {
|
||||
.steam-kills { left: 78.2%; }
|
||||
.steam-range { left: 91.1%; }
|
||||
|
||||
.steam-player-card,
|
||||
.steam-enemy-card {
|
||||
top: clamp(80px, 10.3vh, 90px);
|
||||
aspect-ratio: 300 / 108;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 400% 300%;
|
||||
background-position: 0 0;
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.steam-player-card {
|
||||
left: -1%;
|
||||
top: clamp(80px, 10.3vh, 90px);
|
||||
width: 53%;
|
||||
}
|
||||
|
||||
.steam-enemy-card {
|
||||
right: -1%;
|
||||
top: clamp(80px, 10.3vh, 90px);
|
||||
width: 46%;
|
||||
}
|
||||
|
||||
@ -92,68 +102,36 @@ if (!isDesktopPointer.matches) {
|
||||
transform: translate(-50%, -50%);
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.steam-card-name {
|
||||
top: 28%;
|
||||
color: #f6d58e;
|
||||
font-size: clamp(8px, 2.2vw, 11px);
|
||||
letter-spacing: .06em;
|
||||
}
|
||||
|
||||
.steam-player-card .steam-card-name {
|
||||
left: 58%;
|
||||
top: 31%;
|
||||
left: 61%;
|
||||
}
|
||||
|
||||
.steam-enemy-card .steam-card-name {
|
||||
left: 51%;
|
||||
top: 12%;
|
||||
left: 39%;
|
||||
}
|
||||
|
||||
.steam-card-value {
|
||||
top: 67%;
|
||||
color: #fff0bd;
|
||||
font-size: clamp(8px, 2.4vw, 12px);
|
||||
}
|
||||
|
||||
.steam-player-card .steam-card-value {
|
||||
left: 61%;
|
||||
top: 67%;
|
||||
}
|
||||
|
||||
.steam-enemy-card .steam-card-value {
|
||||
left: 38%;
|
||||
top: 32%;
|
||||
}
|
||||
|
||||
.steam-bar {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
border-radius: 999px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.steam-player-card .steam-bar {
|
||||
left: 32.3%;
|
||||
top: 56.2%;
|
||||
width: 57%;
|
||||
height: 20%;
|
||||
}
|
||||
|
||||
.steam-enemy-card .steam-bar {
|
||||
left: 7.5%;
|
||||
top: 24.8%;
|
||||
width: 60.5%;
|
||||
height: 16%;
|
||||
}
|
||||
|
||||
.steam-bar-fill {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform-origin: left center;
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(180deg, #ffb445 0%, #d43e2f 42%, #821b1c 100%);
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 0 5px rgba(219,63,40,.45);
|
||||
opacity: .9;
|
||||
left: 39%;
|
||||
}
|
||||
|
||||
.steam-radar-wrap {
|
||||
@ -414,7 +392,7 @@ if (!isDesktopPointer.matches) {
|
||||
left: 50%;
|
||||
width: min(64vw, 560px);
|
||||
height: auto;
|
||||
aspect-ratio: 4.74 / 1;
|
||||
aspect-ratio: 960 / 246;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
@ -537,15 +515,28 @@ if (!isDesktopPointer.matches) {
|
||||
<span class="steam-top-value steam-range" data-steam="range">--</span>
|
||||
`);
|
||||
|
||||
addPiece('steam-player-card', leftStatusSrc, `
|
||||
const addHealthPiece = (className, src, inner = '') => {
|
||||
const piece = document.createElement('div');
|
||||
piece.className = `steam-piece ${className}`;
|
||||
piece.style.backgroundImage = `url("${src}")`;
|
||||
|
||||
const probe = new Image();
|
||||
probe.addEventListener('load', () => airshipLog('hud:health-sheet-loaded', { component: className }));
|
||||
probe.addEventListener('error', () => airshipLog('hud:health-sheet-error', { component: className }, 'error'));
|
||||
probe.src = src;
|
||||
|
||||
if (inner) piece.insertAdjacentHTML('beforeend', inner);
|
||||
hud.appendChild(piece);
|
||||
return piece;
|
||||
};
|
||||
|
||||
const playerHealthPiece = addHealthPiece('steam-player-card', playerHealthSrc, `
|
||||
<span class="steam-card-name">SPARROW</span>
|
||||
<div class="steam-bar"><div class="steam-bar-fill" data-steam="player-fill"></div></div>
|
||||
<span class="steam-card-value" data-steam="player-hull">100/100</span>
|
||||
`);
|
||||
|
||||
addPiece('steam-enemy-card', rightControlsSrc, `
|
||||
const enemyHealthPiece = addHealthPiece('steam-enemy-card', enemyHealthSrc, `
|
||||
<span class="steam-card-name">PIRATE</span>
|
||||
<div class="steam-bar"><div class="steam-bar-fill" data-steam="enemy-fill"></div></div>
|
||||
<span class="steam-card-value" data-steam="enemy-hull">CLEAR</span>
|
||||
`);
|
||||
|
||||
@ -644,6 +635,17 @@ if (!isDesktopPointer.matches) {
|
||||
|
||||
const clamp01 = (value) => Math.max(0, Math.min(1, value));
|
||||
|
||||
const healthFrame = (current, max) => {
|
||||
const pct = max > 0 ? clamp01(current / max) : 0;
|
||||
return Math.max(0, Math.min(11, Math.round((1 - pct) * 11)));
|
||||
};
|
||||
|
||||
const setHealthFrame = (piece, frame) => {
|
||||
const col = frame % 4;
|
||||
const row = Math.floor(frame / 4);
|
||||
piece.style.backgroundPosition = `${(col / 3) * 100}% ${(row / 2) * 100}%`;
|
||||
};
|
||||
|
||||
const updateRadar = (scene) => {
|
||||
const pirates = scene.pirates?.getChildren?.().filter((pirate) => pirate?.active) || [];
|
||||
|
||||
@ -690,8 +692,8 @@ if (!isDesktopPointer.matches) {
|
||||
fields.range.textContent = Number.isFinite(range) ? `${Math.round(range)}m` : '--';
|
||||
fields['player-hull'].textContent = `${playerHull}/100`;
|
||||
fields['enemy-hull'].textContent = pirate ? `${enemyHull}/120` : 'CLEAR';
|
||||
fields['player-fill'].style.transform = `scaleX(${clamp01(playerHull / 100)})`;
|
||||
fields['enemy-fill'].style.transform = `scaleX(${pirate ? clamp01(enemyHull / 120) : 0})`;
|
||||
setHealthFrame(playerHealthPiece, healthFrame(playerHull, 100));
|
||||
setHealthFrame(enemyHealthPiece, pirate ? healthFrame(enemyHull, 120) : 11);
|
||||
|
||||
const statusText = scene.status?.text?.trim?.() || '';
|
||||
fields.status.textContent = statusText;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user