feat(player): reposition mobile player focal point
This commit is contained in:
+22
-2
@@ -190,6 +190,18 @@
|
||||
};
|
||||
}
|
||||
|
||||
function playerFocalPoint(stageWidth, stageHeight) {
|
||||
if (![stageWidth, stageHeight].every(value => Number.isFinite(value) && value > 0)) return {x: 0, y: 0};
|
||||
if (stageWidth > stageHeight) return {x: Math.round(stageWidth * .42), y: Math.round(stageHeight * .45)};
|
||||
return {x: Math.round(stageWidth / 2), y: Math.round(stageHeight * .3)};
|
||||
}
|
||||
|
||||
function playerFocalMapOffset(selfIndex, width, minX, minY, columns, rows, cellSize, stageWidth, stageHeight) {
|
||||
const centered = playerMapOffset(selfIndex, width, minX, minY, columns, rows, cellSize);
|
||||
const focal = playerFocalPoint(stageWidth, stageHeight);
|
||||
return {x: centered.x + focal.x - stageWidth / 2, y: centered.y + focal.y - stageHeight / 2};
|
||||
}
|
||||
|
||||
function nextOnboardingStep(currentStep) {
|
||||
return currentStep >= ONBOARDING_STEPS.length - 1 ? null : currentStep + 1;
|
||||
}
|
||||
@@ -495,12 +507,15 @@
|
||||
const rows = maxY - minY + 1;
|
||||
const mapShell = byId("map-shell");
|
||||
const cellSize = playerCellSize(mapShell.clientWidth, mapShell.clientHeight, columns, rows);
|
||||
const offset = playerMapOffset(snapshot.self, snapshot.width, minX, minY, columns, rows, cellSize);
|
||||
const focal = playerFocalPoint(mapShell.clientWidth, mapShell.clientHeight);
|
||||
const offset = playerFocalMapOffset(snapshot.self, snapshot.width, minX, minY, columns, rows, cellSize, mapShell.clientWidth, mapShell.clientHeight);
|
||||
maze.style.setProperty("--cell", `${cellSize}px`);
|
||||
maze.style.gridTemplateColumns = `repeat(${columns}, var(--cell))`;
|
||||
maze.style.gridTemplateRows = `repeat(${rows}, var(--cell))`;
|
||||
maze.style.setProperty("--map-offset-x", `${offset.x}px`);
|
||||
maze.style.setProperty("--map-offset-y", `${offset.y}px`);
|
||||
mapShell.style.setProperty("--player-focal-x", `${focal.x}px`);
|
||||
mapShell.style.setProperty("--player-focal-y", `${focal.y}px`);
|
||||
const objects = new Map();
|
||||
snapshot.objects.forEach(object => { const list = objects.get(object[3]) || []; list.push(object); objects.set(object[3], list); });
|
||||
coordinates.forEach(data => {
|
||||
@@ -837,6 +852,11 @@
|
||||
byId("avatar-control").addEventListener("pointercancel", stopAvatarControl);
|
||||
byId("avatar-control").addEventListener("lostpointercapture", stopAvatarControl);
|
||||
windowObject.addEventListener("blur", resetPlayerControls);
|
||||
const refreshPlayerFocalPoint = () => {
|
||||
if (state.snapshot && state.snapshot.role === "player") windowObject.requestAnimationFrame(() => renderMap(state.snapshot));
|
||||
};
|
||||
windowObject.addEventListener("resize", refreshPlayerFocalPoint);
|
||||
windowObject.addEventListener("orientationchange", refreshPlayerFocalPoint);
|
||||
documentObject.addEventListener("visibilitychange", () => { if (documentObject.hidden) resetPlayerControls(); });
|
||||
documentObject.querySelectorAll("[data-direction]").forEach(button => {
|
||||
button.addEventListener("pointerdown", event => {
|
||||
@@ -902,7 +922,7 @@
|
||||
return {state, handleMessage, move, resetAvatarControl, latencySamples: () => state.latency.snapshot(), pointerFeedbackSamples: () => state.latency.pointerSnapshot()};
|
||||
}
|
||||
|
||||
const api = Object.freeze({TOKEN_KEY, MAX_VIEW_CHUNKS, NAME_COMBINATION_COUNT, LOGIN_HEADLINES, ONBOARDING_STEPS, LATENCY_SAMPLE_LIMIT, AVATAR_TOUCH_TARGET_SIZE, AVATAR_MAX_DEFLECTION, AVATAR_DEAD_ZONE, AVATAR_DIRECTION_HYSTERESIS, AVATAR_SLOW_REPEAT_MS, AVATAR_FAST_REPEAT_MS, DIRECTIONAL_PAD_REPEAT_MS, LatestIntentFlow, LatencyTracker, directionFromKey, directionFromSwipe, avatarDirection, avatarRepeatMs, avatarVector, playerCellSize, playerMapOffset, nextOnboardingStep, randomIndex, randomSuggestedName, randomLoginHeadline, createEnvelope, snapshotIsValid, SnapshotAssembler, projectedCellIndices, clampObserverZoom, observerFitScale, boot});
|
||||
const api = Object.freeze({TOKEN_KEY, MAX_VIEW_CHUNKS, NAME_ADJECTIVES, NAME_NOUNS, NAME_COMBINATION_COUNT, LOGIN_HEADLINES, ONBOARDING_STEPS, LATENCY_SAMPLE_LIMIT, AVATAR_TOUCH_TARGET_SIZE, AVATAR_MAX_DEFLECTION, AVATAR_DEAD_ZONE, AVATAR_DIRECTION_HYSTERESIS, AVATAR_SLOW_REPEAT_MS, AVATAR_FAST_REPEAT_MS, DIRECTIONAL_PAD_REPEAT_MS, LatestIntentFlow, LatencyTracker, directionFromKey, directionFromSwipe, avatarDirection, avatarRepeatMs, avatarVector, playerCellSize, playerMapOffset, playerFocalPoint, playerFocalMapOffset, nextOnboardingStep, randomIndex, randomSuggestedName, randomLoginHeadline, createEnvelope, snapshotIsValid, SnapshotAssembler, projectedCellIndices, clampObserverZoom, observerFitScale, boot});
|
||||
if (typeof module !== "undefined" && module.exports) module.exports = api;
|
||||
root.Maze32Player = api;
|
||||
if (root.document) root.document.addEventListener("DOMContentLoaded", () => { root.maze32PlayerApp = boot(root.document, root); });
|
||||
|
||||
Reference in New Issue
Block a user