like2d 2.8.0 → 2.10.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 (122) hide show
  1. package/README.md +44 -41
  2. package/dist/__benchmarks__/vector2.bench.d.ts +2 -0
  3. package/dist/__benchmarks__/vector2.bench.d.ts.map +1 -0
  4. package/dist/__benchmarks__/vector2.bench.js +74 -0
  5. package/dist/{core → audio}/audio.d.ts +21 -9
  6. package/dist/audio/audio.d.ts.map +1 -0
  7. package/dist/{core → audio}/audio.js +15 -4
  8. package/dist/audio/index.d.ts +2 -0
  9. package/dist/audio/index.d.ts.map +1 -0
  10. package/dist/engine.d.ts +30 -15
  11. package/dist/engine.d.ts.map +1 -1
  12. package/dist/engine.js +79 -160
  13. package/dist/events.d.ts +86 -0
  14. package/dist/events.d.ts.map +1 -0
  15. package/dist/events.js +5 -0
  16. package/dist/gamecontrollerdb.txt +9 -8
  17. package/dist/graphics/canvas.d.ts +65 -0
  18. package/dist/graphics/canvas.d.ts.map +1 -0
  19. package/dist/graphics/canvas.js +224 -0
  20. package/dist/graphics/drawing.d.ts +203 -0
  21. package/dist/graphics/drawing.d.ts.map +1 -0
  22. package/dist/graphics/drawing.js +388 -0
  23. package/dist/graphics/index.d.ts +19 -0
  24. package/dist/graphics/index.d.ts.map +1 -0
  25. package/dist/graphics/index.js +13 -0
  26. package/dist/index.d.ts +18 -24
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +15 -15
  29. package/dist/input/gamepad-mapping.d.ts +134 -0
  30. package/dist/input/gamepad-mapping.d.ts.map +1 -0
  31. package/dist/input/gamepad-mapping.js +146 -0
  32. package/dist/input/gamepad.d.ts +74 -0
  33. package/dist/input/gamepad.d.ts.map +1 -0
  34. package/dist/input/gamepad.js +288 -0
  35. package/dist/input/index.d.ts +6 -0
  36. package/dist/input/index.d.ts.map +1 -0
  37. package/dist/input/index.js +1 -0
  38. package/dist/input/input.d.ts +76 -0
  39. package/dist/input/input.d.ts.map +1 -0
  40. package/dist/input/input.js +164 -0
  41. package/dist/input/keyboard.d.ts +15 -0
  42. package/dist/input/keyboard.d.ts.map +1 -0
  43. package/dist/input/keyboard.js +53 -0
  44. package/dist/input/mouse.d.ts +108 -0
  45. package/dist/input/mouse.d.ts.map +1 -0
  46. package/dist/input/mouse.js +241 -0
  47. package/dist/like.d.ts +80 -0
  48. package/dist/like.d.ts.map +1 -0
  49. package/dist/like.js +5 -0
  50. package/dist/math/index.d.ts +18 -0
  51. package/dist/math/index.d.ts.map +1 -0
  52. package/dist/math/index.js +17 -0
  53. package/dist/math/rect.d.ts +68 -0
  54. package/dist/math/rect.d.ts.map +1 -0
  55. package/dist/{core → math}/rect.js +48 -66
  56. package/dist/math/vector2.d.ts +133 -0
  57. package/dist/math/vector2.d.ts.map +1 -0
  58. package/dist/math/vector2.js +111 -0
  59. package/dist/prefab-scenes/index.d.ts +8 -0
  60. package/dist/prefab-scenes/index.d.ts.map +1 -0
  61. package/dist/prefab-scenes/index.js +7 -0
  62. package/dist/prefab-scenes/mapGamepad.d.ts +28 -0
  63. package/dist/prefab-scenes/mapGamepad.d.ts.map +1 -0
  64. package/dist/prefab-scenes/mapGamepad.js +181 -0
  65. package/dist/prefab-scenes/startScreen.d.ts +59 -0
  66. package/dist/prefab-scenes/startScreen.d.ts.map +1 -0
  67. package/dist/{scenes/startup.js → prefab-scenes/startScreen.js} +48 -8
  68. package/dist/scene.d.ts +104 -6
  69. package/dist/scene.d.ts.map +1 -1
  70. package/dist/scene.js +28 -1
  71. package/dist/timer/index.d.ts +2 -0
  72. package/dist/timer/index.d.ts.map +1 -0
  73. package/dist/timer/timer.d.ts +32 -0
  74. package/dist/timer/timer.d.ts.map +1 -0
  75. package/dist/{core → timer}/timer.js +19 -14
  76. package/package.json +27 -2
  77. package/dist/core/audio.d.ts.map +0 -1
  78. package/dist/core/canvas-config.d.ts +0 -22
  79. package/dist/core/canvas-config.d.ts.map +0 -1
  80. package/dist/core/canvas-config.js +0 -14
  81. package/dist/core/canvas-manager.d.ts +0 -32
  82. package/dist/core/canvas-manager.d.ts.map +0 -1
  83. package/dist/core/canvas-manager.js +0 -179
  84. package/dist/core/events.d.ts +0 -31
  85. package/dist/core/events.d.ts.map +0 -1
  86. package/dist/core/gamepad-buttons.d.ts +0 -23
  87. package/dist/core/gamepad-buttons.d.ts.map +0 -1
  88. package/dist/core/gamepad-buttons.js +0 -36
  89. package/dist/core/gamepad-mapping.d.ts +0 -19
  90. package/dist/core/gamepad-mapping.d.ts.map +0 -1
  91. package/dist/core/gamepad-mapping.js +0 -223
  92. package/dist/core/gamepad.d.ts +0 -61
  93. package/dist/core/gamepad.d.ts.map +0 -1
  94. package/dist/core/gamepad.js +0 -237
  95. package/dist/core/graphics.d.ts +0 -93
  96. package/dist/core/graphics.d.ts.map +0 -1
  97. package/dist/core/graphics.js +0 -289
  98. package/dist/core/input-state.d.ts +0 -14
  99. package/dist/core/input-state.d.ts.map +0 -1
  100. package/dist/core/input-state.js +0 -50
  101. package/dist/core/input.d.ts +0 -33
  102. package/dist/core/input.d.ts.map +0 -1
  103. package/dist/core/input.js +0 -117
  104. package/dist/core/keyboard.d.ts +0 -16
  105. package/dist/core/keyboard.d.ts.map +0 -1
  106. package/dist/core/keyboard.js +0 -83
  107. package/dist/core/like.d.ts +0 -59
  108. package/dist/core/like.d.ts.map +0 -1
  109. package/dist/core/mouse.d.ts +0 -45
  110. package/dist/core/mouse.d.ts.map +0 -1
  111. package/dist/core/mouse.js +0 -182
  112. package/dist/core/rect.d.ts +0 -26
  113. package/dist/core/rect.d.ts.map +0 -1
  114. package/dist/core/timer.d.ts +0 -18
  115. package/dist/core/timer.d.ts.map +0 -1
  116. package/dist/core/vector2.d.ts +0 -26
  117. package/dist/core/vector2.d.ts.map +0 -1
  118. package/dist/core/vector2.js +0 -105
  119. package/dist/scenes/startup.d.ts +0 -18
  120. package/dist/scenes/startup.d.ts.map +0 -1
  121. /package/dist/{core/events.js → audio/index.js} +0 -0
  122. /package/dist/{core/like.js → timer/index.js} +0 -0
@@ -0,0 +1,388 @@
1
+ /**
2
+ * @module graphics
3
+ * @description a reduced-state, Love2D-like wrapper around browser canvas
4
+ *
5
+ * # Graphics Module
6
+ *
7
+ * A wrapper around browser Canvas.
8
+ * In standard usage `like.gfx` gives a {@link BoundGraphics} object with a canvas already on it.
9
+ * So, you can for example call `like.gfx.rectangle('fill', 'green', [10, 10, 30, 30])`
10
+ *
11
+ * ## State Isolation
12
+ * Each drawing operation resets relevant canvas state before executing:
13
+ * - Stroke properties (`lineWidth`, `lineCap`, `lineJoin`, `miterLimit`) are always set to defaults first
14
+ * - No state leakage between drawing calls
15
+ *
16
+ * ## Predicable Parameter Ordering
17
+ * - No clunky argument overrides that could affect positionality.
18
+ * - **Required arguments** come first as positional parameters
19
+ * - **Optional arguments** are grouped in a trailing `props` object
20
+ * - **Mode** `'fill' | 'line'` is the first arg if relevent.
21
+ * - **Color** then {@link Color}, if relevant -- there is no `setColor`.
22
+ *
23
+ * ## Note: Coordinate System is unchanged from native Canvas.
24
+ * - Origin (0, 0) at top-left
25
+ * - X increases right
26
+ * - Y increases down
27
+ * - Angles in radians, 0 is right, positive is clockwise
28
+ */
29
+ import { Vec2 } from "../math/vector2";
30
+ export class ImageHandle {
31
+ constructor(path) {
32
+ Object.defineProperty(this, "path", {
33
+ enumerable: true,
34
+ configurable: true,
35
+ writable: true,
36
+ value: void 0
37
+ });
38
+ Object.defineProperty(this, "element", {
39
+ enumerable: true,
40
+ configurable: true,
41
+ writable: true,
42
+ value: null
43
+ });
44
+ Object.defineProperty(this, "loadPromise", {
45
+ enumerable: true,
46
+ configurable: true,
47
+ writable: true,
48
+ value: void 0
49
+ });
50
+ Object.defineProperty(this, "isLoaded", {
51
+ enumerable: true,
52
+ configurable: true,
53
+ writable: true,
54
+ value: false
55
+ });
56
+ this.path = path;
57
+ this.loadPromise = new Promise((resolve, reject) => {
58
+ const img = new Image();
59
+ img.onload = () => {
60
+ this.element = img;
61
+ this.isLoaded = true;
62
+ resolve();
63
+ };
64
+ img.onerror = () => {
65
+ reject(new Error(`Failed to load image: ${path}`));
66
+ };
67
+ img.src = path;
68
+ });
69
+ }
70
+ isReady() {
71
+ return this.isLoaded;
72
+ }
73
+ ready() {
74
+ return this.loadPromise;
75
+ }
76
+ get size() {
77
+ return [this.element?.width ?? 0, this.element?.height ?? 0];
78
+ }
79
+ getElement() {
80
+ return this.element;
81
+ }
82
+ }
83
+ function parseColor(color) {
84
+ if (typeof color === "string")
85
+ return color;
86
+ const [r, g, b, a = 1] = color;
87
+ return `rgba(${r * 255}, ${g * 255}, ${b * 255}, ${a})`;
88
+ }
89
+ function applyColor(color) {
90
+ return parseColor(color ?? [1, 1, 1, 1]);
91
+ }
92
+ function setStrokeProps(ctx, props) {
93
+ ctx.lineWidth = props?.lineWidth ?? 1;
94
+ ctx.lineCap = props?.lineCap ?? "butt";
95
+ ctx.lineJoin = props?.lineJoin ?? "miter";
96
+ ctx.miterLimit = props?.miterLimit ?? 10;
97
+ }
98
+ function wrapText(ctx, text, maxWidth) {
99
+ const words = text.split(" ");
100
+ const [first, ...rest] = words;
101
+ const lines = [];
102
+ let current = first ?? "";
103
+ rest.forEach((word) => {
104
+ if (ctx.measureText(current + " " + word).width < maxWidth) {
105
+ current += " " + word;
106
+ }
107
+ else {
108
+ lines.push(current);
109
+ current = word;
110
+ }
111
+ });
112
+ lines.push(current);
113
+ return lines;
114
+ }
115
+ function getFontHeight(ctx) {
116
+ const match = ctx.font.match(/(\d+)px/);
117
+ return match ? parseInt(match[1]) : 16;
118
+ }
119
+ /**
120
+ * All of these methods exist on `like.gfx`, but with `ctx`
121
+ * bound to the first arg.
122
+ *
123
+ * Acts as the core of the graphics system, but can be used separately.
124
+ *
125
+ * ```ts
126
+ * import { draw } from "like/graphics"
127
+ * draw.clear(my2dContext, "red");
128
+ * ```
129
+ *
130
+ */
131
+ export const draw = {
132
+ /**
133
+ * Clears the canvas with a solid color.
134
+ * @param ctx Canvas context.
135
+ * @param color Fill color.
136
+ */
137
+ clear(ctx, color = [0, 0, 0, 1]) {
138
+ ctx.fillStyle = parseColor(color);
139
+ ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
140
+ },
141
+ /**
142
+ * Draws a rectangle.
143
+ * @param ctx Canvas context.
144
+ * @param mode Fill or line.
145
+ * @param color Fill or stroke color.
146
+ * @param rect Rectangle [x, y, w, h].
147
+ * @param props Optional stroke properties.
148
+ */
149
+ rectangle(ctx, mode, color, rect, props) {
150
+ const c = applyColor(color);
151
+ if (mode === "fill") {
152
+ ctx.fillStyle = c;
153
+ ctx.fillRect(...rect);
154
+ }
155
+ else {
156
+ setStrokeProps(ctx, props);
157
+ ctx.strokeStyle = c;
158
+ ctx.strokeRect(...rect);
159
+ }
160
+ },
161
+ /**
162
+ * Draws a circle or ellipse.
163
+ * @param ctx Canvas context.
164
+ * @param mode Fill or line.
165
+ * @param color Fill or stroke color.
166
+ * @param position Center position.
167
+ * @param radii Radius (number) or [rx, ry] for ellipse.
168
+ * @param props Optional arc, center, and stroke properties. Center is true by default.
169
+ */
170
+ circle(ctx, mode, color, position, radii, props) {
171
+ const center = (props && 'center' in props) ? props.center : true;
172
+ const c = applyColor(color);
173
+ const size = typeof radii === "number" ? [radii, radii] : radii;
174
+ const [startAngle, endAngle] = props?.arc ?? [0, Math.PI * 2];
175
+ if (!center) {
176
+ position = Vec2.add(position, size);
177
+ }
178
+ ctx.save();
179
+ ctx.translate(...position);
180
+ ctx.scale(...size);
181
+ ctx.beginPath();
182
+ ctx.arc(0, 0, 1, startAngle, endAngle);
183
+ if (mode == 'fill')
184
+ ctx.lineTo(0, 0);
185
+ ctx.closePath();
186
+ ctx.restore();
187
+ if (mode === "fill") {
188
+ ctx.fillStyle = c;
189
+ ctx.fill();
190
+ }
191
+ else {
192
+ setStrokeProps(ctx, props);
193
+ ctx.strokeStyle = c;
194
+ ctx.stroke();
195
+ }
196
+ },
197
+ /**
198
+ * Draws connected line segments.
199
+ * @param ctx Canvas context.
200
+ * @param color Stroke color.
201
+ * @param points Array of [x, y] positions.
202
+ * @param props Optional stroke properties.
203
+ */
204
+ line(ctx, color, points, props) {
205
+ if (points.length < 2)
206
+ return;
207
+ setStrokeProps(ctx, props);
208
+ ctx.beginPath();
209
+ const [[x0, y0], ...rest] = points;
210
+ ctx.moveTo(x0, y0);
211
+ rest.forEach(([x, y]) => ctx.lineTo(x, y));
212
+ ctx.strokeStyle = applyColor(color);
213
+ ctx.stroke();
214
+ },
215
+ /**
216
+ * Draws text at a position.
217
+ *
218
+ * Keep in mind: if you set `align` without `width` in your props,
219
+ * nothing will happen -- you'll get left-aligned text.
220
+ *
221
+ * Align works browser-style: if you align center, your text draws
222
+ * to the left and right of its position. If you align right, your position
223
+ * becomes the upper-right corner of the text.
224
+ *
225
+ * @param ctx Canvas context.
226
+ * @param color Fill color.
227
+ * @param text Text string.
228
+ * @param position Top-left position.
229
+ * @param props {@link PrintProps} Optional font, text limit, or alignment.
230
+ */
231
+ print(ctx, color, text, position, props) {
232
+ const [x, y] = position;
233
+ const { font = "16px sans-serif" } = props ?? {};
234
+ ctx.fillStyle = parseColor(color);
235
+ ctx.font = font;
236
+ ctx.textAlign = props?.align ?? "left";
237
+ if (props && 'width' in props) {
238
+ const { width } = props;
239
+ const lines = wrapText(ctx, text, width);
240
+ const lineHeight = getFontHeight(ctx);
241
+ ctx.textBaseline = "top";
242
+ lines.forEach((line, i) => {
243
+ ctx.fillText(line, x, y + i * lineHeight, width);
244
+ });
245
+ ctx.textBaseline = "alphabetic";
246
+ }
247
+ else {
248
+ ctx.fillText(text, x, y);
249
+ }
250
+ },
251
+ /**
252
+ * Draws an image.
253
+ *
254
+ * @remarks named "draw" because it draws anything _drawable_
255
+ * in the long run.
256
+ *
257
+ * @param ctx Canvas context.
258
+ * @param handle Image handle from newImage.
259
+ * @param position Draw position.
260
+ * @param props Optional rotation, scale, origin, or quad.
261
+ */
262
+ draw(ctx, handle, position, props) {
263
+ if (!handle.isReady())
264
+ return;
265
+ const element = handle.getElement();
266
+ if (!element)
267
+ return;
268
+ const [x, y] = position;
269
+ const { r = 0, scale = 1, origin = 0, quad } = props ?? {};
270
+ const [sx, sy] = typeof scale === "number" ? [scale, scale] : scale;
271
+ const [ox, oy] = typeof origin === "number" ? [origin, origin] : origin;
272
+ ctx.save();
273
+ ctx.translate(x, y);
274
+ ctx.rotate(r);
275
+ ctx.scale(sx, sy);
276
+ if (quad) {
277
+ const [qx, qy, qw, qh] = quad;
278
+ ctx.drawImage(element, qx, qy, qw, qh, -ox, -oy, qw, qh);
279
+ }
280
+ else {
281
+ ctx.drawImage(element, -ox, -oy);
282
+ }
283
+ ctx.restore();
284
+ },
285
+ /**
286
+ * Loads an image from a path.
287
+ * Unlike built-in loading, this pretends to be synchronous.
288
+ * @param ctx Canvas context.
289
+ * @param path Image file path.
290
+ * @returns ImageHandle for use with draw.
291
+ */
292
+ newImage(_ctx, path) {
293
+ return new ImageHandle(path);
294
+ },
295
+ /**
296
+ * Sets the clipping region.
297
+ * @param ctx Canvas context.
298
+ * @param rect Clipping rectangle, or full canvas if omitted.
299
+ */
300
+ clip(ctx, rect) {
301
+ ctx.beginPath();
302
+ if (rect) {
303
+ const [x, y, w, h] = rect;
304
+ ctx.rect(x, y, w, h);
305
+ }
306
+ else {
307
+ ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
308
+ }
309
+ ctx.clip();
310
+ },
311
+ /**
312
+ * Draws a polygon.
313
+ * @param ctx Canvas context.
314
+ * @param mode Fill or line.
315
+ * @param color Fill or stroke color.
316
+ * @param points Array of [x, y] vertices.
317
+ * @param props Optional stroke properties.
318
+ */
319
+ polygon(ctx, mode, color, points, props) {
320
+ if (points.length < 3)
321
+ return;
322
+ const c = applyColor(color);
323
+ ctx.beginPath();
324
+ const [[x0, y0], ...rest] = points;
325
+ ctx.moveTo(x0, y0);
326
+ rest.forEach(([x, y]) => ctx.lineTo(x, y));
327
+ ctx.closePath();
328
+ if (mode === "fill") {
329
+ ctx.fillStyle = c;
330
+ ctx.fill();
331
+ }
332
+ else {
333
+ setStrokeProps(ctx, props);
334
+ ctx.strokeStyle = c;
335
+ ctx.stroke();
336
+ }
337
+ },
338
+ /**
339
+ * Draws individual pixels.
340
+ * @param ctx Canvas context.
341
+ * @param color Fill color.
342
+ * @param pts Array of [x, y] positions.
343
+ */
344
+ points(ctx, color, pts) {
345
+ ctx.fillStyle = applyColor(color);
346
+ pts.forEach(([x, y]) => ctx.fillRect(x, y, 1, 1));
347
+ },
348
+ /**
349
+ * Saves canvas state.
350
+ * @param ctx Canvas context.
351
+ */
352
+ push(ctx) {
353
+ ctx.save();
354
+ },
355
+ /**
356
+ * Restores canvas state.
357
+ * @param ctx Canvas context.
358
+ */
359
+ pop(ctx) {
360
+ ctx.restore();
361
+ },
362
+ /**
363
+ * Applies a translation.
364
+ * @param ctx Canvas context.
365
+ * @param offset [x, y] offset.
366
+ */
367
+ translate(ctx, offset) {
368
+ const [x, y] = offset;
369
+ ctx.translate(x, y);
370
+ },
371
+ /**
372
+ * Applies a rotation.
373
+ * @param ctx Canvas context.
374
+ * @param angle Rotation in radians.
375
+ */
376
+ rotate(ctx, angle) {
377
+ ctx.rotate(angle);
378
+ },
379
+ /**
380
+ * Applies a scale.
381
+ * @param ctx Canvas context.
382
+ * @param factor Scale factor (number or [x, y]).
383
+ */
384
+ scale(ctx, factor) {
385
+ const [sx, sy] = typeof factor === "number" ? [factor, factor] : factor;
386
+ ctx.scale(sx, sy);
387
+ },
388
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @module graphics
3
+ * @description a reduced-state, Love2D-like wrapper around browser canvas
4
+ */
5
+ import { draw } from "./drawing";
6
+ export type { Color, DrawMode, ShapeProps, DrawProps, PrintProps, ImageHandle, } from "./drawing";
7
+ export { draw } from "./drawing";
8
+ export type { CanvasModeOptions, CanvasSize, Canvas, } from "./canvas";
9
+ type Bind<F> = F extends (ctx: CanvasRenderingContext2D, ...args: infer A) => infer R ? (...args: A) => R : never;
10
+ /**
11
+ * A graphics object with a canvas already attatched to it.
12
+ * Calling its methods will draw to the render canvas.
13
+ * See {@link graphics} for more info.
14
+ */
15
+ export type BoundGraphics = {
16
+ [K in keyof typeof draw]: Bind<(typeof draw)[K]>;
17
+ };
18
+ export declare function bindGraphics(ctx: CanvasRenderingContext2D): BoundGraphics;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/graphics/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,YAAY,EACV,KAAK,EACL,QAAQ,EACR,UAAU,EACV,SAAS,EACT,UAAU,EACV,WAAW,GACZ,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,YAAY,EACV,iBAAiB,EACjB,UAAU,EACV,MAAM,GACP,MAAM,UAAU,CAAC;AAElB,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CACvB,GAAG,EAAE,wBAAwB,EAC7B,GAAG,IAAI,EAAE,MAAM,CAAC,KACb,MAAM,CAAC,GACR,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,GACjB,KAAK,CAAC;AAEV;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG;KACzB,CAAC,IAAI,MAAM,OAAO,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;CACjD,CAAC;AAEF,wBAAgB,YAAY,CAAC,GAAG,EAAE,wBAAwB,GAAG,aAAa,CAMzE"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @module graphics
3
+ * @description a reduced-state, Love2D-like wrapper around browser canvas
4
+ */
5
+ import { draw } from "./drawing";
6
+ export { draw } from "./drawing";
7
+ export function bindGraphics(ctx) {
8
+ const bound = {};
9
+ for (const [name, fn] of Object.entries(draw)) {
10
+ bound[name] = (...args) => fn(ctx, ...args);
11
+ }
12
+ return bound;
13
+ }
package/dist/index.d.ts CHANGED
@@ -1,25 +1,19 @@
1
- import type { EventMap, EventType } from './core/events';
2
- import type { Like } from './core/like';
3
- export type { Like } from './core/like';
4
- export type { Vector2 } from './core/vector2';
5
- export { Vec2 } from './core/vector2';
6
- export { Rect } from './core/rect';
7
- export type { Like2DEvent, EventType, EventMap } from './core/events';
8
- export type { CanvasMode, PartialCanvasMode } from './core/canvas-config';
9
- export type { Color, Quad, ShapeProps, DrawProps, PrintProps } from './core/graphics';
10
- export { ImageHandle } from './core/graphics';
11
- export type { Source, SourceOptions } from './core/audio';
12
- export type { Scene } from './scene';
13
- export { StartupScene } from './scenes/startup';
14
- export { getGPName, GP } from './core/gamepad';
15
- export type { StickPosition } from './core/gamepad';
16
- type Callback<K extends EventType> = (...args: EventMap[K]) => void;
17
- type Callbacks = {
18
- [K in EventType]?: Callback<K>;
19
- };
20
- export type LikeWithCallbacks = Like & Callbacks & {
21
- start(): Promise<void>;
22
- dispose(): void;
23
- };
24
- export declare function createLike(container: HTMLElement): LikeWithCallbacks;
1
+ /**
2
+ * @module like2d
3
+ * @description A cozy web-native 2D game framework.
4
+ */
5
+ import type { Like } from './like';
6
+ export type { Like, TopLevelEventHandler } from './like';
7
+ export type { LikeEvent, EventType, EventMap } from './events';
8
+ /**
9
+ * Create a new Like2D game instance attached to a DOM container.
10
+ *
11
+ * This is the entry point for all Like2D games. It creates a canvas element,
12
+ * initializes all subsystems (graphics, audio, input), and returns an object
13
+ * where you can assign game callbacks.
14
+ *
15
+ * @param container - The HTML element to attach the game canvas to.
16
+ * @returns A {@link Like} instance ready for callback assignment
17
+ */
18
+ export declare function createLike(container: HTMLElement): Like;
25
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,YAAY,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACtF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC1D,YAAY,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,KAAK,QAAQ,CAAC,CAAC,SAAS,SAAS,IAAI,CAAC,GAAG,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AAEpE,KAAK,SAAS,GAAG;KACd,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,SAAS,GAAG;IACjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,IAAI,IAAI,CAAC;CACjB,CAAC;AAEF,wBAAgB,UAAU,CAAC,SAAS,EAAE,WAAW,GAAG,iBAAiB,CAapE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnC,YAAY,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AACzD,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAE/D;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI,CAGvD"}
package/dist/index.js CHANGED
@@ -1,19 +1,19 @@
1
+ /**
2
+ * @module like2d
3
+ * @description A cozy web-native 2D game framework.
4
+ */
1
5
  import { Engine } from './engine';
2
- export { Vec2 } from './core/vector2';
3
- export { Rect } from './core/rect';
4
- export { ImageHandle } from './core/graphics';
5
- export { StartupScene } from './scenes/startup';
6
- export { getGPName, GP } from './core/gamepad';
6
+ /**
7
+ * Create a new Like2D game instance attached to a DOM container.
8
+ *
9
+ * This is the entry point for all Like2D games. It creates a canvas element,
10
+ * initializes all subsystems (graphics, audio, input), and returns an object
11
+ * where you can assign game callbacks.
12
+ *
13
+ * @param container - The HTML element to attach the game canvas to.
14
+ * @returns A {@link Like} instance ready for callback assignment
15
+ */
7
16
  export function createLike(container) {
8
17
  const engine = new Engine(container);
9
- const callbacks = {};
10
- const handleEvent = (event) => {
11
- const cb = callbacks[event.type];
12
- if (cb)
13
- cb(...event.args);
14
- };
15
- return Object.assign(engine.like, callbacks, {
16
- start: () => engine.start(handleEvent),
17
- dispose: () => engine.dispose(),
18
- });
18
+ return engine.like;
19
19
  }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * @module GamepadMapping
3
+ *
4
+ * A database, generated on module load,
5
+ * which uses SDL's database to coerce
6
+ * browser APIs into physical gamepad button
7
+ * mappings.
8
+ *
9
+ * Browser API shortcomings:
10
+ * - No standard way of exposing vendor and product
11
+ * - Almost nothing is standard
12
+ * - Vendor and product alone doesn't suffice for GUID -- Different controllers have the same.
13
+ * - D-pads either get mapped to an axis (last pair of axes in Chromium) or buttons (Firefox).
14
+ * - Analog axes get mapped differently in Firefox and Chromium.
15
+ *
16
+ * How we overcome them:
17
+ * - We parse out vendor and product based on currently known formats.
18
+ * - We go with best-match and always fall back on manual mapping.
19
+ */
20
+ import type { Vector2 } from "../math";
21
+ /**
22
+ * ref: https://www.w3.org/TR/gamepad/#dfn-standard-gamepad
23
+ * note: `num` is only the corresponding number on standard mapping above.
24
+ *
25
+ * The point of the mapping system is to apply that _or_ non-standard mappings,
26
+ * Which are exceedingly common.
27
+ */
28
+ declare const buttonMap: readonly [{
29
+ readonly sdl: "a";
30
+ readonly like: "BBottom";
31
+ readonly num: number;
32
+ readonly name: "Bottom Face Button";
33
+ }, {
34
+ readonly sdl: "b";
35
+ readonly like: "BRight";
36
+ readonly num: 1;
37
+ readonly name: "Right Face Button";
38
+ }, {
39
+ readonly sdl: "x";
40
+ readonly like: "BLeft";
41
+ readonly num: 2;
42
+ readonly name: "Left Face Button";
43
+ }, {
44
+ readonly sdl: "y";
45
+ readonly like: "BTop";
46
+ readonly num: 3;
47
+ readonly name: "Top Face Button";
48
+ }, {
49
+ readonly sdl: "leftshoulder";
50
+ readonly like: "L1";
51
+ readonly num: 4;
52
+ readonly name: "Left shoulder (front)";
53
+ }, {
54
+ readonly sdl: "rightshoulder";
55
+ readonly like: "R1";
56
+ readonly num: 5;
57
+ readonly name: "Right shoulder (front)";
58
+ }, {
59
+ readonly sdl: "lefttrigger";
60
+ readonly like: "L2";
61
+ readonly num: 6;
62
+ readonly name: "Left shoulder (rear)";
63
+ }, {
64
+ readonly sdl: "righttrigger";
65
+ readonly like: "R2";
66
+ readonly num: 7;
67
+ readonly name: "Right shoulder (rear)";
68
+ }, {
69
+ readonly sdl: "back";
70
+ readonly like: "MenuLeft";
71
+ readonly num: 8;
72
+ readonly name: "Left Menu Button";
73
+ }, {
74
+ readonly sdl: "start";
75
+ readonly like: "MenuRight";
76
+ readonly num: 9;
77
+ readonly name: "Right Menu Button";
78
+ }, {
79
+ readonly sdl: "leftstick";
80
+ readonly like: "LeftStick";
81
+ readonly num: 10;
82
+ readonly name: "Left Stick Button";
83
+ }, {
84
+ readonly sdl: "rightstick";
85
+ readonly like: "RightStick";
86
+ readonly num: 11;
87
+ readonly name: "Right Stick Button";
88
+ }, {
89
+ readonly sdl: "dpup";
90
+ readonly like: "Up";
91
+ readonly num: 12;
92
+ readonly name: "D-Pad Up";
93
+ }, {
94
+ readonly sdl: "dpdown";
95
+ readonly like: "Down";
96
+ readonly num: 13;
97
+ readonly name: "D-Pad Down";
98
+ }, {
99
+ readonly sdl: "dpleft";
100
+ readonly like: "Left";
101
+ readonly num: 14;
102
+ readonly name: "D-Pad Left";
103
+ }, {
104
+ readonly sdl: "dpright";
105
+ readonly like: "Right";
106
+ readonly num: 15;
107
+ readonly name: "D-Pad right";
108
+ }];
109
+ export type LikeButton = (typeof buttonMap)[number]["like"] | `Button${number}` | `Axis${number}+` | `Axis${number}-`;
110
+ export type GamepadMapping = {
111
+ buttons: ButtonMapping;
112
+ sticks: StickMapping[];
113
+ };
114
+ export type ButtonMapping = Record<number, LikeButton>;
115
+ export type StickMapping = [StickAxisMapping, StickAxisMapping];
116
+ export type StickAxisMapping = {
117
+ index: number;
118
+ invert: boolean;
119
+ };
120
+ export declare const defaultMapping: (stickCount: number) => GamepadMapping;
121
+ export declare const standardButtonMapping: () => ButtonMapping;
122
+ export declare const allButtons: Set<string>;
123
+ export declare const fullButtonName: Map<"BBottom" | "BRight" | "BLeft" | "BTop" | "L1" | "R1" | "L2" | "R2" | "MenuLeft" | "MenuRight" | "LeftStick" | "RightStick" | "Up" | "Down" | "Left" | "Right", "Bottom Face Button" | "Right Face Button" | "Left Face Button" | "Top Face Button" | "Left shoulder (front)" | "Right shoulder (front)" | "Left shoulder (rear)" | "Right shoulder (rear)" | "Left Menu Button" | "Right Menu Button" | "Left Stick Button" | "Right Stick Button" | "D-Pad Up" | "D-Pad Down" | "D-Pad Left" | "D-Pad right">;
124
+ export declare const mapStick: (gp: Gamepad, mapping: StickMapping) => Vector2;
125
+ type SdlMapping = {
126
+ vendor: number;
127
+ product: number;
128
+ name: string;
129
+ sdlName: string;
130
+ mapping: Record<number, LikeButton>;
131
+ };
132
+ export declare function getSdlMapping(gamepad: Gamepad): SdlMapping | undefined;
133
+ export {};
134
+ //# sourceMappingURL=gamepad-mapping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gamepad-mapping.d.ts","sourceRoot":"","sources":["../../src/input/gamepad-mapping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC;;;;;;GAMG;AACH,QAAA,MAAM,SAAS;;;kBAC0B,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyBrC,CAAC;AAEX,MAAM,MAAM,UAAU,GAClB,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAClC,SAAS,MAAM,EAAE,GACjB,OAAO,MAAM,GAAG,GAChB,OAAO,MAAM,GAAG,CAAC;AAIrB,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,YAAY,EAAE,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACvD,MAAM,MAAM,YAAY,GAAG,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;AAChE,MAAM,MAAM,gBAAgB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;AAElE,eAAO,MAAM,cAAc,GAAI,YAAY,MAAM,KAAG,cAQlD,CAAC;AAEH,eAAO,MAAM,qBAAqB,QAAO,aAC0B,CAAC;AACpE,eAAO,MAAM,UAAU,aAAqD,CAAC;AAC7E,eAAO,MAAM,cAAc,qfAE1B,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,IAAI,OAAO,EAAE,SAAS,YAAY,KAAG,OAK7D,CAAC;AAsEF,KAAK,UAAU,GAAG;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACrC,CAAC;AAEF,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CA0BtE"}