blob2d
Version:
Typed Modular 2D Game Engine for Web
61 lines (47 loc) • 1.44 kB
text/typescript
import {refineArray} from '../utils/array';
type TEventCallback = (pressed: boolean) => void;
export class Keyboard<TKey extends string = string> {
public readonly destroy: () => void;
protected states: Map<TKey, boolean>;
protected events: Map<TKey, TEventCallback>;
constructor() {
this.states = new Map();
this.events = new Map();
const listener = (event: KeyboardEvent) => {
this.handleEvent(event);
};
window.addEventListener('keydown', listener);
window.addEventListener('keyup', listener);
this.destroy = () => {
window.removeEventListener('keydown', listener);
window.removeEventListener('keyup', listener);
this.events.clear();
};
}
public on(keys: TKey | TKey[], callback: TEventCallback) {
refineArray(keys).forEach(key => {
this.events.set(key, callback);
});
}
public off(keys: TKey | TKey[]) {
refineArray(keys).forEach(key => {
this.events.delete(key);
});
}
protected handleEvent(event: KeyboardEvent) {
event.preventDefault();
const key = event.key as TKey;
if (!this.events.has(key)) {
return;
}
const pressed = event.type === 'keydown';
// shouldn't invoke keyup before keydown
if (!pressed && !this.states.get(key)) {
return;
}
if (this.states.get(key) !== pressed) {
this.states.set(key, pressed);
this.events.get(key)?.(pressed);
}
}
}