like2d 1.0.0

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.
Files changed (51) hide show
  1. package/README.md +66 -0
  2. package/dist/audio.d.ts +52 -0
  3. package/dist/audio.d.ts.map +1 -0
  4. package/dist/audio.js +250 -0
  5. package/dist/events.d.ts +36 -0
  6. package/dist/events.d.ts.map +1 -0
  7. package/dist/events.js +1 -0
  8. package/dist/gamecontrollerdb.txt +2219 -0
  9. package/dist/gamepad-button-map.d.ts +5 -0
  10. package/dist/gamepad-button-map.d.ts.map +1 -0
  11. package/dist/gamepad-button-map.js +56 -0
  12. package/dist/gamepad-db.d.ts +49 -0
  13. package/dist/gamepad-db.d.ts.map +1 -0
  14. package/dist/gamepad-db.js +192 -0
  15. package/dist/gamepad-mapping.d.ts +31 -0
  16. package/dist/gamepad-mapping.d.ts.map +1 -0
  17. package/dist/gamepad-mapping.js +191 -0
  18. package/dist/gamepad.d.ts +56 -0
  19. package/dist/gamepad.d.ts.map +1 -0
  20. package/dist/gamepad.js +216 -0
  21. package/dist/graphics.d.ts +80 -0
  22. package/dist/graphics.d.ts.map +1 -0
  23. package/dist/graphics.js +388 -0
  24. package/dist/index.d.ts +45 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +250 -0
  27. package/dist/input-state.d.ts +14 -0
  28. package/dist/input-state.d.ts.map +1 -0
  29. package/dist/input-state.js +50 -0
  30. package/dist/input.d.ts +36 -0
  31. package/dist/input.d.ts.map +1 -0
  32. package/dist/input.js +127 -0
  33. package/dist/keyboard.d.ts +9 -0
  34. package/dist/keyboard.d.ts.map +1 -0
  35. package/dist/keyboard.js +33 -0
  36. package/dist/mouse.d.ts +20 -0
  37. package/dist/mouse.d.ts.map +1 -0
  38. package/dist/mouse.js +84 -0
  39. package/dist/rect.d.ts +27 -0
  40. package/dist/rect.d.ts.map +1 -0
  41. package/dist/rect.js +132 -0
  42. package/dist/scene.d.ts +10 -0
  43. package/dist/scene.d.ts.map +1 -0
  44. package/dist/scene.js +1 -0
  45. package/dist/timer.d.ts +19 -0
  46. package/dist/timer.d.ts.map +1 -0
  47. package/dist/timer.js +86 -0
  48. package/dist/vector2.d.ts +32 -0
  49. package/dist/vector2.d.ts.map +1 -0
  50. package/dist/vector2.js +105 -0
  51. package/package.json +64 -0
@@ -0,0 +1,45 @@
1
+ import { Scene } from './scene';
2
+ declare class Like {
3
+ private canvas;
4
+ private ctx;
5
+ private currentScene;
6
+ private isRunning;
7
+ private lastTime;
8
+ private currentWidth;
9
+ private currentHeight;
10
+ graphics: import("./graphics").Graphics;
11
+ audio: import("./audio").Audio;
12
+ keyboard: import("./keyboard").Keyboard;
13
+ mouse: import("./mouse").Mouse;
14
+ input: import("./input").Input;
15
+ gamepad: import("./gamepad").Gamepad;
16
+ timer: import("./timer").Timer;
17
+ constructor();
18
+ init(container: HTMLElement, width?: number, height?: number): Promise<void>;
19
+ toggleFullscreen(): void;
20
+ private setupInputHandlers;
21
+ setScene(scene: Scene): void;
22
+ start(scene: Scene): void;
23
+ private loop;
24
+ getCanvas(): HTMLCanvasElement | null;
25
+ getContext(): CanvasRenderingContext2D | null;
26
+ getWidth(): number;
27
+ getHeight(): number;
28
+ }
29
+ export declare const like: Like;
30
+ export declare const love: Like;
31
+ export { Source } from './audio';
32
+ export type { SourceOptions } from './audio';
33
+ export { timer } from './timer';
34
+ export type { Scene } from './scene';
35
+ export { ImageHandle } from './graphics';
36
+ export type { Color, Quad, ShapeProps, DrawProps, PrintProps } from './graphics';
37
+ export { input } from './input';
38
+ export { gamepad, getButtonName } from './gamepad';
39
+ export type { StickPosition } from './gamepad';
40
+ export type { Vector2 } from './vector2';
41
+ export { V2 } from './vector2';
42
+ export type { Rect } from './rect';
43
+ export { R } from './rect';
44
+ export type { Event } from './events';
45
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,cAAM,IAAI;IACR,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,GAAG,CAAyC;IACpD,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,YAAY,CAAO;IAC3B,OAAO,CAAC,aAAa,CAAO;IAE5B,QAAQ,gCAAY;IACpB,KAAK,0BAAS;IACd,QAAQ,gCAAY;IACpB,KAAK,0BAAS;IACd,KAAK,0BAAS;IACd,OAAO,8BAAW;IAClB,KAAK,0BAAS;;IAIR,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,KAAK,GAAE,MAAY,EAAE,MAAM,GAAE,MAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B5F,gBAAgB,IAAI,IAAI;IAYxB,OAAO,CAAC,kBAAkB;IAwC1B,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAkB5B,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAczB,OAAO,CAAC,IAAI;IAiDZ,SAAS,IAAI,iBAAiB,GAAG,IAAI;IAIrC,UAAU,IAAI,wBAAwB,GAAG,IAAI;IAI7C,QAAQ,IAAI,MAAM;IAIlB,SAAS,IAAI,MAAM;CAGpB;AAED,eAAO,MAAM,IAAI,MAAa,CAAC;AAC/B,eAAO,MAAM,IAAI,MAAO,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,YAAY,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAC/B,YAAY,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,YAAY,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,250 @@
1
+ import { graphics } from './graphics';
2
+ import { audio } from './audio';
3
+ import { keyboard } from './keyboard';
4
+ import { mouse } from './mouse';
5
+ import { input } from './input';
6
+ import { gamepad } from './gamepad';
7
+ import { timer } from './timer';
8
+ class Like {
9
+ constructor() {
10
+ Object.defineProperty(this, "canvas", {
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true,
14
+ value: null
15
+ });
16
+ Object.defineProperty(this, "ctx", {
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true,
20
+ value: null
21
+ });
22
+ Object.defineProperty(this, "currentScene", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: null
27
+ });
28
+ Object.defineProperty(this, "isRunning", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: false
33
+ });
34
+ Object.defineProperty(this, "lastTime", {
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true,
38
+ value: 0
39
+ });
40
+ Object.defineProperty(this, "currentWidth", {
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true,
44
+ value: 800
45
+ });
46
+ Object.defineProperty(this, "currentHeight", {
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ value: 600
51
+ });
52
+ Object.defineProperty(this, "graphics", {
53
+ enumerable: true,
54
+ configurable: true,
55
+ writable: true,
56
+ value: graphics
57
+ });
58
+ Object.defineProperty(this, "audio", {
59
+ enumerable: true,
60
+ configurable: true,
61
+ writable: true,
62
+ value: audio
63
+ });
64
+ Object.defineProperty(this, "keyboard", {
65
+ enumerable: true,
66
+ configurable: true,
67
+ writable: true,
68
+ value: keyboard
69
+ });
70
+ Object.defineProperty(this, "mouse", {
71
+ enumerable: true,
72
+ configurable: true,
73
+ writable: true,
74
+ value: mouse
75
+ });
76
+ Object.defineProperty(this, "input", {
77
+ enumerable: true,
78
+ configurable: true,
79
+ writable: true,
80
+ value: input
81
+ });
82
+ Object.defineProperty(this, "gamepad", {
83
+ enumerable: true,
84
+ configurable: true,
85
+ writable: true,
86
+ value: gamepad
87
+ });
88
+ Object.defineProperty(this, "timer", {
89
+ enumerable: true,
90
+ configurable: true,
91
+ writable: true,
92
+ value: timer
93
+ });
94
+ }
95
+ async init(container, width = 800, height = 600) {
96
+ this.currentWidth = width;
97
+ this.currentHeight = height;
98
+ this.canvas = document.createElement('canvas');
99
+ this.canvas.width = width;
100
+ this.canvas.height = height;
101
+ this.canvas.style.border = '1px solid #ccc';
102
+ this.canvas.style.display = 'block';
103
+ this.ctx = this.canvas.getContext('2d');
104
+ if (!this.ctx) {
105
+ throw new Error('Failed to get 2D context');
106
+ }
107
+ graphics.setContext(this.ctx);
108
+ mouse.setCanvas(this.canvas);
109
+ container.appendChild(this.canvas);
110
+ this.setupInputHandlers();
111
+ // Initialize gamepad mapping database
112
+ await gamepad.init();
113
+ }
114
+ toggleFullscreen() {
115
+ if (!this.canvas)
116
+ return;
117
+ if (!document.fullscreenElement) {
118
+ this.canvas.requestFullscreen().catch(err => {
119
+ console.error(`Error attempting to enable fullscreen: ${err.message}`);
120
+ });
121
+ }
122
+ else {
123
+ document.exitFullscreen();
124
+ }
125
+ }
126
+ setupInputHandlers() {
127
+ window.addEventListener('keydown', (e) => {
128
+ if (this.currentScene?.handleEvent) {
129
+ this.currentScene.handleEvent({ type: 'keypressed', scancode: e.code, keycode: e.key });
130
+ }
131
+ });
132
+ window.addEventListener('keyup', (e) => {
133
+ if (this.currentScene?.handleEvent) {
134
+ this.currentScene.handleEvent({ type: 'keyreleased', scancode: e.code, keycode: e.key });
135
+ }
136
+ });
137
+ if (this.canvas) {
138
+ this.canvas.addEventListener('mousedown', (e) => {
139
+ if (this.currentScene?.handleEvent) {
140
+ const rect = this.canvas.getBoundingClientRect();
141
+ this.currentScene.handleEvent({
142
+ type: 'mousepressed',
143
+ x: e.clientX - rect.left,
144
+ y: e.clientY - rect.top,
145
+ button: e.button + 1
146
+ });
147
+ }
148
+ });
149
+ this.canvas.addEventListener('mouseup', (e) => {
150
+ if (this.currentScene?.handleEvent) {
151
+ const rect = this.canvas.getBoundingClientRect();
152
+ this.currentScene.handleEvent({
153
+ type: 'mousereleased',
154
+ x: e.clientX - rect.left,
155
+ y: e.clientY - rect.top,
156
+ button: e.button + 1
157
+ });
158
+ }
159
+ });
160
+ }
161
+ }
162
+ setScene(scene) {
163
+ this.currentScene = scene;
164
+ timer.resetSceneTime();
165
+ if (this.canvas) {
166
+ if (scene.width !== this.currentWidth || scene.height !== this.currentHeight) {
167
+ this.currentWidth = scene.width;
168
+ this.currentHeight = scene.height;
169
+ this.canvas.width = scene.width;
170
+ this.canvas.height = scene.height;
171
+ }
172
+ }
173
+ if (this.isRunning && scene.load) {
174
+ scene.load();
175
+ }
176
+ }
177
+ start(scene) {
178
+ if (this.isRunning)
179
+ return;
180
+ this.setScene(scene);
181
+ this.isRunning = true;
182
+ if (this.currentScene?.load) {
183
+ this.currentScene.load();
184
+ }
185
+ this.lastTime = performance.now();
186
+ this.loop();
187
+ }
188
+ loop() {
189
+ if (!this.isRunning || !this.currentScene)
190
+ return;
191
+ const currentTime = performance.now();
192
+ const dt = (currentTime - this.lastTime) / 1000;
193
+ this.lastTime = currentTime;
194
+ if (timer.isSleeping()) {
195
+ requestAnimationFrame(() => this.loop());
196
+ return;
197
+ }
198
+ timer.update(dt);
199
+ const { pressed, released, gamepadPressed, gamepadReleased } = input.update();
200
+ // Trigger action callbacks
201
+ if (this.currentScene?.handleEvent) {
202
+ for (const action of pressed) {
203
+ this.currentScene.handleEvent({ type: 'actionpressed', action });
204
+ }
205
+ }
206
+ if (this.currentScene?.handleEvent) {
207
+ for (const action of released) {
208
+ this.currentScene.handleEvent({ type: 'actionreleased', action });
209
+ }
210
+ }
211
+ // Trigger gamepad callbacks
212
+ if (this.currentScene?.handleEvent) {
213
+ for (const { gamepadIndex, buttonIndex, buttonName } of gamepadPressed) {
214
+ this.currentScene.handleEvent({ type: 'gamepadpressed', gamepadIndex, buttonIndex, buttonName });
215
+ }
216
+ }
217
+ if (this.currentScene?.handleEvent) {
218
+ for (const { gamepadIndex, buttonIndex, buttonName } of gamepadReleased) {
219
+ this.currentScene.handleEvent({ type: 'gamepadreleased', gamepadIndex, buttonIndex, buttonName });
220
+ }
221
+ }
222
+ this.currentScene.update(dt);
223
+ if (this.ctx) {
224
+ graphics.clear();
225
+ this.currentScene.draw();
226
+ }
227
+ requestAnimationFrame(() => this.loop());
228
+ }
229
+ getCanvas() {
230
+ return this.canvas;
231
+ }
232
+ getContext() {
233
+ return this.ctx;
234
+ }
235
+ getWidth() {
236
+ return this.currentWidth;
237
+ }
238
+ getHeight() {
239
+ return this.currentHeight;
240
+ }
241
+ }
242
+ export const like = new Like();
243
+ export const love = like;
244
+ export { Source } from './audio';
245
+ export { timer } from './timer';
246
+ export { ImageHandle } from './graphics';
247
+ export { input } from './input';
248
+ export { gamepad, getButtonName } from './gamepad';
249
+ export { V2 } from './vector2';
250
+ export { R } from './rect';
@@ -0,0 +1,14 @@
1
+ export declare class InputStateTracker<T> {
2
+ private prevState;
3
+ private currState;
4
+ update(pressedKeys: Set<T>): {
5
+ justPressed: T[];
6
+ justReleased: T[];
7
+ };
8
+ isDown(key: T): boolean;
9
+ justPressed(key: T): boolean;
10
+ justReleased(key: T): boolean;
11
+ getCurrentState(): Set<T>;
12
+ clear(): void;
13
+ }
14
+ //# sourceMappingURL=input-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-state.d.ts","sourceRoot":"","sources":["../src/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"}
@@ -0,0 +1,50 @@
1
+ export class InputStateTracker {
2
+ constructor() {
3
+ Object.defineProperty(this, "prevState", {
4
+ enumerable: true,
5
+ configurable: true,
6
+ writable: true,
7
+ value: new Set()
8
+ });
9
+ Object.defineProperty(this, "currState", {
10
+ enumerable: true,
11
+ configurable: true,
12
+ writable: true,
13
+ value: new Set()
14
+ });
15
+ }
16
+ update(pressedKeys) {
17
+ const justPressed = [];
18
+ const justReleased = [];
19
+ const nextState = new Set(pressedKeys);
20
+ for (const key of nextState) {
21
+ if (!this.currState.has(key)) {
22
+ justPressed.push(key);
23
+ }
24
+ }
25
+ for (const key of this.currState) {
26
+ if (!nextState.has(key)) {
27
+ justReleased.push(key);
28
+ }
29
+ }
30
+ this.prevState = new Set(this.currState);
31
+ this.currState = nextState;
32
+ return { justPressed, justReleased };
33
+ }
34
+ isDown(key) {
35
+ return this.currState.has(key);
36
+ }
37
+ justPressed(key) {
38
+ return !this.prevState.has(key) && this.currState.has(key);
39
+ }
40
+ justReleased(key) {
41
+ return this.prevState.has(key) && !this.currState.has(key);
42
+ }
43
+ getCurrentState() {
44
+ return new Set(this.currState);
45
+ }
46
+ clear() {
47
+ this.prevState.clear();
48
+ this.currState.clear();
49
+ }
50
+ }
@@ -0,0 +1,36 @@
1
+ export type InputType = 'keyboard' | 'mouse' | 'gamepad';
2
+ export interface InputBinding {
3
+ type: InputType;
4
+ code: string;
5
+ gamepadIndex?: number;
6
+ }
7
+ export declare class Input {
8
+ private actionMap;
9
+ private actionStateTracker;
10
+ map(action: string, inputs: string[]): void;
11
+ unmap(action: string): void;
12
+ isDown(action: string): boolean;
13
+ justPressed(action: string): boolean;
14
+ justReleased(action: string): boolean;
15
+ update(): {
16
+ pressed: string[];
17
+ 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
+ };
31
+ private parseInput;
32
+ private isBindingActive;
33
+ clear(): void;
34
+ }
35
+ export declare const input: Input;
36
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../src/input.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAaD,qBAAa,KAAK;IAChB,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,kBAAkB,CAAmC;IAE7D,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;QACR,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,cAAc,EAAE,KAAK,CAAC;YAAE,YAAY,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAC;YAAC,cAAc,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACjH,eAAe,EAAE,KAAK,CAAC;YAAE,YAAY,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAC;YAAC,cAAc,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACnH;IAqBD,OAAO,CAAC,UAAU;IA8BlB,OAAO,CAAC,eAAe;IA6BvB,KAAK,IAAI,IAAI;CAId;AAED,eAAO,MAAM,KAAK,OAAc,CAAC"}
package/dist/input.js ADDED
@@ -0,0 +1,127 @@
1
+ import { keyboard } from "./keyboard";
2
+ import { mouse } from "./mouse";
3
+ import { gamepad } from "./gamepad";
4
+ import { InputStateTracker } from './input-state';
5
+ import { getButtonIndex } from './gamepad-button-map';
6
+ const buttonMap = {
7
+ 'Left': 1,
8
+ 'Right': 3,
9
+ 'Middle': 2,
10
+ '1': 1,
11
+ '2': 2,
12
+ '3': 3,
13
+ '4': 4,
14
+ '5': 5,
15
+ };
16
+ export class Input {
17
+ constructor() {
18
+ Object.defineProperty(this, "actionMap", {
19
+ enumerable: true,
20
+ configurable: true,
21
+ writable: true,
22
+ value: new Map()
23
+ });
24
+ Object.defineProperty(this, "actionStateTracker", {
25
+ enumerable: true,
26
+ configurable: true,
27
+ writable: true,
28
+ value: new InputStateTracker()
29
+ });
30
+ }
31
+ map(action, inputs) {
32
+ const bindings = inputs.map(input => this.parseInput(input));
33
+ this.actionMap.set(action, bindings);
34
+ }
35
+ unmap(action) {
36
+ this.actionMap.delete(action);
37
+ this.actionStateTracker.clear();
38
+ }
39
+ isDown(action) {
40
+ const bindings = this.actionMap.get(action);
41
+ if (!bindings)
42
+ return false;
43
+ return bindings.some(binding => this.isBindingActive(binding));
44
+ }
45
+ justPressed(action) {
46
+ return this.actionStateTracker.justPressed(action);
47
+ }
48
+ justReleased(action) {
49
+ return this.actionStateTracker.justReleased(action);
50
+ }
51
+ update() {
52
+ const { pressed: gamepadPressed, released: gamepadReleased } = gamepad.update();
53
+ const activeActions = new Set();
54
+ for (const [action] of this.actionMap) {
55
+ if (this.isDown(action)) {
56
+ activeActions.add(action);
57
+ }
58
+ }
59
+ const { justPressed, justReleased } = this.actionStateTracker.update(activeActions);
60
+ return {
61
+ pressed: justPressed,
62
+ released: justReleased,
63
+ gamepadPressed,
64
+ gamepadReleased,
65
+ };
66
+ }
67
+ parseInput(input) {
68
+ const normalized = input.trim();
69
+ if (normalized.startsWith('Mouse')) {
70
+ const buttonCode = normalized.replace('Mouse', '');
71
+ return { type: 'mouse', code: buttonCode };
72
+ }
73
+ if (normalized.startsWith('GP')) {
74
+ // Format: GP ButtonBottom, GP LB, GP RT, etc. - any gamepad
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
+ }
90
+ }
91
+ return { type: 'keyboard', code: normalized };
92
+ }
93
+ isBindingActive(binding) {
94
+ switch (binding.type) {
95
+ case 'keyboard':
96
+ return keyboard.isDown(binding.code);
97
+ case 'mouse': {
98
+ const button = buttonMap[binding.code];
99
+ if (button !== undefined) {
100
+ return mouse.isDown(button);
101
+ }
102
+ return false;
103
+ }
104
+ case 'gamepad': {
105
+ const buttonIndex = getButtonIndex(binding.code);
106
+ if (buttonIndex !== undefined) {
107
+ if (binding.gamepadIndex !== undefined) {
108
+ // Check specific gamepad
109
+ return gamepad.isButtonDown(binding.gamepadIndex, buttonIndex);
110
+ }
111
+ else {
112
+ // Check any gamepad
113
+ return gamepad.isButtonDownOnAny(buttonIndex);
114
+ }
115
+ }
116
+ return false;
117
+ }
118
+ default:
119
+ return false;
120
+ }
121
+ }
122
+ clear() {
123
+ this.actionMap.clear();
124
+ this.actionStateTracker.clear();
125
+ }
126
+ }
127
+ export const input = new Input();
@@ -0,0 +1,9 @@
1
+ export declare class Keyboard {
2
+ private pressedScancodes;
3
+ constructor();
4
+ private setupEventListeners;
5
+ isDown(scancode: string): boolean;
6
+ isAnyDown(...scancodes: string[]): boolean;
7
+ }
8
+ export declare const keyboard: Keyboard;
9
+ //# sourceMappingURL=keyboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../src/keyboard.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAQ;IACnB,OAAO,CAAC,gBAAgB,CAAqB;;IAM7C,OAAO,CAAC,mBAAmB;IAkB3B,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIjC,SAAS,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO;CAG3C;AAED,eAAO,MAAM,QAAQ,UAAiB,CAAC"}
@@ -0,0 +1,33 @@
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
+ this.setupEventListeners();
10
+ }
11
+ setupEventListeners() {
12
+ window.addEventListener('keydown', (e) => {
13
+ if (e.code) {
14
+ this.pressedScancodes.add(e.code);
15
+ }
16
+ });
17
+ window.addEventListener('keyup', (e) => {
18
+ if (e.code) {
19
+ this.pressedScancodes.delete(e.code);
20
+ }
21
+ });
22
+ window.addEventListener('blur', () => {
23
+ this.pressedScancodes.clear();
24
+ });
25
+ }
26
+ isDown(scancode) {
27
+ return this.pressedScancodes.has(scancode);
28
+ }
29
+ isAnyDown(...scancodes) {
30
+ return scancodes.some(code => this.pressedScancodes.has(code));
31
+ }
32
+ }
33
+ export const keyboard = new Keyboard();
@@ -0,0 +1,20 @@
1
+ import type { Vector2 } from './vector2';
2
+ export declare class Mouse {
3
+ private x;
4
+ private y;
5
+ private buttons;
6
+ private canvas;
7
+ constructor();
8
+ setCanvas(canvas: HTMLCanvasElement): void;
9
+ private setupEventListeners;
10
+ getPosition(): Vector2;
11
+ getX(): number;
12
+ getY(): number;
13
+ isDown(button: number): boolean;
14
+ getPressedButtons(): Set<number>;
15
+ isVisible(): boolean;
16
+ setVisible(visible: boolean): void;
17
+ getRelativeMode(): boolean;
18
+ }
19
+ export declare const mouse: Mouse;
20
+ //# sourceMappingURL=mouse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mouse.d.ts","sourceRoot":"","sources":["../src/mouse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,qBAAa,KAAK;IAChB,OAAO,CAAC,CAAC,CAAK;IACd,OAAO,CAAC,CAAC,CAAK;IACd,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,MAAM,CAAkC;;IAMhD,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAI1C,OAAO,CAAC,mBAAmB;IAyB3B,WAAW,IAAI,OAAO;IAItB,IAAI,IAAI,MAAM;IAId,IAAI,IAAI,MAAM;IAId,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAI/B,iBAAiB,IAAI,GAAG,CAAC,MAAM,CAAC;IAIhC,SAAS,IAAI,OAAO;IAIpB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAQlC,eAAe,IAAI,OAAO;CAG3B;AAED,eAAO,MAAM,KAAK,OAAc,CAAC"}