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 ndsScale = computed(() =>
|
||||||
const scaleX = (windowSize.width.value - 40) / 235;
|
getNDS2DScale(windowSize.width.value, windowSize.height.value),
|
||||||
const scaleY = (windowSize.height.value - 40) / 431;
|
);
|
||||||
return Math.min(scaleX, scaleY);
|
|
||||||
});
|
|
||||||
|
|
||||||
const gallery = useGalleryStore();
|
const gallery = useGalleryStore();
|
||||||
const TOP_SCREEN_OFFSET = 170;
|
const TOP_SCREEN_OFFSET = 170;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useWindowSize } from "@vueuse/core";
|
|
||||||
import gsap from "gsap";
|
import gsap from "gsap";
|
||||||
import { LazyLagModal } from "#components";
|
import { LazyLagModal } from "#components";
|
||||||
|
|
||||||
@@ -30,20 +29,6 @@ const bottomScreenCanvas = computed(() => bottomScreen.value?.canvas ?? null);
|
|||||||
const isTouchDevice = () =>
|
const isTouchDevice = () =>
|
||||||
"ontouchstart" in window || navigator.maxTouchPoints > 0;
|
"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");
|
const helpButton = useTemplateRef("helpButton");
|
||||||
let helpAnimation: gsap.core.Timeline | null = null;
|
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(
|
watch(
|
||||||
() => app.hintsAllowed,
|
() => app.hintsAllowed,
|
||||||
(allowed) => {
|
(allowed) => {
|
||||||
if (!allowed) hideHelpLabels();
|
if (allowed) return;
|
||||||
|
helpAnimation?.kill();
|
||||||
|
helpAnimation = null;
|
||||||
|
app.hintsVisible = false;
|
||||||
},
|
},
|
||||||
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
@@ -129,9 +119,7 @@ onMounted(async () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const scaleX = (window.innerWidth - 40) / 235;
|
const scale = getNDS2DScale(window.innerWidth, window.innerHeight);
|
||||||
const scaleY = (window.innerHeight - 40) / 431;
|
|
||||||
const scale = Math.min(scaleX, scaleY);
|
|
||||||
|
|
||||||
if (app.settings.renderingMode === "2d" && scale < 1) return;
|
if (app.settings.renderingMode === "2d" && scale < 1) return;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { z } from "zod/mini";
|
import { z } from "zod/mini";
|
||||||
|
import { useWindowSize } from "@vueuse/core";
|
||||||
import type * as THREE from "three";
|
import type * as THREE from "three";
|
||||||
|
|
||||||
export const LOGICAL_WIDTH = 256;
|
export const LOGICAL_WIDTH = 256;
|
||||||
@@ -18,6 +19,24 @@ export const APP_COLORS = [
|
|||||||
|
|
||||||
const STORAGE_ID = "nds-settings";
|
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({
|
const settingsSchema = z.object({
|
||||||
color: z.object({
|
color: z.object({
|
||||||
col: z.number(),
|
col: z.number(),
|
||||||
@@ -55,7 +74,9 @@ export const useAppStore = defineStore("app", {
|
|||||||
visitedGallery: false,
|
visitedGallery: false,
|
||||||
camera: null as THREE.Camera | null,
|
camera: null as THREE.Camera | null,
|
||||||
hintsVisible: false,
|
hintsVisible: false,
|
||||||
hintsAllowed: false,
|
// hints wanted by the current app state (intro done, not in gallery)
|
||||||
|
hintsRequested: false,
|
||||||
|
windowSize: useWindowSize(),
|
||||||
lagDetected: false,
|
lagDetected: false,
|
||||||
lagModalOpen: false,
|
lagModalOpen: false,
|
||||||
};
|
};
|
||||||
@@ -96,12 +117,11 @@ export const useAppStore = defineStore("app", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
allowHints() {
|
allowHints() {
|
||||||
this.hintsAllowed = true;
|
this.hintsRequested = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
disallowHints() {
|
disallowHints() {
|
||||||
this.hintsAllowed = false;
|
this.hintsRequested = false;
|
||||||
this.hintsVisible = false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
showHints() {
|
showHints() {
|
||||||
@@ -128,5 +148,14 @@ export const useAppStore = defineStore("app", {
|
|||||||
row: state.settings.color.row,
|
row: state.settings.color.row,
|
||||||
hex: APP_COLORS[state.settings.color.row]![state.settings.color.col]!,
|
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(() => {
|
.call(() => {
|
||||||
const app = useAppStore();
|
const app = useAppStore();
|
||||||
if (window.innerWidth / window.innerHeight > 614 / 667) {
|
app.allowHints();
|
||||||
app.allowHints();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user