summaryrefslogtreecommitdiffstats
path: root/src/renderer/runtime/view/input
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/runtime/view/input')
-rw-r--r--src/renderer/runtime/view/input/gameinput.ts78
-rw-r--r--src/renderer/runtime/view/input/inputhandler.ts44
2 files changed, 122 insertions, 0 deletions
diff --git a/src/renderer/runtime/view/input/gameinput.ts b/src/renderer/runtime/view/input/gameinput.ts
new file mode 100644
index 0000000..67fbe0c
--- /dev/null
+++ b/src/renderer/runtime/view/input/gameinput.ts
@@ -0,0 +1,78 @@
+import { InputHandler } from './inputhandler';
+
+import { Listenable } from '../../util';
+
+import { vec2 } from 'gl-matrix';
+
+export enum ButtonCode {
+ Action,
+ Back,
+ Menu,
+}
+
+const buttonMapping: Record<string, ButtonCode> = {
+ KeyZ: ButtonCode.Action,
+ KeyX: ButtonCode.Back,
+ KeyC: ButtonCode.Menu,
+};
+
+export interface DirectionInput {
+ type: 'direction';
+ direction: vec2;
+}
+
+export interface ButtonInput {
+ type: 'button';
+ button: ButtonCode;
+}
+
+export type GameInput = DirectionInput | ButtonInput;
+
+export class GameInputHandler extends Listenable<[GameInput]> {
+ private readonly input: InputHandler;
+
+ constructor() {
+ super();
+
+ this.input = new InputHandler(
+ new Set([
+ 'ArrowLeft',
+ 'ArrowUp',
+ 'ArrowRight',
+ 'ArrowDown',
+ ...Object.keys(buttonMapping),
+ ]));
+
+ this.input.addListener((key: string, pressed: boolean) => {
+ const button = buttonMapping[key];
+ if (button !== undefined) {
+ if (pressed)
+ this.runListeners({
+ type: 'button',
+ button,
+ });
+
+ return;
+ }
+
+ const dir = vec2.create();
+
+ if (this.input.has('ArrowLeft'))
+ vec2.add(dir, dir, [-1, 0]);
+ if (this.input.has('ArrowUp'))
+ vec2.add(dir, dir, [0, -1]);
+ if (this.input.has('ArrowRight'))
+ vec2.add(dir, dir, [1, 0]);
+ if (this.input.has('ArrowDown'))
+ vec2.add(dir, dir, [0, 1]);
+
+ if (vec2.sqrLen(dir) > 0)
+ vec2.normalize(dir, dir);
+
+ this.runListeners({
+ type: 'direction',
+ direction: dir,
+ });
+ });
+ }
+}
diff --git a/src/renderer/runtime/view/input/inputhandler.ts b/src/renderer/runtime/view/input/inputhandler.ts
new file mode 100644
index 0000000..17abfe6
--- /dev/null
+++ b/src/renderer/runtime/view/input/inputhandler.ts
@@ -0,0 +1,44 @@
+import { Listenable } from '../../util';
+
+export class InputHandler extends Listenable<[string, boolean]> {
+ private readonly keys: Set<string> = new Set();
+
+ constructor(relevantKeys: Set<string>) {
+ super();
+
+ window.addEventListener('keydown', (ev) => {
+ if (!relevantKeys.has(ev.code))
+ return;
+
+ ev.preventDefault();
+
+ if (ev.repeat)
+ return;
+
+ this.keys.add(ev.code);
+ this.runListeners(ev.code, true);
+ });
+
+ window.addEventListener('keyup', (ev) => {
+ if (!relevantKeys.has(ev.code))
+ return;
+
+ ev.preventDefault();
+
+ if (!this.keys.has(ev.code))
+ return;
+
+ this.keys.delete(ev.code);
+ this.runListeners(ev.code, false);
+ });
+
+ window.addEventListener('blur', () => {
+ this.keys.clear();
+ this.runListeners('', false);
+ });
+ }
+
+ public has(key: string): boolean {
+ return this.keys.has(key);
+ }
+}