like2d 1.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +74 -42
- package/assets/logo-banner.svg +188 -0
- package/assets/logo-icon.svg +88 -0
- package/assets/logo.svg +188 -0
- package/dist/adapters/callback/index.d.ts +43 -0
- package/dist/adapters/callback/index.d.ts.map +1 -0
- package/dist/adapters/callback/index.js +80 -0
- package/dist/adapters/scene/index.d.ts +42 -0
- package/dist/adapters/scene/index.d.ts.map +1 -0
- package/dist/adapters/scene/index.js +112 -0
- package/dist/adapters/scene/scene.d.ts +18 -0
- package/dist/adapters/scene/scene.d.ts.map +1 -0
- package/dist/adapters/scene/startup-scene.d.ts +17 -0
- package/dist/adapters/scene/startup-scene.d.ts.map +1 -0
- package/dist/adapters/scene/startup-scene.js +41 -0
- package/dist/core/audio.d.ts +61 -0
- package/dist/core/audio.d.ts.map +1 -0
- package/dist/core/audio.js +226 -0
- package/dist/core/canvas-config.d.ts +22 -0
- package/dist/core/canvas-config.d.ts.map +1 -0
- package/dist/core/canvas-config.js +14 -0
- package/dist/core/canvas-manager.d.ts +26 -0
- package/dist/core/canvas-manager.d.ts.map +1 -0
- package/dist/core/canvas-manager.js +197 -0
- package/dist/core/events.d.ts +52 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/gamepad-button-map.d.ts.map +1 -0
- package/dist/core/gamepad-buttons.d.ts +23 -0
- package/dist/core/gamepad-buttons.d.ts.map +1 -0
- package/dist/core/gamepad-buttons.js +36 -0
- package/dist/core/gamepad-db.d.ts.map +1 -0
- package/dist/{gamepad-mapping.d.ts → core/gamepad-mapping.d.ts} +3 -15
- package/dist/core/gamepad-mapping.d.ts.map +1 -0
- package/dist/core/gamepad-mapping.js +223 -0
- package/dist/{gamepad.d.ts → core/gamepad.d.ts} +22 -17
- package/dist/core/gamepad.d.ts.map +1 -0
- package/dist/{gamepad.js → core/gamepad.js} +91 -70
- package/dist/{graphics.d.ts → core/graphics.d.ts} +2 -8
- package/dist/core/graphics.d.ts.map +1 -0
- package/dist/{graphics.js → core/graphics.js} +4 -41
- package/dist/core/input-state.d.ts.map +1 -0
- package/dist/{input.d.ts → core/input.d.ts} +11 -14
- package/dist/core/input.d.ts.map +1 -0
- package/dist/{input.js → core/input.js} +31 -41
- package/dist/core/keyboard.d.ts +15 -0
- package/dist/core/keyboard.d.ts.map +1 -0
- package/dist/core/keyboard.js +70 -0
- package/dist/core/mouse.d.ts +29 -0
- package/dist/core/mouse.d.ts.map +1 -0
- package/dist/core/mouse.js +130 -0
- package/dist/{rect.d.ts → core/rect.d.ts} +1 -2
- package/dist/core/rect.d.ts.map +1 -0
- package/dist/{rect.js → core/rect.js} +24 -28
- package/dist/{timer.d.ts → core/timer.d.ts} +0 -1
- package/dist/core/timer.d.ts.map +1 -0
- package/dist/{timer.js → core/timer.js} +0 -1
- package/dist/{vector2.d.ts → core/vector2.d.ts} +4 -10
- package/dist/core/vector2.d.ts.map +1 -0
- package/dist/{vector2.js → core/vector2.js} +40 -40
- package/dist/engine.d.ts +42 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +154 -0
- package/dist/index.d.ts +38 -44
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -250
- package/package.json +9 -23
- package/dist/audio.d.ts +0 -52
- package/dist/audio.d.ts.map +0 -1
- package/dist/audio.js +0 -250
- package/dist/events.d.ts +0 -36
- package/dist/events.d.ts.map +0 -1
- package/dist/gamepad-button-map.d.ts.map +0 -1
- package/dist/gamepad-db.d.ts.map +0 -1
- package/dist/gamepad-mapping.d.ts.map +0 -1
- package/dist/gamepad-mapping.js +0 -191
- package/dist/gamepad.d.ts.map +0 -1
- package/dist/graphics.d.ts.map +0 -1
- package/dist/input-state.d.ts.map +0 -1
- package/dist/input.d.ts.map +0 -1
- package/dist/keyboard.d.ts +0 -9
- package/dist/keyboard.d.ts.map +0 -1
- package/dist/keyboard.js +0 -33
- package/dist/mouse.d.ts +0 -20
- package/dist/mouse.d.ts.map +0 -1
- package/dist/mouse.js +0 -84
- package/dist/rect.d.ts.map +0 -1
- package/dist/scene.d.ts +0 -10
- package/dist/scene.d.ts.map +0 -1
- package/dist/timer.d.ts.map +0 -1
- package/dist/vector2.d.ts.map +0 -1
- /package/dist/{scene.js → adapters/scene/scene.js} +0 -0
- /package/dist/{events.js → core/events.js} +0 -0
- /package/dist/{gamepad-button-map.d.ts → core/gamepad-button-map.d.ts} +0 -0
- /package/dist/{gamepad-button-map.js → core/gamepad-button-map.js} +0 -0
- /package/dist/{gamepad-db.d.ts → core/gamepad-db.d.ts} +0 -0
- /package/dist/{gamepad-db.js → core/gamepad-db.js} +0 -0
- /package/dist/{input-state.d.ts → core/input-state.d.ts} +0 -0
- /package/dist/{input-state.js → core/input-state.js} +0 -0
|
@@ -1,35 +1,41 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getGPName, GP } from './gamepad-buttons';
|
|
2
2
|
import { ButtonMapping } from './gamepad-mapping';
|
|
3
|
-
export {
|
|
4
|
-
export interface GamepadButtonEvent {
|
|
5
|
-
gamepadIndex: number;
|
|
6
|
-
buttonIndex: number;
|
|
7
|
-
buttonName: string;
|
|
8
|
-
rawButtonIndex: number;
|
|
9
|
-
}
|
|
3
|
+
export { GP, getGPName };
|
|
10
4
|
export interface StickPosition {
|
|
11
5
|
x: number;
|
|
12
6
|
y: number;
|
|
13
7
|
}
|
|
8
|
+
export type ButtonCallback = (gamepadIndex: number, buttonIndex: number, buttonName: string, pressed: boolean) => void;
|
|
14
9
|
export declare class Gamepad {
|
|
15
10
|
private buttonTrackers;
|
|
16
11
|
private connectedGamepads;
|
|
17
12
|
private buttonMappings;
|
|
13
|
+
onButtonEvent?: (gamepadIndex: number, buttonIndex: number, buttonName: string, pressed: boolean) => void;
|
|
14
|
+
private onConnected?;
|
|
15
|
+
private onDisconnected?;
|
|
16
|
+
private gamepadConnectedHandler;
|
|
17
|
+
private gamepadDisconnectedHandler;
|
|
18
|
+
private blurHandler;
|
|
18
19
|
constructor();
|
|
20
|
+
private handleGamepadConnected;
|
|
21
|
+
private handleGamepadDisconnected;
|
|
22
|
+
private handleBlur;
|
|
23
|
+
setCallbacks(callbacks: {
|
|
24
|
+
onConnected?: (gamepad: globalThis.Gamepad) => void;
|
|
25
|
+
onDisconnected?: (gamepadIndex: number) => void;
|
|
26
|
+
}): void;
|
|
27
|
+
dispose(): void;
|
|
19
28
|
init(): Promise<void>;
|
|
20
|
-
private
|
|
21
|
-
private
|
|
22
|
-
update():
|
|
23
|
-
pressed: GamepadButtonEvent[];
|
|
24
|
-
released: GamepadButtonEvent[];
|
|
25
|
-
};
|
|
29
|
+
private onGamepadConnectedInternal;
|
|
30
|
+
private onGamepadDisconnectedInternal;
|
|
31
|
+
update(): void;
|
|
26
32
|
isConnected(gamepadIndex: number): boolean;
|
|
27
33
|
/**
|
|
28
34
|
* Check if a button is currently pressed on a specific gamepad
|
|
29
35
|
* Uses mapped button indices (standard layout)
|
|
30
36
|
*/
|
|
31
|
-
isButtonDown(gamepadIndex: number,
|
|
32
|
-
isButtonDownOnAny(
|
|
37
|
+
isButtonDown(gamepadIndex: number, buttonIndex: number): boolean;
|
|
38
|
+
isButtonDownOnAny(buttonIndex: number): boolean;
|
|
33
39
|
getPressedButtons(gamepadIndex: number): Set<number>;
|
|
34
40
|
getConnectedGamepads(): number[];
|
|
35
41
|
/**
|
|
@@ -52,5 +58,4 @@ export declare class Gamepad {
|
|
|
52
58
|
getLeftStick(gamepadIndex: number): StickPosition;
|
|
53
59
|
getRightStick(gamepadIndex: number): StickPosition;
|
|
54
60
|
}
|
|
55
|
-
export declare const gamepad: Gamepad;
|
|
56
61
|
//# sourceMappingURL=gamepad.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gamepad.d.ts","sourceRoot":"","sources":["../../src/core/gamepad.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAkB,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC;AAEzB,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAkBD,MAAM,MAAM,cAAc,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAEvH,qBAAa,OAAO;IAClB,OAAO,CAAC,cAAc,CAAgD;IACtE,OAAO,CAAC,iBAAiB,CAAyC;IAClE,OAAO,CAAC,cAAc,CAAoC;IACnD,aAAa,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACjH,OAAO,CAAC,WAAW,CAAC,CAAwC;IAC5D,OAAO,CAAC,cAAc,CAAC,CAAiC;IAGxD,OAAO,CAAC,uBAAuB,CAAuC;IACtE,OAAO,CAAC,0BAA0B,CAAuC;IACzE,OAAO,CAAC,WAAW,CAAa;;IAchC,OAAO,CAAC,sBAAsB;IAK9B,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,UAAU;IAMlB,YAAY,CAAC,SAAS,EAAE;QACtB,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,KAAK,IAAI,CAAC;QACpD,cAAc,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;KACjD,GAAG,IAAI;IAKR,OAAO,IAAI,IAAI;IAST,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,OAAO,CAAC,0BAA0B;IAclC,OAAO,CAAC,6BAA6B;IAMrC,MAAM,IAAI,IAAI;IA4Cd,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI1C;;;OAGG;IACH,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO;IAKhE,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAO/C,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAKpD,oBAAoB,IAAI,MAAM,EAAE;IAIhC;;OAEG;IACH,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,UAAU,CAAC,OAAO,GAAG,SAAS;IAIhE;;OAEG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIjE;;OAEG;IACH,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAKzC;;OAEG;IACH,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK3D,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAMxD,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa;IAMjD,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa;CAKnD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getGPName, GP } from './gamepad-buttons';
|
|
2
2
|
import { InputStateTracker } from './input-state';
|
|
3
3
|
import { gamepadMapping } from './gamepad-mapping';
|
|
4
|
-
export {
|
|
4
|
+
export { GP, getGPName };
|
|
5
5
|
const AXIS_DEADZONE = 0.15;
|
|
6
6
|
function applyDeadzone(value, deadzone = AXIS_DEADZONE) {
|
|
7
7
|
if (Math.abs(value) < deadzone)
|
|
@@ -37,60 +37,99 @@ export class Gamepad {
|
|
|
37
37
|
writable: true,
|
|
38
38
|
value: new Map()
|
|
39
39
|
});
|
|
40
|
-
|
|
40
|
+
Object.defineProperty(this, "onButtonEvent", {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
writable: true,
|
|
44
|
+
value: void 0
|
|
45
|
+
});
|
|
46
|
+
Object.defineProperty(this, "onConnected", {
|
|
47
|
+
enumerable: true,
|
|
48
|
+
configurable: true,
|
|
49
|
+
writable: true,
|
|
50
|
+
value: void 0
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(this, "onDisconnected", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
writable: true,
|
|
56
|
+
value: void 0
|
|
57
|
+
});
|
|
58
|
+
// Event handler references for cleanup
|
|
59
|
+
Object.defineProperty(this, "gamepadConnectedHandler", {
|
|
60
|
+
enumerable: true,
|
|
61
|
+
configurable: true,
|
|
62
|
+
writable: true,
|
|
63
|
+
value: void 0
|
|
64
|
+
});
|
|
65
|
+
Object.defineProperty(this, "gamepadDisconnectedHandler", {
|
|
66
|
+
enumerable: true,
|
|
67
|
+
configurable: true,
|
|
68
|
+
writable: true,
|
|
69
|
+
value: void 0
|
|
70
|
+
});
|
|
71
|
+
Object.defineProperty(this, "blurHandler", {
|
|
72
|
+
enumerable: true,
|
|
73
|
+
configurable: true,
|
|
74
|
+
writable: true,
|
|
75
|
+
value: void 0
|
|
76
|
+
});
|
|
77
|
+
// Bind event handlers
|
|
78
|
+
this.gamepadConnectedHandler = this.handleGamepadConnected.bind(this);
|
|
79
|
+
this.gamepadDisconnectedHandler = this.handleGamepadDisconnected.bind(this);
|
|
80
|
+
this.blurHandler = this.handleBlur.bind(this);
|
|
81
|
+
// Register event listeners
|
|
82
|
+
window.addEventListener('gamepadconnected', this.gamepadConnectedHandler);
|
|
83
|
+
window.addEventListener('gamepaddisconnected', this.gamepadDisconnectedHandler);
|
|
84
|
+
window.addEventListener('blur', this.blurHandler);
|
|
85
|
+
}
|
|
86
|
+
handleGamepadConnected(e) {
|
|
87
|
+
this.onGamepadConnectedInternal(e.gamepad);
|
|
88
|
+
this.onConnected?.(e.gamepad);
|
|
89
|
+
}
|
|
90
|
+
handleGamepadDisconnected(e) {
|
|
91
|
+
this.onGamepadDisconnectedInternal(e.gamepad.index);
|
|
92
|
+
this.onDisconnected?.(e.gamepad.index);
|
|
93
|
+
}
|
|
94
|
+
handleBlur() {
|
|
95
|
+
for (const tracker of this.buttonTrackers.values()) {
|
|
96
|
+
tracker.clear();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
setCallbacks(callbacks) {
|
|
100
|
+
this.onConnected = callbacks.onConnected;
|
|
101
|
+
this.onDisconnected = callbacks.onDisconnected;
|
|
102
|
+
}
|
|
103
|
+
dispose() {
|
|
104
|
+
window.removeEventListener('gamepadconnected', this.gamepadConnectedHandler);
|
|
105
|
+
window.removeEventListener('gamepaddisconnected', this.gamepadDisconnectedHandler);
|
|
106
|
+
window.removeEventListener('blur', this.blurHandler);
|
|
107
|
+
this.connectedGamepads.clear();
|
|
108
|
+
this.buttonTrackers.clear();
|
|
109
|
+
this.buttonMappings.clear();
|
|
41
110
|
}
|
|
42
111
|
async init() {
|
|
43
112
|
await gamepadMapping.loadDatabase();
|
|
44
113
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
const hexMatch = id.match(/^([0-9a-fA-F]{4})[\s-]+([0-9a-fA-F]{4})/);
|
|
56
|
-
if (hexMatch) {
|
|
57
|
-
const vendor = parseInt(hexMatch[1], 16);
|
|
58
|
-
const product = parseInt(hexMatch[2], 16);
|
|
59
|
-
if (!isNaN(vendor) && !isNaN(product)) {
|
|
60
|
-
return { vendor, product };
|
|
61
|
-
}
|
|
114
|
+
onGamepadConnectedInternal(gamepad) {
|
|
115
|
+
this.connectedGamepads.set(gamepad.index, gamepad);
|
|
116
|
+
this.buttonTrackers.set(gamepad.index, new InputStateTracker());
|
|
117
|
+
const mapping = gamepadMapping.getMapping(gamepad);
|
|
118
|
+
this.buttonMappings.set(gamepad.index, mapping);
|
|
119
|
+
console.log(`[Gamepad] Connected: "${gamepad.id}"`);
|
|
120
|
+
if (mapping.vendor !== null && mapping.product !== null) {
|
|
121
|
+
console.log(`[Gamepad] Vendor: 0x${mapping.vendor.toString(16).padStart(4, '0')}, Product: 0x${mapping.product.toString(16).padStart(4, '0')}`);
|
|
62
122
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this.buttonMappings.set(e.gamepad.index, mapping);
|
|
71
|
-
console.log(`[Gamepad] Connected: "${e.gamepad.id}"`);
|
|
72
|
-
const vp = this.extractVendorProduct(e.gamepad);
|
|
73
|
-
if (vp) {
|
|
74
|
-
console.log(`[Gamepad] Vendor: 0x${vp.vendor.toString(16).padStart(4, '0')}, Product: 0x${vp.product.toString(16).padStart(4, '0')}`);
|
|
75
|
-
}
|
|
76
|
-
const mappingType = e.gamepad.mapping === 'standard' ? 'browser standard' : (mapping.hasMapping ? 'SDL DB' : 'unmapped');
|
|
77
|
-
console.log(`[Gamepad] Mapped as: "${mapping.controllerName}" (${mappingType})`);
|
|
78
|
-
});
|
|
79
|
-
window.addEventListener('gamepaddisconnected', (e) => {
|
|
80
|
-
this.connectedGamepads.delete(e.gamepad.index);
|
|
81
|
-
this.buttonTrackers.delete(e.gamepad.index);
|
|
82
|
-
this.buttonMappings.delete(e.gamepad.index);
|
|
83
|
-
});
|
|
84
|
-
window.addEventListener('blur', () => {
|
|
85
|
-
for (const tracker of this.buttonTrackers.values()) {
|
|
86
|
-
tracker.clear();
|
|
87
|
-
}
|
|
88
|
-
});
|
|
123
|
+
const mappingType = gamepad.mapping === 'standard' ? 'browser standard' : (mapping.hasMapping ? 'SDL DB' : 'unmapped');
|
|
124
|
+
console.log(`[Gamepad] Mapped as: "${mapping.controllerName}" (${mappingType})`);
|
|
125
|
+
}
|
|
126
|
+
onGamepadDisconnectedInternal(gamepadIndex) {
|
|
127
|
+
this.connectedGamepads.delete(gamepadIndex);
|
|
128
|
+
this.buttonTrackers.delete(gamepadIndex);
|
|
129
|
+
this.buttonMappings.delete(gamepadIndex);
|
|
89
130
|
}
|
|
90
131
|
update() {
|
|
91
132
|
const gamepads = navigator.getGamepads ? navigator.getGamepads() : [];
|
|
92
|
-
const pressed = [];
|
|
93
|
-
const released = [];
|
|
94
133
|
for (let i = 0; i < gamepads.length; i++) {
|
|
95
134
|
const gamepad = gamepads[i];
|
|
96
135
|
if (gamepad) {
|
|
@@ -118,24 +157,13 @@ export class Gamepad {
|
|
|
118
157
|
}
|
|
119
158
|
const changes = tracker.update(pressedButtons);
|
|
120
159
|
for (const buttonIndex of changes.justPressed) {
|
|
121
|
-
|
|
122
|
-
gamepadIndex: i,
|
|
123
|
-
buttonIndex,
|
|
124
|
-
buttonName: getButtonName(buttonIndex),
|
|
125
|
-
rawButtonIndex: mapping.fromStandard.get(buttonIndex) ?? buttonIndex,
|
|
126
|
-
});
|
|
160
|
+
this.onButtonEvent?.(i, buttonIndex, getGPName(buttonIndex), true);
|
|
127
161
|
}
|
|
128
162
|
for (const buttonIndex of changes.justReleased) {
|
|
129
|
-
|
|
130
|
-
gamepadIndex: i,
|
|
131
|
-
buttonIndex,
|
|
132
|
-
buttonName: getButtonName(buttonIndex),
|
|
133
|
-
rawButtonIndex: mapping.fromStandard.get(buttonIndex) ?? buttonIndex,
|
|
134
|
-
});
|
|
163
|
+
this.onButtonEvent?.(i, buttonIndex, getGPName(buttonIndex), false);
|
|
135
164
|
}
|
|
136
165
|
}
|
|
137
166
|
}
|
|
138
|
-
return { pressed, released };
|
|
139
167
|
}
|
|
140
168
|
isConnected(gamepadIndex) {
|
|
141
169
|
return this.connectedGamepads.has(gamepadIndex);
|
|
@@ -144,17 +172,11 @@ export class Gamepad {
|
|
|
144
172
|
* Check if a button is currently pressed on a specific gamepad
|
|
145
173
|
* Uses mapped button indices (standard layout)
|
|
146
174
|
*/
|
|
147
|
-
isButtonDown(gamepadIndex,
|
|
148
|
-
const buttonIndex = typeof button === 'string' ? getButtonIndex(button) : button;
|
|
149
|
-
if (buttonIndex === undefined)
|
|
150
|
-
return false;
|
|
175
|
+
isButtonDown(gamepadIndex, buttonIndex) {
|
|
151
176
|
const tracker = this.buttonTrackers.get(gamepadIndex);
|
|
152
177
|
return tracker ? tracker.isDown(buttonIndex) : false;
|
|
153
178
|
}
|
|
154
|
-
isButtonDownOnAny(
|
|
155
|
-
const buttonIndex = typeof button === 'string' ? getButtonIndex(button) : button;
|
|
156
|
-
if (buttonIndex === undefined)
|
|
157
|
-
return false;
|
|
179
|
+
isButtonDownOnAny(buttonIndex) {
|
|
158
180
|
for (const tracker of this.buttonTrackers.values()) {
|
|
159
181
|
if (tracker.isDown(buttonIndex))
|
|
160
182
|
return true;
|
|
@@ -213,4 +235,3 @@ export class Gamepad {
|
|
|
213
235
|
return applyRadialDeadzone(gamepad.axes[2], gamepad.axes[3]);
|
|
214
236
|
}
|
|
215
237
|
}
|
|
216
|
-
export const gamepad = new Gamepad();
|
|
@@ -40,12 +40,12 @@ export declare class ImageHandle {
|
|
|
40
40
|
}
|
|
41
41
|
export declare class Graphics {
|
|
42
42
|
private ctx;
|
|
43
|
-
private screenCtx;
|
|
43
|
+
private readonly screenCtx;
|
|
44
44
|
private canvases;
|
|
45
45
|
private backgroundColor;
|
|
46
46
|
private images;
|
|
47
47
|
private defaultFont;
|
|
48
|
-
|
|
48
|
+
constructor(ctx: CanvasRenderingContext2D);
|
|
49
49
|
private applyColor;
|
|
50
50
|
private setStrokeProps;
|
|
51
51
|
clear(): void;
|
|
@@ -63,11 +63,6 @@ export declare class Graphics {
|
|
|
63
63
|
getFont(): string;
|
|
64
64
|
newImage(path: string): ImageHandle;
|
|
65
65
|
draw(handle: ImageHandle, position: Vector2, props?: DrawProps): void;
|
|
66
|
-
push(): void;
|
|
67
|
-
pop(): void;
|
|
68
|
-
translate(delta: Vector2): void;
|
|
69
|
-
rotate(angle: number): void;
|
|
70
|
-
scale(s: number | Vector2): void;
|
|
71
66
|
getCanvasSize(): Vector2;
|
|
72
67
|
newCanvas(size: Vector2): Canvas;
|
|
73
68
|
setCanvas(canvas?: Canvas | null): void;
|
|
@@ -76,5 +71,4 @@ export declare class Graphics {
|
|
|
76
71
|
arc(mode: DrawMode, x: number, y: number, radius: number, angle1: number, angle2: number, props?: ShapeProps): void;
|
|
77
72
|
points(color: Color, points: Vector2[]): void;
|
|
78
73
|
}
|
|
79
|
-
export declare const graphics: Graphics;
|
|
80
74
|
//# sourceMappingURL=graphics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphics.d.ts","sourceRoot":"","sources":["../../src/core/graphics.ts"],"names":[],"mappings":"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"}
|
|
@@ -59,18 +59,18 @@ function parseColor(color) {
|
|
|
59
59
|
return `rgba(${r * 255}, ${g * 255}, ${b * 255}, ${a})`;
|
|
60
60
|
}
|
|
61
61
|
export class Graphics {
|
|
62
|
-
constructor() {
|
|
62
|
+
constructor(ctx) {
|
|
63
63
|
Object.defineProperty(this, "ctx", {
|
|
64
64
|
enumerable: true,
|
|
65
65
|
configurable: true,
|
|
66
66
|
writable: true,
|
|
67
|
-
value:
|
|
67
|
+
value: void 0
|
|
68
68
|
});
|
|
69
69
|
Object.defineProperty(this, "screenCtx", {
|
|
70
70
|
enumerable: true,
|
|
71
71
|
configurable: true,
|
|
72
72
|
writable: true,
|
|
73
|
-
value:
|
|
73
|
+
value: void 0
|
|
74
74
|
});
|
|
75
75
|
Object.defineProperty(this, "canvases", {
|
|
76
76
|
enumerable: true,
|
|
@@ -96,13 +96,9 @@ export class Graphics {
|
|
|
96
96
|
writable: true,
|
|
97
97
|
value: '16px sans-serif'
|
|
98
98
|
});
|
|
99
|
-
}
|
|
100
|
-
setContext(ctx) {
|
|
101
99
|
this.screenCtx = ctx;
|
|
102
100
|
this.ctx = ctx;
|
|
103
|
-
|
|
104
|
-
ctx.font = this.defaultFont;
|
|
105
|
-
}
|
|
101
|
+
ctx.font = this.defaultFont;
|
|
106
102
|
}
|
|
107
103
|
applyColor(color) {
|
|
108
104
|
return parseColor(color ?? [1, 1, 1, 1]);
|
|
@@ -269,38 +265,6 @@ export class Graphics {
|
|
|
269
265
|
}
|
|
270
266
|
this.ctx.restore();
|
|
271
267
|
}
|
|
272
|
-
push() {
|
|
273
|
-
if (!this.ctx)
|
|
274
|
-
return;
|
|
275
|
-
this.ctx.save();
|
|
276
|
-
}
|
|
277
|
-
pop() {
|
|
278
|
-
if (!this.ctx)
|
|
279
|
-
return;
|
|
280
|
-
this.ctx.restore();
|
|
281
|
-
}
|
|
282
|
-
translate(delta) {
|
|
283
|
-
if (!this.ctx)
|
|
284
|
-
return;
|
|
285
|
-
const [x, y] = delta;
|
|
286
|
-
this.ctx.translate(x, y);
|
|
287
|
-
}
|
|
288
|
-
rotate(angle) {
|
|
289
|
-
if (!this.ctx)
|
|
290
|
-
return;
|
|
291
|
-
this.ctx.rotate(angle);
|
|
292
|
-
}
|
|
293
|
-
scale(s) {
|
|
294
|
-
if (!this.ctx)
|
|
295
|
-
return;
|
|
296
|
-
if (typeof s === 'number') {
|
|
297
|
-
this.ctx.scale(s, s);
|
|
298
|
-
}
|
|
299
|
-
else {
|
|
300
|
-
const [sx, sy] = s;
|
|
301
|
-
this.ctx.scale(sx, sy);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
268
|
getCanvasSize() {
|
|
305
269
|
const width = this.ctx?.canvas.width ?? 800;
|
|
306
270
|
const height = this.ctx?.canvas.height ?? 600;
|
|
@@ -385,4 +349,3 @@ export class Graphics {
|
|
|
385
349
|
points.forEach(([x, y]) => this.ctx.fillRect(x, y, 1, 1));
|
|
386
350
|
}
|
|
387
351
|
}
|
|
388
|
-
export const graphics = new Graphics();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-state.d.ts","sourceRoot":"","sources":["../../src/core/input-state.ts"],"names":[],"mappings":"AAAA,qBAAa,iBAAiB,CAAC,CAAC;IAC9B,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,SAAS,CAAgB;IAEjC,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG;QAAE,WAAW,EAAE,CAAC,EAAE,CAAC;QAAC,YAAY,EAAE,CAAC,EAAE,CAAA;KAAE;IAuBpE,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IAIvB,WAAW,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IAI5B,YAAY,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IAI7B,eAAe,IAAI,GAAG,CAAC,CAAC,CAAC;IAIzB,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -1,12 +1,22 @@
|
|
|
1
|
+
import type { Keyboard } from './keyboard';
|
|
2
|
+
import type { Mouse } from './mouse';
|
|
3
|
+
import type { Gamepad } from './gamepad';
|
|
1
4
|
export type InputType = 'keyboard' | 'mouse' | 'gamepad';
|
|
2
5
|
export interface InputBinding {
|
|
3
6
|
type: InputType;
|
|
4
7
|
code: string;
|
|
5
|
-
gamepadIndex?: number;
|
|
6
8
|
}
|
|
7
9
|
export declare class Input {
|
|
8
10
|
private actionMap;
|
|
9
11
|
private actionStateTracker;
|
|
12
|
+
private keyboard;
|
|
13
|
+
private mouse;
|
|
14
|
+
private gamepad;
|
|
15
|
+
constructor(deps: {
|
|
16
|
+
keyboard: Keyboard;
|
|
17
|
+
mouse: Mouse;
|
|
18
|
+
gamepad: Gamepad;
|
|
19
|
+
});
|
|
10
20
|
map(action: string, inputs: string[]): void;
|
|
11
21
|
unmap(action: string): void;
|
|
12
22
|
isDown(action: string): boolean;
|
|
@@ -15,22 +25,9 @@ export declare class Input {
|
|
|
15
25
|
update(): {
|
|
16
26
|
pressed: string[];
|
|
17
27
|
released: string[];
|
|
18
|
-
gamepadPressed: Array<{
|
|
19
|
-
gamepadIndex: number;
|
|
20
|
-
buttonIndex: number;
|
|
21
|
-
buttonName: string;
|
|
22
|
-
rawButtonIndex: number;
|
|
23
|
-
}>;
|
|
24
|
-
gamepadReleased: Array<{
|
|
25
|
-
gamepadIndex: number;
|
|
26
|
-
buttonIndex: number;
|
|
27
|
-
buttonName: string;
|
|
28
|
-
rawButtonIndex: number;
|
|
29
|
-
}>;
|
|
30
28
|
};
|
|
31
29
|
private parseInput;
|
|
32
30
|
private isBindingActive;
|
|
33
31
|
clear(): void;
|
|
34
32
|
}
|
|
35
|
-
export declare const input: Input;
|
|
36
33
|
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/core/input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAaD,qBAAa,KAAK;IAChB,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,kBAAkB,CAAmC;IAC7D,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,OAAO,CAAU;gBAEb,IAAI,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE;IAMxE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI;IAK3C,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK3B,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAO/B,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIpC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIrC,MAAM,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE;IAgBnD,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,eAAe;IAuBvB,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { keyboard } from "./keyboard";
|
|
2
|
-
import { mouse } from "./mouse";
|
|
3
|
-
import { gamepad } from "./gamepad";
|
|
4
1
|
import { InputStateTracker } from './input-state';
|
|
5
|
-
import {
|
|
2
|
+
import { GP_NAME_MAP } from './gamepad-buttons';
|
|
6
3
|
const buttonMap = {
|
|
7
4
|
'Left': 1,
|
|
8
5
|
'Right': 3,
|
|
@@ -14,7 +11,7 @@ const buttonMap = {
|
|
|
14
11
|
'5': 5,
|
|
15
12
|
};
|
|
16
13
|
export class Input {
|
|
17
|
-
constructor() {
|
|
14
|
+
constructor(deps) {
|
|
18
15
|
Object.defineProperty(this, "actionMap", {
|
|
19
16
|
enumerable: true,
|
|
20
17
|
configurable: true,
|
|
@@ -27,6 +24,27 @@ export class Input {
|
|
|
27
24
|
writable: true,
|
|
28
25
|
value: new InputStateTracker()
|
|
29
26
|
});
|
|
27
|
+
Object.defineProperty(this, "keyboard", {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
configurable: true,
|
|
30
|
+
writable: true,
|
|
31
|
+
value: void 0
|
|
32
|
+
});
|
|
33
|
+
Object.defineProperty(this, "mouse", {
|
|
34
|
+
enumerable: true,
|
|
35
|
+
configurable: true,
|
|
36
|
+
writable: true,
|
|
37
|
+
value: void 0
|
|
38
|
+
});
|
|
39
|
+
Object.defineProperty(this, "gamepad", {
|
|
40
|
+
enumerable: true,
|
|
41
|
+
configurable: true,
|
|
42
|
+
writable: true,
|
|
43
|
+
value: void 0
|
|
44
|
+
});
|
|
45
|
+
this.keyboard = deps.keyboard;
|
|
46
|
+
this.mouse = deps.mouse;
|
|
47
|
+
this.gamepad = deps.gamepad;
|
|
30
48
|
}
|
|
31
49
|
map(action, inputs) {
|
|
32
50
|
const bindings = inputs.map(input => this.parseInput(input));
|
|
@@ -49,7 +67,7 @@ export class Input {
|
|
|
49
67
|
return this.actionStateTracker.justReleased(action);
|
|
50
68
|
}
|
|
51
69
|
update() {
|
|
52
|
-
|
|
70
|
+
this.gamepad.update();
|
|
53
71
|
const activeActions = new Set();
|
|
54
72
|
for (const [action] of this.actionMap) {
|
|
55
73
|
if (this.isDown(action)) {
|
|
@@ -57,12 +75,7 @@ export class Input {
|
|
|
57
75
|
}
|
|
58
76
|
}
|
|
59
77
|
const { justPressed, justReleased } = this.actionStateTracker.update(activeActions);
|
|
60
|
-
return {
|
|
61
|
-
pressed: justPressed,
|
|
62
|
-
released: justReleased,
|
|
63
|
-
gamepadPressed,
|
|
64
|
-
gamepadReleased,
|
|
65
|
-
};
|
|
78
|
+
return { pressed: justPressed, released: justReleased };
|
|
66
79
|
}
|
|
67
80
|
parseInput(input) {
|
|
68
81
|
const normalized = input.trim();
|
|
@@ -70,48 +83,26 @@ export class Input {
|
|
|
70
83
|
const buttonCode = normalized.replace('Mouse', '');
|
|
71
84
|
return { type: 'mouse', code: buttonCode };
|
|
72
85
|
}
|
|
73
|
-
if (normalized.startsWith('
|
|
74
|
-
|
|
75
|
-
// Format: GP0 ButtonBottom, GP1 LB, etc. - specific gamepad
|
|
76
|
-
const rest = normalized.slice(2); // Remove "GP" prefix
|
|
77
|
-
// Check if there's a gamepad index
|
|
78
|
-
const match = rest.match(/^(\d+)\s+(.+)$/);
|
|
79
|
-
if (match) {
|
|
80
|
-
// Specific gamepad: GP0 ButtonBottom
|
|
81
|
-
const gamepadIndex = parseInt(match[1], 10);
|
|
82
|
-
const buttonName = match[2].trim();
|
|
83
|
-
return { type: 'gamepad', code: buttonName, gamepadIndex };
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
// Any gamepad: GP ButtonBottom
|
|
87
|
-
const buttonName = rest.trim();
|
|
88
|
-
return { type: 'gamepad', code: buttonName };
|
|
89
|
-
}
|
|
86
|
+
if (normalized.startsWith('Button') || normalized.startsWith('DP')) {
|
|
87
|
+
return { type: 'gamepad', code: normalized };
|
|
90
88
|
}
|
|
91
89
|
return { type: 'keyboard', code: normalized };
|
|
92
90
|
}
|
|
93
91
|
isBindingActive(binding) {
|
|
94
92
|
switch (binding.type) {
|
|
95
93
|
case 'keyboard':
|
|
96
|
-
return keyboard.isDown(binding.code);
|
|
94
|
+
return this.keyboard.isDown(binding.code);
|
|
97
95
|
case 'mouse': {
|
|
98
96
|
const button = buttonMap[binding.code];
|
|
99
97
|
if (button !== undefined) {
|
|
100
|
-
return mouse.isDown(button);
|
|
98
|
+
return this.mouse.isDown(button);
|
|
101
99
|
}
|
|
102
100
|
return false;
|
|
103
101
|
}
|
|
104
102
|
case 'gamepad': {
|
|
105
|
-
const buttonIndex =
|
|
103
|
+
const buttonIndex = GP_NAME_MAP[binding.code];
|
|
106
104
|
if (buttonIndex !== undefined) {
|
|
107
|
-
|
|
108
|
-
// Check specific gamepad
|
|
109
|
-
return gamepad.isButtonDown(binding.gamepadIndex, buttonIndex);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
// Check any gamepad
|
|
113
|
-
return gamepad.isButtonDownOnAny(buttonIndex);
|
|
114
|
-
}
|
|
105
|
+
return this.gamepad.isButtonDownOnAny(buttonIndex);
|
|
115
106
|
}
|
|
116
107
|
return false;
|
|
117
108
|
}
|
|
@@ -124,4 +115,3 @@ export class Input {
|
|
|
124
115
|
this.actionStateTracker.clear();
|
|
125
116
|
}
|
|
126
117
|
}
|
|
127
|
-
export const input = new Input();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class Keyboard {
|
|
2
|
+
private pressedScancodes;
|
|
3
|
+
onKeyEvent?: (scancode: string, keycode: string, type: 'keydown' | 'keyup') => void;
|
|
4
|
+
private keydownHandler;
|
|
5
|
+
private keyupHandler;
|
|
6
|
+
private blurHandler;
|
|
7
|
+
constructor();
|
|
8
|
+
private handleKeyDown;
|
|
9
|
+
private handleKeyUp;
|
|
10
|
+
private handleBlur;
|
|
11
|
+
dispose(): void;
|
|
12
|
+
isDown(scancode: string): boolean;
|
|
13
|
+
isAnyDown(...scancodes: string[]): boolean;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=keyboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../src/core/keyboard.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAQ;IACnB,OAAO,CAAC,gBAAgB,CAAqB;IACtC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,KAAK,IAAI,CAAC;IAG3F,OAAO,CAAC,cAAc,CAAwC;IAC9D,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,WAAW,CAAa;;IAchC,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,UAAU;IAIlB,OAAO,IAAI,IAAI;IAOf,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIjC,SAAS,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO;CAG3C"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export class Keyboard {
|
|
2
|
+
constructor() {
|
|
3
|
+
Object.defineProperty(this, "pressedScancodes", {
|
|
4
|
+
enumerable: true,
|
|
5
|
+
configurable: true,
|
|
6
|
+
writable: true,
|
|
7
|
+
value: new Set()
|
|
8
|
+
});
|
|
9
|
+
Object.defineProperty(this, "onKeyEvent", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
configurable: true,
|
|
12
|
+
writable: true,
|
|
13
|
+
value: void 0
|
|
14
|
+
});
|
|
15
|
+
// Event handler references for cleanup
|
|
16
|
+
Object.defineProperty(this, "keydownHandler", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: void 0
|
|
21
|
+
});
|
|
22
|
+
Object.defineProperty(this, "keyupHandler", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
writable: true,
|
|
26
|
+
value: void 0
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(this, "blurHandler", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
value: void 0
|
|
33
|
+
});
|
|
34
|
+
// Bind event handlers
|
|
35
|
+
this.keydownHandler = this.handleKeyDown.bind(this);
|
|
36
|
+
this.keyupHandler = this.handleKeyUp.bind(this);
|
|
37
|
+
this.blurHandler = this.handleBlur.bind(this);
|
|
38
|
+
// Register event listeners
|
|
39
|
+
window.addEventListener('keydown', this.keydownHandler);
|
|
40
|
+
window.addEventListener('keyup', this.keyupHandler);
|
|
41
|
+
window.addEventListener('blur', this.blurHandler);
|
|
42
|
+
}
|
|
43
|
+
handleKeyDown(e) {
|
|
44
|
+
if (e.code) {
|
|
45
|
+
this.pressedScancodes.add(e.code);
|
|
46
|
+
}
|
|
47
|
+
this.onKeyEvent?.(e.code, e.key, 'keydown');
|
|
48
|
+
}
|
|
49
|
+
handleKeyUp(e) {
|
|
50
|
+
if (e.code) {
|
|
51
|
+
this.pressedScancodes.delete(e.code);
|
|
52
|
+
}
|
|
53
|
+
this.onKeyEvent?.(e.code, e.key, 'keyup');
|
|
54
|
+
}
|
|
55
|
+
handleBlur() {
|
|
56
|
+
this.pressedScancodes.clear();
|
|
57
|
+
}
|
|
58
|
+
dispose() {
|
|
59
|
+
window.removeEventListener('keydown', this.keydownHandler);
|
|
60
|
+
window.removeEventListener('keyup', this.keyupHandler);
|
|
61
|
+
window.removeEventListener('blur', this.blurHandler);
|
|
62
|
+
this.pressedScancodes.clear();
|
|
63
|
+
}
|
|
64
|
+
isDown(scancode) {
|
|
65
|
+
return this.pressedScancodes.has(scancode);
|
|
66
|
+
}
|
|
67
|
+
isAnyDown(...scancodes) {
|
|
68
|
+
return scancodes.some(code => this.pressedScancodes.has(code));
|
|
69
|
+
}
|
|
70
|
+
}
|