feat(nds): improve key input system
This commit is contained in:
@@ -8,7 +8,7 @@ const QUIT_SIZE = assets.images.achievements.quit.rect.width;
|
|||||||
const QUIT_X = Math.floor(LOGICAL_WIDTH / 2 - QUIT_SIZE / 2);
|
const QUIT_X = Math.floor(LOGICAL_WIDTH / 2 - QUIT_SIZE / 2);
|
||||||
const QUIT_Y = 135;
|
const QUIT_Y = 135;
|
||||||
|
|
||||||
useKeyDown((key) => {
|
useKeyDown(({ key }) => {
|
||||||
if (store.isIntro || store.isOutro) return;
|
if (store.isIntro || store.isOutro) return;
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ onClick((x, y) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
useKeyDown((key) => {
|
useKeyDown(({ key }) => {
|
||||||
if (props.yOffset !== 0) return;
|
if (props.yOffset !== 0) return;
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case "NDS_START":
|
case "NDS_START":
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ onClick(() => {
|
|||||||
store.animateOutro();
|
store.animateOutro();
|
||||||
});
|
});
|
||||||
|
|
||||||
useKeyDown((key) => {
|
useKeyDown(({ key }) => {
|
||||||
if (store.isIntro || store.isOutro) return;
|
if (store.isIntro || store.isOutro) return;
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
|||||||
@@ -203,38 +203,15 @@ const { onRender } = useLoop();
|
|||||||
const physicalButtonsDown = new Set<string>();
|
const physicalButtonsDown = new Set<string>();
|
||||||
let mousePressedButton: string | null = null;
|
let mousePressedButton: string | null = null;
|
||||||
|
|
||||||
const keyToButton: Record<string, string> = {
|
useKeyDown(({ ndsButton }) => {
|
||||||
ArrowUp: "UP",
|
if (ndsButton) {
|
||||||
ArrowDown: "DOWN",
|
physicalButtonsDown.add(ndsButton);
|
||||||
ArrowLeft: "LEFT",
|
|
||||||
ArrowRight: "RIGHT",
|
|
||||||
d: "A",
|
|
||||||
s: "B",
|
|
||||||
w: "X",
|
|
||||||
a: "Y",
|
|
||||||
D: "A",
|
|
||||||
S: "B",
|
|
||||||
W: "X",
|
|
||||||
A: "Y",
|
|
||||||
" ": "SELECT",
|
|
||||||
Enter: "START",
|
|
||||||
};
|
|
||||||
|
|
||||||
useKeyDown((key) => {
|
|
||||||
const button = keyToButton[key];
|
|
||||||
if (button) {
|
|
||||||
physicalButtonsDown.add(button);
|
|
||||||
window.dispatchEvent(
|
|
||||||
new KeyboardEvent("keydown", { key: `NDS_${button}` }),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
useKeyUp((key) => {
|
useKeyUp(({ ndsButton }) => {
|
||||||
const button = keyToButton[key];
|
if (ndsButton) {
|
||||||
if (button) {
|
physicalButtonsDown.delete(ndsButton);
|
||||||
physicalButtonsDown.delete(button);
|
|
||||||
window.dispatchEvent(new KeyboardEvent("keyup", { key: `NDS_${button}` }));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ onRender((ctx) => {
|
|||||||
ctx.fillStyle = `rgba(0, 0, 0, ${store.isIntro ? store.intro.fadeOpacity : store.isOutro ? store.outro.fadeOpacity : 0})`;
|
ctx.fillStyle = `rgba(0, 0, 0, ${store.isIntro ? store.intro.fadeOpacity : store.isOutro ? store.outro.fadeOpacity : 0})`;
|
||||||
ctx.fillRect(0, 0, LOGICAL_WIDTH, LOGICAL_HEIGHT);
|
ctx.fillRect(0, 0, LOGICAL_WIDTH, LOGICAL_HEIGHT);
|
||||||
});
|
});
|
||||||
useKeyDown((key) => {
|
useKeyDown(({ key }) => {
|
||||||
if (
|
if (
|
||||||
currentAnimation ||
|
currentAnimation ||
|
||||||
store.isIntro ||
|
store.isIntro ||
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
onUnmounted(() => timeline?.kill());
|
onUnmounted(() => timeline?.kill());
|
||||||
|
|
||||||
useKeyDown((key) => {
|
useKeyDown(({ key }) => {
|
||||||
if (!store.showConfirmationPopup) return;
|
if (!store.showConfirmationPopup) return;
|
||||||
|
|
||||||
if (textProgress.value < 1 && key === "NDS_A") {
|
if (textProgress.value < 1 && key === "NDS_A") {
|
||||||
@@ -73,7 +73,7 @@ useKeyDown((key) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
useKeyUp((key) => {
|
useKeyUp(({ key }) => {
|
||||||
if (store.showConfirmationPopup && key === "NDS_A") {
|
if (store.showConfirmationPopup && key === "NDS_A") {
|
||||||
waitingForNdsARelease = false;
|
waitingForNdsARelease = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ onClick((x, y) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
useKeyDown((key) => {
|
useKeyDown(({ key }) => {
|
||||||
if (isAnimating.value) return;
|
if (isAnimating.value) return;
|
||||||
if (key === "NDS_X") {
|
if (key === "NDS_X") {
|
||||||
handleVisitAll();
|
handleVisitAll();
|
||||||
|
|||||||
@@ -538,7 +538,7 @@ const slide = (rowDir: number, colDir: number) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useKeyDown((key) => {
|
useKeyDown(({ key }) => {
|
||||||
if (isAnimating.value) return;
|
if (isAnimating.value) return;
|
||||||
switch (key) {
|
switch (key) {
|
||||||
// TODO: remove this, testing only
|
// TODO: remove this, testing only
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ const select = (col: number, row: number) => {
|
|||||||
app.setColor(col, row);
|
app.setColor(col, row);
|
||||||
};
|
};
|
||||||
|
|
||||||
useKeyDown((key) => {
|
useKeyDown(({ key }) => {
|
||||||
if (isAnimating.value) return;
|
if (isAnimating.value) return;
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ onRender((ctx) => {
|
|||||||
);
|
);
|
||||||
}, 110);
|
}, 110);
|
||||||
|
|
||||||
useKeyDown((key) => {
|
useKeyDown(({ key }) => {
|
||||||
if (state.value !== "alive") return;
|
if (state.value !== "alive") return;
|
||||||
|
|
||||||
const newDirection = direction.clone();
|
const newDirection = direction.clone();
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ onRender((ctx) => {
|
|||||||
);
|
);
|
||||||
}, 10);
|
}, 10);
|
||||||
|
|
||||||
useKeyDown((key) => {
|
useKeyDown(({ key }) => {
|
||||||
if (isAnimating.value || !props.selected || props.disabled) return;
|
if (isAnimating.value || !props.selected || props.disabled) return;
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case "NDS_UP":
|
case "NDS_UP":
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ export const useButtonNavigation = <T extends Record<string, Rect>>({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
useKeyDown((key) => {
|
useKeyDown(({ key }) => {
|
||||||
if (blockInteractions.value) return;
|
if (blockInteractions.value) return;
|
||||||
|
|
||||||
const currentButton = selectedButton.value as Entry;
|
const currentButton = selectedButton.value as Entry;
|
||||||
|
|||||||
@@ -1,8 +1,19 @@
|
|||||||
export type KeyDownCallback = (key: string) => void;
|
import { mapKeyToNDS } from "~/utils/input";
|
||||||
|
|
||||||
|
export type KeyDownCallback = (params: {
|
||||||
|
key: string;
|
||||||
|
ndsButton: string | null;
|
||||||
|
repeated: boolean;
|
||||||
|
}) => void;
|
||||||
|
|
||||||
export const useKeyDown = (callback: KeyDownCallback) => {
|
export const useKeyDown = (callback: KeyDownCallback) => {
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
callback(event.key);
|
const ndsButton = mapKeyToNDS(event.key);
|
||||||
|
callback({
|
||||||
|
key: ndsButton ? `NDS_${ndsButton}` : event.key,
|
||||||
|
ndsButton,
|
||||||
|
repeated: event.repeat,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
export type KeyUpCallback = (key: string) => void;
|
import { mapKeyToNDS } from "~/utils/input";
|
||||||
|
|
||||||
|
export type KeyUpCallback = (params: {
|
||||||
|
key: string;
|
||||||
|
ndsButton: string | null;
|
||||||
|
}) => void;
|
||||||
|
|
||||||
export const useKeyUp = (callback: KeyUpCallback) => {
|
export const useKeyUp = (callback: KeyUpCallback) => {
|
||||||
const handleKeyUp = (event: KeyboardEvent) => {
|
const handleKeyUp = (event: KeyboardEvent) => {
|
||||||
callback(event.key);
|
const ndsButton = mapKeyToNDS(event.key);
|
||||||
|
callback({
|
||||||
|
key: ndsButton ? `NDS_${ndsButton}` : event.key,
|
||||||
|
ndsButton,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -12,63 +12,6 @@ const bottomScreen = useTemplateRef<ScreenInstance>("bottomScreen");
|
|||||||
|
|
||||||
const topScreenCanvas = computed(() => topScreen.value?.canvas ?? null);
|
const topScreenCanvas = computed(() => topScreen.value?.canvas ?? null);
|
||||||
const bottomScreenCanvas = computed(() => bottomScreen.value?.canvas ?? null);
|
const bottomScreenCanvas = computed(() => bottomScreen.value?.canvas ?? null);
|
||||||
|
|
||||||
const a = useAchievementsStore();
|
|
||||||
|
|
||||||
const keyToButton: Record<string, string> = {
|
|
||||||
ArrowUp: "UP",
|
|
||||||
ArrowDown: "DOWN",
|
|
||||||
ArrowLeft: "LEFT",
|
|
||||||
ArrowRight: "RIGHT",
|
|
||||||
d: "A",
|
|
||||||
s: "B",
|
|
||||||
z: "X",
|
|
||||||
q: "Y",
|
|
||||||
D: "A",
|
|
||||||
S: "B",
|
|
||||||
Z: "X",
|
|
||||||
Q: "Y",
|
|
||||||
" ": "SELECT",
|
|
||||||
Enter: "START",
|
|
||||||
};
|
|
||||||
|
|
||||||
// events are dispatched from NDS.vue in 3d mode
|
|
||||||
// events are dispatched from here in 2d mode
|
|
||||||
// that's a bit dirty but who cares, there is a lot of dirty things going on here
|
|
||||||
// like who choose Nuxt to build such an app
|
|
||||||
useKeyDown((key) => {
|
|
||||||
if (app.settings.renderingMode === "3d") return;
|
|
||||||
const button = keyToButton[key];
|
|
||||||
if (button) {
|
|
||||||
window.dispatchEvent(
|
|
||||||
new KeyboardEvent("keydown", { key: `NDS_${button}` }),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// testing purpose only
|
|
||||||
if (key === "m") {
|
|
||||||
a.reset();
|
|
||||||
} else if (key === "o") {
|
|
||||||
for (const ach of ACHIEVEMENTS) {
|
|
||||||
a.unlock(ach.id);
|
|
||||||
}
|
|
||||||
} else if (key === "p") {
|
|
||||||
for (const ach of ACHIEVEMENTS) {
|
|
||||||
if (!a.isUnlocked(ach.id)) {
|
|
||||||
a.unlock(ach.id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
useKeyUp((key) => {
|
|
||||||
if (app.settings.renderingMode === "3d") return;
|
|
||||||
const button = keyToButton[key];
|
|
||||||
if (button) {
|
|
||||||
window.dispatchEvent(new KeyboardEvent("keyup", { key: `NDS_${button}` }));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
17
app/utils/input.ts
Normal file
17
app/utils/input.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
const KEY_TO_NDS_BUTTON: Record<string, string> = {
|
||||||
|
ArrowUp: "UP",
|
||||||
|
ArrowDown: "DOWN",
|
||||||
|
ArrowLeft: "LEFT",
|
||||||
|
ArrowRight: "RIGHT",
|
||||||
|
D: "A",
|
||||||
|
S: "B",
|
||||||
|
Z: "X",
|
||||||
|
Q: "Y",
|
||||||
|
" ": "SELECT",
|
||||||
|
Enter: "START",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const mapKeyToNDS = (key: string): string | null => {
|
||||||
|
key = key.length === 1 ? key.toUpperCase() : key;
|
||||||
|
return KEY_TO_NDS_BUTTON[key] ?? null;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user