Skip to content

Instantly share code, notes, and snippets.

@WamWooWam
Last active May 30, 2019 21:04
Show Gist options
  • Save WamWooWam/d28685fba29c3ccdebfd301f405f672d to your computer and use it in GitHub Desktop.
Save WamWooWam/d28685fba29c3ccdebfd301f405f672d to your computer and use it in GitHub Desktop.
Konami Code in TypeScript with gamepad support
// only buttons i care about
const UP = 12;
const DOWN = 13;
const LEFT = 14;
const RIGHT = 15;
const A = 0;
const B = 1;
const START = 9;
class GamepadHelper {
buttonsCache: boolean[] = [];
buttonsStatus: boolean[] = [];
public buttonPressed(button: number): boolean {
return this.buttonsStatus[button] && !this.buttonsCache[button];
}
}
export class Konami {
constructor(onKonami: Function) {
this.onKonami = onKonami;
document.addEventListener("keyup", this.onKeyPress.bind(this));
if (navigator.getGamepads) {
if ("gamepadconnected" in window) {
window!.addEventListener("gamepadconnected", this.onGamepadAdded.bind(this));
}
else {
window.setInterval(this.chromePollGamepads.bind(this), 100);
}
window.addEventListener("gamepaddisconnected", this.onGamepadRemoved.bind(this));
}
}
onKonami: Function;
gamepads: Map<number, GamepadHelper> = new Map<number, GamepadHelper>();
gamepadPollInterval: number = 0;
keys: string = "";
target: string = "uuddlrlrbas";
onKeyPress(ev: KeyboardEvent) {
let key = ev.key.toLowerCase();
switch (key) {
case "up":
case "arrowup":
this.keys += "u";
break;
case "down":
case "arrowdown":
this.keys += "d";
break;
case "left":
case "arrowleft":
this.keys += "l";
break;
case "right":
case "arrowright":
this.keys += "r";
break;
case "enter":
this.keys += "s";
break;
default:
this.keys += key;
break;
}
if (!this.target.startsWith(this.keys)) {
this.keys = "";
}
if (this.keys == this.target) {
this.keys = "";
this.onKonami();
}
}
onGamepadAdded(ev: GamepadEvent) {
this.gamepads.set(ev.gamepad.index, new GamepadHelper());
if (this.gamepadPollInterval === 0) {
this.gamepadPollInterval = setInterval(this.pollGamepads.bind(this), 66);
}
}
onGamepadRemoved(ev: GamepadEvent) {
this.gamepads.delete(ev.gamepad.index);
if (this.gamepads.size === 0) {
clearInterval(this.gamepadPollInterval);
this.gamepadPollInterval = 0;
}
}
chromePollGamepads() { // this is dumb
let pads = navigator.getGamepads();
for (let pad of pads) {
if (pad !== null && !this.gamepads.has(pad.index)) {
this.gamepads.set(pad.index, new GamepadHelper());
if (this.gamepadPollInterval === 0) {
this.gamepadPollInterval = setInterval(this.pollGamepads.bind(this), 66);
}
}
}
}
pollGamepads() {
for (let pad of navigator.getGamepads()) {
if (pad !== null && pad.mapping == "standard") {
let api = this.gamepads.get(pad.index);
api.buttonsCache = [];
for (let i = 0; i < api.buttonsStatus.length; i++) {
api.buttonsCache[i] = api.buttonsStatus[i];
}
api.buttonsStatus = []
for (var i = 0; i < pad.buttons.length; i++) {
api.buttonsStatus[i] = pad.buttons[i].pressed
}
let x = Math.min(Math.max(-1, pad.axes[0]), 1);
x = Math.abs(x) < 0.25 ? 0 : x;
let y = Math.min(Math.max(-1, pad.axes[1]), 1);
y = Math.abs(y) < 0.25 ? 0 : y;
api.buttonsStatus[UP] = api.buttonsStatus[UP] || (y == -1);
api.buttonsStatus[DOWN] = api.buttonsStatus[DOWN] || (y == 1);
api.buttonsStatus[LEFT] = api.buttonsStatus[LEFT] || (x == -1);
api.buttonsStatus[RIGHT] = api.buttonsStatus[RIGHT] || (x == 1);
for (var i = 0; i < api.buttonsStatus.length; i++) {
let pressed = api.buttonPressed(i);
if (pressed) {
switch (i) {
case UP:
this.keys += "u";
break;
case DOWN:
this.keys += "d";
break;
case LEFT:
this.keys += "l";
break;
case RIGHT:
this.keys += "r";
break;
case B:
this.keys += "b";
break;
case A:
this.keys += "a";
break;
case START:
this.keys += "s";
break;
}
if (!this.target.startsWith(this.keys)) {
this.keys = "";
}
if (this.keys == this.target) {
this.onKonami();
this.keys = "";
}
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment