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.
- package/README.md +66 -0
- package/dist/audio.d.ts +52 -0
- package/dist/audio.d.ts.map +1 -0
- package/dist/audio.js +250 -0
- package/dist/events.d.ts +36 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +1 -0
- package/dist/gamecontrollerdb.txt +2219 -0
- package/dist/gamepad-button-map.d.ts +5 -0
- package/dist/gamepad-button-map.d.ts.map +1 -0
- package/dist/gamepad-button-map.js +56 -0
- package/dist/gamepad-db.d.ts +49 -0
- package/dist/gamepad-db.d.ts.map +1 -0
- package/dist/gamepad-db.js +192 -0
- package/dist/gamepad-mapping.d.ts +31 -0
- package/dist/gamepad-mapping.d.ts.map +1 -0
- package/dist/gamepad-mapping.js +191 -0
- package/dist/gamepad.d.ts +56 -0
- package/dist/gamepad.d.ts.map +1 -0
- package/dist/gamepad.js +216 -0
- package/dist/graphics.d.ts +80 -0
- package/dist/graphics.d.ts.map +1 -0
- package/dist/graphics.js +388 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +250 -0
- package/dist/input-state.d.ts +14 -0
- package/dist/input-state.d.ts.map +1 -0
- package/dist/input-state.js +50 -0
- package/dist/input.d.ts +36 -0
- package/dist/input.d.ts.map +1 -0
- package/dist/input.js +127 -0
- package/dist/keyboard.d.ts +9 -0
- package/dist/keyboard.d.ts.map +1 -0
- package/dist/keyboard.js +33 -0
- package/dist/mouse.d.ts +20 -0
- package/dist/mouse.d.ts.map +1 -0
- package/dist/mouse.js +84 -0
- package/dist/rect.d.ts +27 -0
- package/dist/rect.d.ts.map +1 -0
- package/dist/rect.js +132 -0
- package/dist/scene.d.ts +10 -0
- package/dist/scene.d.ts.map +1 -0
- package/dist/scene.js +1 -0
- package/dist/timer.d.ts +19 -0
- package/dist/timer.d.ts.map +1 -0
- package/dist/timer.js +86 -0
- package/dist/vector2.d.ts +32 -0
- package/dist/vector2.d.ts.map +1 -0
- package/dist/vector2.js +105 -0
- package/package.json +64 -0
package/dist/index.d.ts
ADDED
|
@@ -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
|
+
}
|
package/dist/input.d.ts
ADDED
|
@@ -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"}
|
package/dist/keyboard.js
ADDED
|
@@ -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();
|
package/dist/mouse.d.ts
ADDED
|
@@ -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"}
|