like2d 2.8.0 → 2.9.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 (77) hide show
  1. package/README.md +34 -35
  2. package/dist/core/audio.d.ts +12 -9
  3. package/dist/core/audio.d.ts.map +1 -1
  4. package/dist/core/audio.js +7 -4
  5. package/dist/core/canvas.d.ts +58 -0
  6. package/dist/core/canvas.d.ts.map +1 -0
  7. package/dist/core/canvas.js +209 -0
  8. package/dist/core/events.d.ts +91 -13
  9. package/dist/core/events.d.ts.map +1 -1
  10. package/dist/core/events.js +20 -0
  11. package/dist/core/gamepad-mapping.d.ts +57 -18
  12. package/dist/core/gamepad-mapping.d.ts.map +1 -1
  13. package/dist/core/gamepad-mapping.js +23 -223
  14. package/dist/core/gamepad.d.ts +34 -58
  15. package/dist/core/gamepad.d.ts.map +1 -1
  16. package/dist/core/gamepad.js +79 -213
  17. package/dist/core/graphics.d.ts +175 -65
  18. package/dist/core/graphics.d.ts.map +1 -1
  19. package/dist/core/graphics.js +294 -202
  20. package/dist/core/input-state.d.ts +2 -2
  21. package/dist/core/input-state.d.ts.map +1 -1
  22. package/dist/core/input.d.ts +22 -15
  23. package/dist/core/input.d.ts.map +1 -1
  24. package/dist/core/input.js +25 -37
  25. package/dist/core/keyboard.d.ts +6 -7
  26. package/dist/core/keyboard.d.ts.map +1 -1
  27. package/dist/core/keyboard.js +15 -35
  28. package/dist/core/like.d.ts +98 -44
  29. package/dist/core/like.d.ts.map +1 -1
  30. package/dist/core/like.js +8 -0
  31. package/dist/core/mouse.d.ts +31 -24
  32. package/dist/core/mouse.d.ts.map +1 -1
  33. package/dist/core/mouse.js +59 -99
  34. package/dist/core/timer.d.ts +2 -5
  35. package/dist/core/timer.d.ts.map +1 -1
  36. package/dist/core/timer.js +2 -14
  37. package/dist/engine.d.ts +61 -16
  38. package/dist/engine.d.ts.map +1 -1
  39. package/dist/engine.js +121 -160
  40. package/dist/index.d.ts +42 -21
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +35 -14
  43. package/dist/math/index.d.ts +2 -0
  44. package/dist/math/index.d.ts.map +1 -0
  45. package/dist/math/index.js +1 -0
  46. package/dist/math/rect.d.ts +71 -0
  47. package/dist/math/rect.d.ts.map +1 -0
  48. package/dist/{core → math}/rect.js +8 -0
  49. package/dist/math/vector2.d.ts +78 -0
  50. package/dist/math/vector2.d.ts.map +1 -0
  51. package/dist/{core → math}/vector2.js +24 -0
  52. package/dist/prefab-scenes/index.d.ts +7 -0
  53. package/dist/prefab-scenes/index.d.ts.map +1 -0
  54. package/dist/prefab-scenes/index.js +6 -0
  55. package/dist/prefab-scenes/startScreen.d.ts +59 -0
  56. package/dist/prefab-scenes/startScreen.d.ts.map +1 -0
  57. package/dist/{scenes/startup.js → prefab-scenes/startScreen.js} +48 -8
  58. package/dist/scene.d.ts +103 -5
  59. package/dist/scene.d.ts.map +1 -1
  60. package/dist/scene.js +28 -1
  61. package/package.json +18 -2
  62. package/dist/core/canvas-config.d.ts +0 -22
  63. package/dist/core/canvas-config.d.ts.map +0 -1
  64. package/dist/core/canvas-config.js +0 -14
  65. package/dist/core/canvas-manager.d.ts +0 -32
  66. package/dist/core/canvas-manager.d.ts.map +0 -1
  67. package/dist/core/canvas-manager.js +0 -179
  68. package/dist/core/gamepad-buttons.d.ts +0 -23
  69. package/dist/core/gamepad-buttons.d.ts.map +0 -1
  70. package/dist/core/gamepad-buttons.js +0 -36
  71. package/dist/core/rect.d.ts +0 -26
  72. package/dist/core/rect.d.ts.map +0 -1
  73. package/dist/core/vector2.d.ts +0 -26
  74. package/dist/core/vector2.d.ts.map +0 -1
  75. package/dist/gamecontrollerdb.txt +0 -2221
  76. package/dist/scenes/startup.d.ts +0 -18
  77. package/dist/scenes/startup.d.ts.map +0 -1
@@ -0,0 +1,78 @@
1
+ /** A pair of numbers `[x, y]`
2
+ * representing for example:
3
+ * - position in 2D space
4
+ * - width and height
5
+ * - velocity
6
+ *
7
+ * See {@link Vec2} for full library.
8
+ *
9
+ * ## Examples
10
+ *
11
+ * #### Constructing a Vector2
12
+ * ```ts
13
+ * const onionSize: Vector2 = [width, height];
14
+ * ```
15
+ *
16
+ * #### Deconstructing a Vector2
17
+ * ```ts
18
+ * const [width, height] = onionSize;
19
+ * ```
20
+ *
21
+ * #### Making math less repetitive.
22
+ * ```ts
23
+ * x += dx * speed;
24
+ * y += dy * speed;
25
+ * // becomes...
26
+ * pos = Vec2.add(pos, Vec2.mul(delta, speed))
27
+ * ```
28
+ *
29
+ * #### Summing an array of Vector2
30
+ * ```ts
31
+ * const nums: Vector2[] = [[50, 100], [-5, -5], [0, 99]];
32
+ * const sum = nums.reduce(Vec2.add);
33
+ * ```
34
+ *
35
+ * #### Using LIKE graphics API
36
+ * ```ts
37
+ * // Draw a circle in the center of the canvas.
38
+ * const pos = Vec2.div(
39
+ * like.canvas.getSize(),
40
+ * 2,
41
+ * )
42
+ * like.graphics.circle('fill', 'blue', pos, 20);
43
+ * ```
44
+ * */
45
+ export type Vector2 = [number, number];
46
+ /** Library of Vec2 functions. See {@link Vector2} for overview. */
47
+ export declare namespace Vec2 {
48
+ function add(a: Vector2, b: Vector2): Vector2;
49
+ function sub(a: Vector2, b: Vector2): Vector2;
50
+ function mul(v: Vector2, other: Vector2 | number): Vector2;
51
+ function div(v: Vector2, other: Vector2 | number): Vector2;
52
+ function mod(v: Vector2, other: Vector2 | number): Vector2;
53
+ function eq(v: Vector2, other: Vector2): boolean;
54
+ function dot(a: Vector2, b: Vector2): number;
55
+ function cross(a: Vector2, b: Vector2): number;
56
+ function lengthSq(v: Vector2): number;
57
+ function length(v: Vector2): number;
58
+ function normalize(v: Vector2): Vector2;
59
+ function distance(a: Vector2, b: Vector2): number;
60
+ function lerp(a: Vector2, b: Vector2, t: number): Vector2;
61
+ function toPolar(v: Vector2): {
62
+ r: number;
63
+ angle: number;
64
+ };
65
+ function fromPolar(r: number, angle: number): Vector2;
66
+ function angle(v: Vector2): number;
67
+ function rotate(v: Vector2, angle: number): Vector2;
68
+ function negate(v: Vector2): Vector2;
69
+ function floor(v: Vector2): Vector2;
70
+ function ceil(v: Vector2): Vector2;
71
+ function round(v: Vector2): Vector2;
72
+ function min(a: Vector2, b: Vector2): Vector2;
73
+ function max(a: Vector2, b: Vector2): Vector2;
74
+ function clamp(v: Vector2, min: Vector2, max: Vector2): Vector2;
75
+ function fromAngle(angle: number, len?: number): Vector2;
76
+ function zero(): Vector2;
77
+ }
78
+ //# sourceMappingURL=vector2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector2.d.ts","sourceRoot":"","sources":["../../src/math/vector2.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2CK;AACL,MAAM,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEvC,mEAAmE;AACnE,yBAAiB,IAAI,CAAC;IACpB,SAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAEnD;IAED,SAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAEnD;IAED,SAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAKhE;IAED,SAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAKhE;IAED,SAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAKhE;IAED,SAAgB,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAEtD;IAED,SAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,MAAM,CAElD;IAED,SAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,MAAM,CAEpD;IAED,SAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAE3C;IAED,SAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAEzC;IAED,SAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAI7C;IAED,SAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,MAAM,CAEvD;IAED,SAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAE/D;IAED,SAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAKhE;IAED,SAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAE3D;IAED,SAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAExC;IAED,SAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAIzD;IAED,SAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAE1C;IAED,SAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAEzC;IAED,SAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAExC;IAED,SAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAEzC;IAED,SAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAEnD;IAED,SAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAEnD;IAED,SAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAKrE;IAED,SAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAE,MAAU,GAAG,OAAO,CAEjE;IAED,SAAgB,IAAI,IAAI,OAAO,CAE9B;CACF"}
@@ -1,3 +1,5 @@
1
+ import { mod as mmod } from ".";
2
+ /** Library of Vec2 functions. See {@link Vector2} for overview. */
1
3
  export var Vec2;
2
4
  (function (Vec2) {
3
5
  function add(a, b) {
@@ -22,6 +24,17 @@ export var Vec2;
22
24
  return [v[0] / other[0], v[1] / other[1]];
23
25
  }
24
26
  Vec2.div = div;
27
+ function mod(v, other) {
28
+ if (typeof other === 'number') {
29
+ return [mmod(v[0], other), mmod(v[1], other)];
30
+ }
31
+ return [mmod(v[0], other[0]), mmod(v[1], other[1])];
32
+ }
33
+ Vec2.mod = mod;
34
+ function eq(v, other) {
35
+ return v[0] == other[0] && v[1] == other[1];
36
+ }
37
+ Vec2.eq = eq;
25
38
  function dot(a, b) {
26
39
  return a[0] * b[0] + a[1] * b[1];
27
40
  }
@@ -53,6 +66,17 @@ export var Vec2;
53
66
  return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
54
67
  }
55
68
  Vec2.lerp = lerp;
69
+ function toPolar(v) {
70
+ return {
71
+ r: Vec2.length(v),
72
+ angle: Vec2.angle(v),
73
+ };
74
+ }
75
+ Vec2.toPolar = toPolar;
76
+ function fromPolar(r, angle) {
77
+ return [r * Math.cos(angle), r * Math.sin(angle)];
78
+ }
79
+ Vec2.fromPolar = fromPolar;
56
80
  function angle(v) {
57
81
  return Math.atan2(v[1], v[0]);
58
82
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @module prefab-scenes
3
+ *
4
+ * A set of built-in scenes to aid with game development.
5
+ */
6
+ export { StartScreen } from "./startScreen";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prefab-scenes/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @module prefab-scenes
3
+ *
4
+ * A set of built-in scenes to aid with game development.
5
+ */
6
+ export { StartScreen } from "./startScreen";
@@ -0,0 +1,59 @@
1
+ import { type Scene } from '../scene';
2
+ import { Like } from '..';
3
+ /**
4
+ * ## Why
5
+ *
6
+ * 1. Because the LIKE logo looks awesome.
7
+ * 2. Autoplay restriction, doesn't let you play audio until the page is clicked.
8
+ * 3. You have to click on the game in order to send inputs, anyway.
9
+ * 4. It's polite.
10
+ *
11
+ * ## Usage
12
+ *
13
+ * ```typescript
14
+ * import { createLike, StartScreen } from 'like';
15
+ * import { GameScene } from './game';
16
+ *
17
+ * const container = document.getElementById("myGame");
18
+ * const like = createLike(container);
19
+ *
20
+ * // these callbacks will be ignored until the scene is clicked
21
+ * like.update = function () { ... }
22
+ * like.draw = function () { ... }
23
+ *
24
+ * // Set up the start screen
25
+ * like.setScene(new StartScreen())
26
+ * like.start();
27
+ * ```
28
+ *
29
+ * Alternatively, copy-paste this code into your own project and modify it freely.
30
+ * Update imports:
31
+ *
32
+ * ```ts
33
+ * import { type Scene } from 'like/scene';
34
+ * import type { ImageHandle } from 'like/core/graphics';
35
+ * import { Vec2 } from 'like/math/vector2';
36
+ * import { Like } from 'like';
37
+ * ```
38
+ *
39
+ * ## Custom Rendering
40
+ *
41
+ * Pass a custom draw function to replace the default logo:
42
+ *
43
+ * ```typescript
44
+ * const startup = new StartupScene(gameScene, (like) => {
45
+ * like.gfx.clear([0, 0, 0, 1]);
46
+ * like.gfx.print([1, 1, 1], 'Click to Start', [100, 100]);
47
+ * });
48
+ * ```
49
+ */
50
+ export declare class StartScreen implements Scene {
51
+ private next;
52
+ private onDraw?;
53
+ private logo;
54
+ constructor(next: Scene, onDraw?: ((like: Like) => void) | undefined);
55
+ load(like: Like): void;
56
+ draw(like: Like): void;
57
+ mousepressed(like: Like): void;
58
+ }
59
+ //# sourceMappingURL=startScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startScreen.d.ts","sourceRoot":"","sources":["../../src/prefab-scenes/startScreen.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,UAAU,CAAC;AAGtC,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAI1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBAAa,WAAY,YAAW,KAAK;IAIrC,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM,CAAC;IAJjB,OAAO,CAAC,IAAI,CAAe;gBAGjB,IAAI,EAAE,KAAK,EACX,MAAM,CAAC,GAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,aAAA;IAGvC,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAItB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAWtB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;CAG/B"}
@@ -1,13 +1,53 @@
1
- import { Vec2 } from '../core/vector2';
1
+ import { Vec2 } from '../math/vector2';
2
2
  const LOGO = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBDcmVhdGVkIHdpdGggSW5rc2NhcGUgKGh0dHA6Ly93d3cuaW5rc2NhcGUub3JnLykgLS0+Cjxzdmcgd2lkdGg9IjMwMG1tIiBoZWlnaHQ9IjEwNW1tIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMDAgMTA1IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogPHJlY3QgeD0iMTAiIHk9IjExLjIzIiB3aWR0aD0iMjgwIiBoZWlnaHQ9IjgzLjU0NCIgZmlsbD0iI2U0ODA4MCIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiLz4KIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+CiAgPHJlY3QgeD0iOTcuNDg0IiB5PSIxMS4yMyIgd2lkdGg9IjUyLjUxNiIgaGVpZ2h0PSI0Ni4yMzciLz4KICA8cmVjdCB4PSIxNTAiIHk9IjExLjIzIiB3aWR0aD0iMzUuMDExIiBoZWlnaHQ9IjQ2LjIzNyIvPgogIDxyZWN0IHg9IjE4NS4wMSIgeT0iMTEuMjMiIHdpZHRoPSI1Mi41MTYiIGhlaWdodD0iNDYuMjM3Ii8+CiAgPHJlY3QgeD0iMjM3LjUzIiB5PSIxMS4yMyIgd2lkdGg9IjUyLjUxNiIgaGVpZ2h0PSI0Ni4yMzciLz4KIDwvZz4KIDxnPgogIDxyZWN0IHg9IjEzMi40OSIgeT0iMTEuMjMiIHdpZHRoPSIxNy41MDUiIGhlaWdodD0iMjcuNDYxIi8+CiAgPHJlY3QgeD0iMTUwIiB5PSIyOS4zMDIiIHdpZHRoPSI4Ljc1MjciIGhlaWdodD0iMTguNzc2Ii8+CiAgPHJlY3QgeD0iMTc2LjI2IiB5PSIyOS4zMDIiIHdpZHRoPSI4Ljc1MjciIGhlaWdodD0iMTguNzc2Ii8+CiA8L2c+CiA8cmVjdCB4PSIxNTAiIHk9IjExLjIzIiB3aWR0aD0iMTcuNTA1IiBoZWlnaHQ9IjguNjg0NSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CiA8cmVjdCB4PSIxNjcuNTEiIHk9IjExLjIzIiB3aWR0aD0iMTcuNTA1IiBoZWlnaHQ9IjguNjg0NSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CiA8Zz4KICA8cGF0aCBkPSJtMjM3LjUzIDM4LjY5MS0xNy41MDUtOS4zODgyIDE3LjUwNS0xOC4wNzN6Ii8+CiAgPHJlY3QgeD0iMjAyLjg4IiB5PSI0OC4wNzkiIHdpZHRoPSIxNi43NzIiIGhlaWdodD0iOS4zODgyIi8+CiAgPHJlY3QgeD0iMjcyLjU0IiB5PSIyMC4yNjYiIHdpZHRoPSIxNi43NzIiIGhlaWdodD0iOS4zODgyIi8+CiAgPHJlY3QgeD0iMjcyLjU0IiB5PSIzOC42OTEiIHdpZHRoPSIxNi43NzIiIGhlaWdodD0iOS4zODgyIi8+CiAgPHBhdGggZD0ibTIwMi41MiAyOS4zMDIgMC4zNjY4NS0xOC4wNzNoMTcuMTM5eiIvPgogPC9nPgogPHBhdGggZD0ibTY0LjA3OCAxLjAwNDItMzMuMzc1IDMzLjM3NS0wLjAxNzQzIDAuMDE3NGEyMy42MTIgMjMuNjEyIDAgMCAwIDAgMzMuMzkyIDIzLjYxMiAyMy42MTIgMCAwIDAgMzAuMDEyIDIuODAyMiAyMy42MTIgMjMuNjEyIDAgMCAxIDdlLTMgMC41NzAzNCAyMy42MTIgMjMuNjEyIDAgMCAxLTIzLjYxMiAyMy42MTJoNTMuOTdhMjMuNjEyIDIzLjYxMiAwIDAgMS0yMy42MTEtMjMuNjEyIDIzLjYxMiAyMy42MTIgMCAwIDEgN2UtMyAtMC41NzAzNCAyMy42MTIgMjMuNjEyIDAgMCAwIDMwLjAxMi0yLjgwMjkgMjMuNjEyIDIzLjYxMiAwIDAgMC02Ljg4ZS00IC0zMy4zOTJ6IiBmaWxsPSIjODBjM2U0IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIuNSI+CiAgPGNpcmNsZSB0cmFuc2Zvcm09InJvdGF0ZSgxMzUpIiBjeD0iLTIwLjk4OCIgY3k9Ii05My4yNDMiIHI9IjIzLjYxMiIvPgogIDxjaXJjbGUgdHJhbnNmb3JtPSJyb3RhdGUoMTM1KSIgY3g9IjIuNjIzOCIgY3k9Ii02OS42MzIiIHI9IjIzLjYxMiIvPgogIDxjaXJjbGUgY3g9IjkxLjA2MiIgY3k9IjcxLjE2MSIgcj0iMjMuNjEyIi8+CiAgPGNpcmNsZSBjeD0iMzcuMDkzIiBjeT0iNzEuMTYxIiByPSIyMy42MTIiLz4KIDwvZz4KPC9zdmc+Cg==';
3
3
  /**
4
- * A simple startup scene that waits for a mouse click before advancing.
4
+ * ## Why
5
5
  *
6
- * This exists to work around browser autoplay restrictions - browsers require
7
- * user interaction (like a click) before allowing audio playback. Show this
8
- * scene first, then transition to your game scene on click.
6
+ * 1. Because the LIKE logo looks awesome.
7
+ * 2. Autoplay restriction, doesn't let you play audio until the page is clicked.
8
+ * 3. You have to click on the game in order to send inputs, anyway.
9
+ * 4. It's polite.
10
+ *
11
+ * ## Usage
12
+ *
13
+ * ```typescript
14
+ * import { createLike, StartScreen } from 'like';
15
+ * import { GameScene } from './game';
16
+ *
17
+ * const container = document.getElementById("myGame");
18
+ * const like = createLike(container);
19
+ *
20
+ * // these callbacks will be ignored until the scene is clicked
21
+ * like.update = function () { ... }
22
+ * like.draw = function () { ... }
23
+ *
24
+ * // Set up the start screen
25
+ * like.setScene(new StartScreen())
26
+ * like.start();
27
+ * ```
28
+ *
29
+ * Alternatively, copy-paste this code into your own project and modify it freely.
30
+ * Update imports:
31
+ *
32
+ * ```ts
33
+ * import { type Scene } from 'like/scene';
34
+ * import type { ImageHandle } from 'like/core/graphics';
35
+ * import { Vec2 } from 'like/math/vector2';
36
+ * import { Like } from 'like';
37
+ * ```
38
+ *
39
+ * ## Custom Rendering
40
+ *
41
+ * Pass a custom draw function to replace the default logo:
42
+ *
43
+ * ```typescript
44
+ * const startup = new StartupScene(gameScene, (like) => {
45
+ * like.gfx.clear([0, 0, 0, 1]);
46
+ * like.gfx.print([1, 1, 1], 'Click to Start', [100, 100]);
47
+ * });
48
+ * ```
9
49
  */
10
- export class StartupScene {
50
+ export class StartScreen {
11
51
  constructor(next, onDraw) {
12
52
  Object.defineProperty(this, "next", {
13
53
  enumerable: true,
@@ -37,12 +77,12 @@ export class StartupScene {
37
77
  }
38
78
  else if (this.logo.isReady()) {
39
79
  like.gfx.clear([0.05, 0.05, 0.08, 1]);
40
- const winSize = like.gfx.getCanvasSize();
80
+ const winSize = like.canvas.getSize();
41
81
  const scale = (winSize[0] * 0.5) / this.logo.size[0];
42
82
  like.gfx.draw(this.logo, Vec2.div(winSize, 2), { scale, origin: Vec2.div(this.logo.size, 2) });
43
83
  }
44
84
  }
45
- mousepressed(like, _pos, _button) {
85
+ mousepressed(like) {
46
86
  like.setScene(this.next);
47
87
  }
48
88
  }
package/dist/scene.d.ts CHANGED
@@ -1,10 +1,108 @@
1
- import type { Like2DEvent, EventMap, EventType } from './core/events';
1
+ /**
2
+ * @module scene
3
+ * @description A helpful callback / state management layer, plus utility scenes.
4
+ *
5
+ */
6
+ import type { LikeEvent, EventMap } from './core/events';
2
7
  import type { Like } from './core/like';
3
- type EventHandler<K extends EventType> = (like: Like, ...args: EventMap[K]) => void;
8
+ /**
9
+ * An interface for creating scenes.
10
+ *
11
+ * ## Why Scenes?
12
+ *
13
+ * For any game with more than one scene, we have to either:
14
+ * - switch-case on game state in every single callback
15
+ * - rebind all of the callbacks ourselves
16
+ * - wrap handleEvent (hint: that's what this does)
17
+ *
18
+ * Also, some no need to pass around a `like` object.
19
+ * Here, `like` instead piggybacks on a closure that follows around
20
+ * your running scene and shows up as an additional first argument
21
+ * to every callback.
22
+ *
23
+ * ## Quick Start
24
+ *
25
+ * Have a scene handle all the callbacks, disabling global
26
+ * callbacks.
27
+ * ```typescript
28
+ * // set up a scene
29
+ * class MagicalGrowingRectangle extends Scene {
30
+ * rectangleSize = 10;
31
+ * constructor() {}
32
+ *
33
+ * keypressed(_like: Like) {
34
+ * this.rectangleSize += 10;
35
+ * }
36
+ *
37
+ * draw(like: Like) {
38
+ * like.gfx.rectangle('fill', 'green',
39
+ * [10, 10, this.rectangleSize, this.rectangleSize])
40
+ * }
41
+ * }
42
+ *
43
+ * like.setScene(new MagicalGrowingRectangle());
44
+ * ```
45
+ *
46
+ * To get back to global callbacks, just use `like.handleEvent = undefined`
47
+ *
48
+ * ## Scene Lifecycle
49
+ *
50
+ * Works a lot like global callbacks.
51
+ *
52
+ * 1. `like.setScene(scene)` is called
53
+ * 2. Scene's `load` callback fires immediately
54
+ * 3. `update` and `draw` begin on next frame
55
+ * 4. Scene receives input events as they occur
56
+ *
57
+ * ## Composing scenes
58
+ *
59
+ * Thought you'd never ask.
60
+ * Just like the `like` object, scenes have handleEvent on them.
61
+ * So, you could layer them like this, for example:
62
+ *
63
+ * ```typescript
64
+ * class UI implements Scene {
65
+ * constructor(public game: Game) {}
66
+ *
67
+ * handleEvent(like: Like, event: Like2DEvent) {
68
+ * // Block mouse events in order to create a top bar.
69
+ * const mouseY = like.mouse.getPosition()[1];
70
+ * if (!event.type.startsWith('mouse') || mouseY > 100) {
71
+ * sceneDispatch(this.game, like, event);
72
+ * }
73
+ *
74
+ * // Then, call my own callbacks.
75
+ * // By calling it here, the UI draws on top.
76
+ * callSceneHandlers(this, like, event);
77
+ * }
78
+ * ...
79
+ * }
80
+ *
81
+ * class Game implements Scene {
82
+ * ...
83
+ * }
84
+ *
85
+ * like.setScene(new UI(new Game()))
86
+ * ```
87
+ *
88
+ * Composing scenes lets you filter events, layer game elements,
89
+ * and more. Don't sleep on it.
90
+ */
4
91
  export type Scene = {
5
- [K in EventType]?: EventHandler<K>;
92
+ [K in keyof EventMap]?: (like: Like, ...args: EventMap[K]) => void;
6
93
  } & {
7
- handleEvent?(like: Like, event: Like2DEvent): void;
94
+ handleEvent?(like: Like, event: LikeEvent): void;
8
95
  };
9
- export {};
96
+ /**
97
+ * Used to call a scene's own handlers like `update` or `draw`,
98
+ * typically at the end of handleEvent
99
+ * after modifying the event stream or composing sub-scenes.
100
+ */
101
+ export declare const callSceneHandlers: (scene: Scene, like: Like, event: LikeEvent) => void;
102
+ /**
103
+ * Used to call sub scenes while respecting potential `handleEvent` within them.
104
+ * The main scene is similar to a sub-scene of the root (like) object in this
105
+ * regard.
106
+ */
107
+ export declare const sceneDispatch: (scene: Scene, like: Like, event: LikeEvent) => void;
10
108
  //# sourceMappingURL=scene.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,KAAK,YAAY,CAAC,CAAC,SAAS,SAAS,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AAEpF,MAAM,MAAM,KAAK,GAAG;KACjB,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;CACnC,GAAG;IACF,WAAW,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;CACpD,CAAC"}
1
+ {"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkFG;AAEH,MAAM,MAAM,KAAK,GAAG;KACjB,CAAC,IAAI,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI;CACnE,GAAG;IACF,WAAW,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CAClD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,OAAO,SAAS,SAI3E,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,OAAO,SAAS,SAMvE,CAAA"}
package/dist/scene.js CHANGED
@@ -1 +1,28 @@
1
- export {};
1
+ /**
2
+ * @module scene
3
+ * @description A helpful callback / state management layer, plus utility scenes.
4
+ *
5
+ */
6
+ /**
7
+ * Used to call a scene's own handlers like `update` or `draw`,
8
+ * typically at the end of handleEvent
9
+ * after modifying the event stream or composing sub-scenes.
10
+ */
11
+ export const callSceneHandlers = (scene, like, event) => {
12
+ if (event.type in scene) {
13
+ scene[event.type](like, ...event.args);
14
+ }
15
+ };
16
+ /**
17
+ * Used to call sub scenes while respecting potential `handleEvent` within them.
18
+ * The main scene is similar to a sub-scene of the root (like) object in this
19
+ * regard.
20
+ */
21
+ export const sceneDispatch = (scene, like, event) => {
22
+ if (scene.handleEvent) {
23
+ scene.handleEvent(like, event);
24
+ }
25
+ else {
26
+ callSceneHandlers(scene, like, event);
27
+ }
28
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "like2d",
3
- "version": "2.8.0",
3
+ "version": "2.9.0",
4
4
  "description": "A web-native game framework inspired by Love2D",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -10,6 +10,22 @@
10
10
  ".": {
11
11
  "import": "./dist/index.js",
12
12
  "types": "./dist/index.d.ts"
13
+ },
14
+ "./scene": {
15
+ "import": "./dist/scene.js",
16
+ "types": "./dist/scene.d.ts"
17
+ },
18
+ "./math/*": {
19
+ "import": "./dist/math/*.js",
20
+ "types": "./dist/math/*.d.ts"
21
+ },
22
+ "./prefab-scenes": {
23
+ "import": "./dist/prefab-scenes/index.js",
24
+ "types": "./dist/prefab-scenes/index.d.ts"
25
+ },
26
+ "./internal/*": {
27
+ "import": "./dist/core/*.js",
28
+ "types": "./dist/core/*.d.ts"
13
29
  }
14
30
  },
15
31
  "files": [
@@ -19,7 +35,7 @@
19
35
  "LICENSE"
20
36
  ],
21
37
  "scripts": {
22
- "build": "tsc && cp src/gamecontrollerdb.txt dist/",
38
+ "build": "tsc",
23
39
  "typecheck": "tsc --noEmit",
24
40
  "lint": "echo 'No linting configured'",
25
41
  "clean": "rm -rf dist",
@@ -1,22 +0,0 @@
1
- import type { Vector2 } from './vector2';
2
- export type CanvasMode = {
3
- pixelResolution: Vector2 | null;
4
- fullscreen: boolean;
5
- };
6
- export type PartialCanvasMode = {
7
- pixelResolution?: Vector2 | null;
8
- fullscreen?: boolean;
9
- };
10
- /**
11
- * Calculate the scale and offset for rendering fixed-size content to a target canvas.
12
- * This is useful when you want to render in "native" mode but maintain a fixed game resolution.
13
- *
14
- * @param canvasSize - The actual canvas size in pixels
15
- * @param gameSize - The desired game resolution (fixed size)
16
- * @returns Object containing the scale factor and offset for centering
17
- */
18
- export declare function calcFixedScale(canvasSize: Vector2, gameSize: Vector2): {
19
- scale: number;
20
- offset: Vector2;
21
- };
22
- //# sourceMappingURL=canvas-config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"canvas-config.d.ts","sourceRoot":"","sources":["../../src/core/canvas-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,MAAM,UAAU,GAAG;IACvB,eAAe,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,eAAe,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAKzG"}
@@ -1,14 +0,0 @@
1
- /**
2
- * Calculate the scale and offset for rendering fixed-size content to a target canvas.
3
- * This is useful when you want to render in "native" mode but maintain a fixed game resolution.
4
- *
5
- * @param canvasSize - The actual canvas size in pixels
6
- * @param gameSize - The desired game resolution (fixed size)
7
- * @returns Object containing the scale factor and offset for centering
8
- */
9
- export function calcFixedScale(canvasSize, gameSize) {
10
- const scale = Math.min(canvasSize[0] / gameSize[0], canvasSize[1] / gameSize[1]);
11
- const scaledGame = [gameSize[0] * scale, gameSize[1] * scale];
12
- const offset = [(canvasSize[0] - scaledGame[0]) * 0.5, (canvasSize[1] - scaledGame[1]) * 0.5];
13
- return { scale, offset };
14
- }
@@ -1,32 +0,0 @@
1
- import type { CanvasMode, PartialCanvasMode } from './canvas-config';
2
- import { type Vector2 } from './vector2';
3
- export declare class CanvasManager {
4
- private canvas;
5
- private container;
6
- private ctx;
7
- private config;
8
- private resizeObserver;
9
- private pixelCanvas;
10
- private pixelCtx;
11
- private onWindowResize;
12
- onResize: ((size: Vector2, pixelSize: Vector2, fullscreen: boolean) => void) | null;
13
- constructor(canvas: HTMLCanvasElement, container: HTMLElement, ctx: CanvasRenderingContext2D, config?: CanvasMode);
14
- private listenForPixelRatioChanges;
15
- setMode(mode: PartialCanvasMode): void;
16
- getMode(): CanvasMode;
17
- private applyConfig;
18
- private applyPixelMode;
19
- private applyNativeMode;
20
- dispose(): void;
21
- present(): void;
22
- getDisplayCanvas(): HTMLCanvasElement;
23
- /** Canvas to render to. Pixel canvas in pixel mode, display canvas otherwise. */
24
- getRenderTarget(): {
25
- canvas: HTMLCanvasElement;
26
- ctx: CanvasRenderingContext2D;
27
- };
28
- /** Render target size in pixels. Pixel resolution in pixel mode, scaled size otherwise. */
29
- getCanvasSize(): Vector2;
30
- transformMousePosition(offsetX: number, offsetY: number): Vector2;
31
- }
32
- //# sourceMappingURL=canvas-manager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"canvas-manager.d.ts","sourceRoot":"","sources":["../../src/core/canvas-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAmB/C,qBAAa,aAAa;IAUtB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,MAAM;IAZhB,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,QAAQ,CAAyC;IAEzD,OAAO,CAAC,cAAc,CAA4B;IAE3C,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;gBAGxF,MAAM,EAAE,iBAAiB,EACzB,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,wBAAwB,EAC7B,MAAM,GAAE,UAAyD;IAW3E,OAAO,CAAC,0BAA0B;IAQlC,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI;IAKtC,OAAO,IAAI,UAAU;IAIrB,OAAO,CAAC,WAAW;IAwBnB,OAAO,CAAC,cAAc;IAqBtB,OAAO,CAAC,eAAe;IAkBvB,OAAO,IAAI,IAAI;IAQf,OAAO,IAAI,IAAI;IAaf,gBAAgB,IAAI,iBAAiB;IAIrC,iFAAiF;IACjF,eAAe,IAAI;QAAE,MAAM,EAAE,iBAAiB,CAAC;QAAC,GAAG,EAAE,wBAAwB,CAAA;KAAE;IAO/E,2FAA2F;IAC3F,aAAa,IAAI,OAAO;IAKxB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;CAYlE"}