fix: radar compass always heading-up with rotating N/E/S/W labels, fix reopen bug

- Compass is now always heading-up: player facing direction is fixed
  pointing up, N/E/S/W labels rotate around the edge as player turns
- Fix: reopening a closed radar window now resends start_radar command
  so streaming resumes without needing a full page refresh

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-08 12:07:40 +02:00
parent 3852cf205e
commit 502467e075

View file

@ -3608,7 +3608,14 @@ function showRadarWindow(name) {
}
);
if (!isNew) return;
if (!isNew) {
// Window was hidden, not destroyed — re-register and restart streaming
radarWindows[name] = win;
if (socket && socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({ player_name: name, command: 'start_radar' }));
}
return;
}
radarWindows[name] = win;
win.dataset.character = name;
@ -3636,14 +3643,7 @@ function showRadarWindow(name) {
rangeLabel.appendChild(rangeSelect);
controls.appendChild(rangeLabel);
const headingToggle = document.createElement('label');
headingToggle.className = 'radar-heading-toggle';
const headingCheck = document.createElement('input');
headingCheck.type = 'checkbox';
headingCheck.checked = false;
headingToggle.appendChild(headingCheck);
headingToggle.appendChild(document.createTextNode(' Heading-up'));
controls.appendChild(headingToggle);
// Compass is always heading-up (player facing direction = up)
content.appendChild(controls);
@ -3672,7 +3672,6 @@ function showRadarWindow(name) {
win._radarCanvas = canvas;
win._radarListBody = listBody;
win._radarRangeSelect = rangeSelect;
win._radarHeadingCheck = headingCheck;
// Send start_radar command
if (socket && socket.readyState === WebSocket.OPEN) {
@ -3688,7 +3687,6 @@ function updateRadarWindow(msg) {
const canvas = win._radarCanvas;
const listBody = win._radarListBody;
const range = parseFloat(win._radarRangeSelect.value) || RADAR_DEFAULT_RANGE;
const headingUp = win._radarHeadingCheck.checked;
const objects = msg.objects || [];
const playerEW = msg.player_ew;
@ -3726,44 +3724,48 @@ function updateRadarWindow(msg) {
ctx.moveTo(0, cy); ctx.lineTo(size, cy);
ctx.stroke();
// Heading line (north indicator or player heading)
const headingRad = headingUp ? 0 : (-playerHeading * Math.PI / 180);
// Always heading-up: player facing direction = up on canvas.
// Compass labels rotate around the edge based on player heading.
const headingRad = playerHeading * Math.PI / 180;
const compassLabels = [
{ label: 'N', angle: 0 },
{ label: 'E', angle: Math.PI / 2 },
{ label: 'S', angle: Math.PI },
{ label: 'W', angle: -Math.PI / 2 },
];
ctx.font = 'bold 12px monospace';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
compassLabels.forEach(({ label, angle }) => {
// Rotate compass direction by negative heading so labels move as player turns
const a = angle - headingRad;
const lx = cx + Math.sin(a) * (cx - 12);
const ly = cy - Math.cos(a) * (cx - 12);
ctx.fillStyle = label === 'N' ? '#cc4444' : '#888';
ctx.fillText(label, lx, ly);
});
// Facing direction indicator (always points up from center)
ctx.strokeStyle = '#666';
ctx.lineWidth = 1;
ctx.beginPath();
const nhx = cx + Math.sin(headingRad) * cx * 0.9;
const nhy = cy - Math.cos(headingRad) * cx * 0.9;
ctx.moveTo(cx, cy);
ctx.lineTo(nhx, nhy);
ctx.lineTo(cx, cy - cx * 0.85);
ctx.stroke();
// N label
ctx.fillStyle = '#888';
ctx.font = '10px monospace';
ctx.textAlign = 'center';
const nlx = cx + Math.sin(headingRad) * (cx - 10);
const nly = cy - Math.cos(headingRad) * (cx - 10);
ctx.fillText('N', nlx, nly + 3);
// Rotation angle for heading-up mode (negate to counter-rotate world)
const rotAngle = headingUp ? (-playerHeading * Math.PI / 180) : 0;
// Rotation angle: negate heading to counter-rotate world so facing = up
const rotAngle = -headingRad;
// Draw objects
objects.forEach(obj => {
const dEW = obj.ew - playerEW;
const dNS = obj.ns - playerNS;
// Rotate if heading-up
let dx, dy;
if (rotAngle !== 0) {
const cosA = Math.cos(rotAngle);
const sinA = Math.sin(rotAngle);
dx = dEW * cosA - dNS * sinA;
dy = -(dEW * sinA + dNS * cosA);
} else {
dx = dEW;
dy = -dNS; // NS increases north, canvas Y increases down
}
// Rotate world by negative heading so player facing = up
const cosA = Math.cos(rotAngle);
const sinA = Math.sin(rotAngle);
const dx = dEW * cosA - dNS * sinA;
const dy = -(dEW * sinA + dNS * cosA);
const px = cx + dx * scale;
const py = cy + dy * scale;