fix: hide help buttons on screen too small to click on physical buttons
This commit is contained in:
@@ -95,11 +95,9 @@ const handleTouchEnd = (event: TouchEvent) => {
|
||||
);
|
||||
};
|
||||
|
||||
const ndsScale = computed(() => {
|
||||
const scaleX = (windowSize.width.value - 40) / 235;
|
||||
const scaleY = (windowSize.height.value - 40) / 431;
|
||||
return Math.min(scaleX, scaleY);
|
||||
});
|
||||
const ndsScale = computed(() =>
|
||||
getNDS2DScale(windowSize.width.value, windowSize.height.value),
|
||||
);
|
||||
|
||||
const gallery = useGalleryStore();
|
||||
const TOP_SCREEN_OFFSET = 170;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import { useWindowSize } from "@vueuse/core";
|
||||
import gsap from "gsap";
|
||||
import { LazyLagModal } from "#components";
|
||||
|
||||
@@ -30,20 +29,6 @@ const bottomScreenCanvas = computed(() => bottomScreen.value?.canvas ?? null);
|
||||
const isTouchDevice = () =>
|
||||
"ontouchstart" in window || navigator.maxTouchPoints > 0;
|
||||
|
||||
const windowSize = useWindowSize();
|
||||
|
||||
watch(
|
||||
[windowSize.width, windowSize.height],
|
||||
([width, height]) => {
|
||||
if (width / height > 614 / 667) {
|
||||
if (app.booted) app.allowHints();
|
||||
} else {
|
||||
app.disallowHints();
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
const helpButton = useTemplateRef("helpButton");
|
||||
let helpAnimation: gsap.core.Timeline | null = null;
|
||||
|
||||
@@ -105,11 +90,16 @@ const hideHelpLabels = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// help button is removed when hints are disallowed, no need to animate it out
|
||||
watch(
|
||||
() => app.hintsAllowed,
|
||||
(allowed) => {
|
||||
if (!allowed) hideHelpLabels();
|
||||
if (allowed) return;
|
||||
helpAnimation?.kill();
|
||||
helpAnimation = null;
|
||||
app.hintsVisible = false;
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
@@ -129,9 +119,7 @@ onMounted(async () => {
|
||||
});
|
||||
}
|
||||
|
||||
const scaleX = (window.innerWidth - 40) / 235;
|
||||
const scaleY = (window.innerHeight - 40) / 431;
|
||||
const scale = Math.min(scaleX, scaleY);
|
||||
const scale = getNDS2DScale(window.innerWidth, window.innerHeight);
|
||||
|
||||
if (app.settings.renderingMode === "2d" && scale < 1) return;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { z } from "zod/mini";
|
||||
import { useWindowSize } from "@vueuse/core";
|
||||
import type * as THREE from "three";
|
||||
|
||||
export const LOGICAL_WIDTH = 256;
|
||||
@@ -18,6 +19,24 @@ export const APP_COLORS = [
|
||||
|
||||
const STORAGE_ID = "nds-settings";
|
||||
|
||||
// 2d nds is 414x431, scaled so the screens fit, it overflows horizontally on narrow viewports
|
||||
export const getNDS2DScale = (width: number, height: number) =>
|
||||
Math.min((width - 40) / 235, (height - 40) / 431);
|
||||
|
||||
// 3d: fixed vertical fov, so buttons clip at a fixed aspect ratio (measured: 810px wide at 865px tall)
|
||||
const HINTS_MIN_ASPECT_RATIO_3D = 810 / 865;
|
||||
// 2d: horizontal span of the physical buttons (A button is ~14px from the edge)
|
||||
const NDS2D_BUTTONS_SPAN = 386;
|
||||
|
||||
const screenFitsHints = (
|
||||
width: number,
|
||||
height: number,
|
||||
renderingMode: "3d" | "2d",
|
||||
) =>
|
||||
renderingMode === "3d"
|
||||
? width / height > HINTS_MIN_ASPECT_RATIO_3D
|
||||
: NDS2D_BUTTONS_SPAN * getNDS2DScale(width, height) <= width;
|
||||
|
||||
const settingsSchema = z.object({
|
||||
color: z.object({
|
||||
col: z.number(),
|
||||
@@ -55,7 +74,9 @@ export const useAppStore = defineStore("app", {
|
||||
visitedGallery: false,
|
||||
camera: null as THREE.Camera | null,
|
||||
hintsVisible: false,
|
||||
hintsAllowed: false,
|
||||
// hints wanted by the current app state (intro done, not in gallery)
|
||||
hintsRequested: false,
|
||||
windowSize: useWindowSize(),
|
||||
lagDetected: false,
|
||||
lagModalOpen: false,
|
||||
};
|
||||
@@ -96,12 +117,11 @@ export const useAppStore = defineStore("app", {
|
||||
},
|
||||
|
||||
allowHints() {
|
||||
this.hintsAllowed = true;
|
||||
this.hintsRequested = true;
|
||||
},
|
||||
|
||||
disallowHints() {
|
||||
this.hintsAllowed = false;
|
||||
this.hintsVisible = false;
|
||||
this.hintsRequested = false;
|
||||
},
|
||||
|
||||
showHints() {
|
||||
@@ -128,5 +148,14 @@ export const useAppStore = defineStore("app", {
|
||||
row: state.settings.color.row,
|
||||
hex: APP_COLORS[state.settings.color.row]![state.settings.color.col]!,
|
||||
}),
|
||||
|
||||
// hints wanted and screen large enough
|
||||
hintsAllowed: (state) =>
|
||||
state.hintsRequested &&
|
||||
screenFitsHints(
|
||||
state.windowSize.width,
|
||||
state.windowSize.height,
|
||||
state.settings.renderingMode,
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -67,9 +67,7 @@ export const useIntroStore = defineStore("intro", {
|
||||
)
|
||||
.call(() => {
|
||||
const app = useAppStore();
|
||||
if (window.innerWidth / window.innerHeight > 614 / 667) {
|
||||
app.allowHints();
|
||||
}
|
||||
app.allowHints();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user