heaventaker/src/game/input.js
2021-06-12 10:29:34 +02:00

201 lines
5.9 KiB
JavaScript

import Hammer from "hammerjs";
const keybinds = {
"right": "ArrowRight",
"left": "ArrowLeft",
"up": "ArrowUp",
"down": "ArrowDown",
"debug": "f3",
"pause": "Escape"
};
class KeyHandler {
constructor() {
this.keys = new Map();
this.treshold = 0.3;
this.hammertime = new Hammer(document);
this.axis = new Map([
["x", ["moveRight", "moveLeft"]],
["y", ["moveUp", "moveDown"]],
["rotation", 0]
]);
/** @type {{ type: keyof DocumentEventMap, listener: (this: Document, ev: Event) => any, options?: boolean | EventListenerOptions}} */
this.handlers = [];
this.addHandlers();
this.mounted = false;
this.mountHandlers();
this.keysWasPressed = new Map();
/** @type {Map<string, Function[]>} */
this.listeners = new Map();
}
/**
* @param {K} type
* @param {(this: Document, ev: DocumentEventMap[K]) => any} listener
* @param {boolean | EventListenerOptions} [options]
* @template {keyof DocumentEventMap} K
*/
addDocumentEventListener(type, listener, options) {
this.handlers.push({
type,
listener,
options
});
if(this.mounted) document.addEventListener(type, listener, options);
}
/**
* Adds an event listener
* @param {string} type
* @param {(ev: keyof keybinds) => any} listener
*/
addEventListener(type, listener) {
if(!this.listeners.has(type)) this.listeners.set(type, []);
this.listeners.get(type).push(listener);
}
/**
* Emits an event
* @param {string} type
* @param {keyof keybinds} data
*/
emit(type, data) {
if(!this.listeners.has(type)) return;
this.listeners.get(type).forEach(listener => listener(data));
}
/**
* @param {K} type
* @param {(this: Document, ev: DocumentEventMap[K]) => any} listener
* @param {boolean | EventListenerOptions} [options]
* @template {keyof DocumentEventMap} K
*/
removeEventListener(type, listener, options) {
var handler = this.handlers.findIndex(e => e.type === type && e.listener === listener && e.options === options);
if(handler !== -1) this.handlers.splice(handler, 1);
document.removeEventListener(type, listener, options);
}
addHandlers() {
this.addDocumentEventListener("keydown", (ev) => {
if(this.pressKeyBind(ev.key)) {
ev.preventDefault();
return false;
};
});
this.addDocumentEventListener("keyup", (ev) => {
if(this.unpressKeyBind(ev.key)) {
ev.preventDefault();
return false;
};
});
this.hammertime.on("tap", (ev) => {
var { x, y } = ev.center;
x -= innerWidth / 2;
y -= innerHeight / 2;
var multiplier = 1 / (Math.abs(x) + Math.abs(y));
x *= multiplier;
y *= multiplier;
var direction;
if(x >= 0.5) {
direction = "right";
} else if(x <= -0.5) {
direction = "left";
} else if(y >= 0.5) {
direction = "down";
} else if(y <= -0.5) {
direction = "up";
}
this.keysWasPressed.set(direction, true);
});
this.hammertime.on('swipeleft', (ev) => {
this.keysWasPressed.set("left", true);
});
this.hammertime.on('swiperight', (ev) => {
this.keysWasPressed.set("right", true);
});
this.hammertime.on('swipeup', (ev) => {
this.keysWasPressed.set("up", true);
});
this.hammertime.on('swipedown', (ev) => {
this.keysWasPressed.set("down", true);
});
this.hammertime.get('swipe').set({ direction: Hammer.DIRECTION_ALL });
}
mountHandlers() {
for(var { type, listener, options } of this.handlers) {
document.addEventListener(type, listener, options);
}
this.mounted = true;
}
unmountHandlers() {
for(var { type, listener, options } of this.handlers) {
document.removeEventListener(type, listener, options);
}
this.mounted = false;
}
pressKeyBind(key) {
var kb = this.getKeyBind(key);
if(!kb) return null;
this.keysWasPressed.set(kb, true);
this.emit("keyDown", kb);
return this.pressKey(kb);
}
unpressKeyBind(key) {
var kb = this.getKeyBind(key);
if(!kb) return null;
this.keysWasPressed.delete(kb);
this.emit("keyUp", kb);
return this.unpressKey(kb);
}
setKeyBindAxis(key, value) {
var kb = this.getKeyBind(key);
if(!kb) return null;
return this.setAxis(kb, value);
}
getKeyBind(key) {
var index = Object.values(keybinds).map(t => t.toLowerCase()).indexOf(key.toLowerCase());
if(index === -1) return null;
return Object.keys(keybinds)[index];
}
isKeyPressed(key) {
return this.keys.has(key) && this.keys.get(key) > this.treshold;
}
wasKeyPressed(key) {
var was = this.keysWasPressed.has(key);
this.keysWasPressed.delete(key);
return was;
}
getAxis(key) {
if(!this.axis.has(key)) return;
var val = this.axis.get(key);
if(typeof val === "number") return val;
if(typeof val === "string") return this.keys.get(val);
var res = 0;
res += this.isKeyPressed(val[0]) ? 1 : 0;
res -= this.isKeyPressed(val[1]) ? 1 : 0;
return res;
}
pressKey(key) {
return this.keys.set(key, 1);
}
unpressKey(key) {
return this.keys.set(key, 0);
}
setAxis(key, val) {
return this.axis.set(key, val);
}
}
var keys = new KeyHandler;
export { keys };