like2d 2.9.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 (103) hide show
  1. package/README.md +21 -17
  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 +12 -3
  6. package/dist/audio/audio.d.ts.map +1 -0
  7. package/dist/{core → audio}/audio.js +10 -2
  8. package/dist/audio/index.d.ts +2 -0
  9. package/dist/audio/index.d.ts.map +1 -0
  10. package/dist/audio/index.js +1 -0
  11. package/dist/engine.d.ts +12 -42
  12. package/dist/engine.d.ts.map +1 -1
  13. package/dist/engine.js +34 -76
  14. package/dist/{core/events.d.ts → events.d.ts} +27 -50
  15. package/dist/events.d.ts.map +1 -0
  16. package/dist/events.js +5 -0
  17. package/dist/gamecontrollerdb.txt +2222 -0
  18. package/dist/{core → graphics}/canvas.d.ts +18 -11
  19. package/dist/graphics/canvas.d.ts.map +1 -0
  20. package/dist/{core → graphics}/canvas.js +73 -58
  21. package/dist/{core/graphics.d.ts → graphics/drawing.d.ts} +25 -25
  22. package/dist/graphics/drawing.d.ts.map +1 -0
  23. package/dist/{core/graphics.js → graphics/drawing.js} +59 -52
  24. package/dist/graphics/index.d.ts +19 -0
  25. package/dist/graphics/index.d.ts.map +1 -0
  26. package/dist/graphics/index.js +13 -0
  27. package/dist/index.d.ts +3 -30
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +0 -21
  30. package/dist/input/gamepad-mapping.d.ts +134 -0
  31. package/dist/input/gamepad-mapping.d.ts.map +1 -0
  32. package/dist/input/gamepad-mapping.js +146 -0
  33. package/dist/input/gamepad.d.ts +74 -0
  34. package/dist/input/gamepad.d.ts.map +1 -0
  35. package/dist/input/gamepad.js +288 -0
  36. package/dist/input/index.d.ts +6 -0
  37. package/dist/input/index.d.ts.map +1 -0
  38. package/dist/input/index.js +1 -0
  39. package/dist/input/input.d.ts +76 -0
  40. package/dist/input/input.d.ts.map +1 -0
  41. package/dist/input/input.js +164 -0
  42. package/dist/input/keyboard.d.ts +15 -0
  43. package/dist/input/keyboard.d.ts.map +1 -0
  44. package/dist/{core → input}/keyboard.js +11 -21
  45. package/dist/input/mouse.d.ts +108 -0
  46. package/dist/input/mouse.d.ts.map +1 -0
  47. package/dist/input/mouse.js +241 -0
  48. package/dist/like.d.ts +80 -0
  49. package/dist/like.d.ts.map +1 -0
  50. package/dist/like.js +5 -0
  51. package/dist/math/index.d.ts +16 -0
  52. package/dist/math/index.d.ts.map +1 -1
  53. package/dist/math/index.js +16 -0
  54. package/dist/math/rect.d.ts +24 -27
  55. package/dist/math/rect.d.ts.map +1 -1
  56. package/dist/math/rect.js +47 -73
  57. package/dist/math/vector2.d.ts +87 -32
  58. package/dist/math/vector2.d.ts.map +1 -1
  59. package/dist/math/vector2.js +92 -110
  60. package/dist/prefab-scenes/index.d.ts +1 -0
  61. package/dist/prefab-scenes/index.d.ts.map +1 -1
  62. package/dist/prefab-scenes/index.js +1 -0
  63. package/dist/prefab-scenes/mapGamepad.d.ts +28 -0
  64. package/dist/prefab-scenes/mapGamepad.d.ts.map +1 -0
  65. package/dist/prefab-scenes/mapGamepad.js +181 -0
  66. package/dist/prefab-scenes/startScreen.d.ts +2 -2
  67. package/dist/prefab-scenes/startScreen.js +2 -2
  68. package/dist/scene.d.ts +2 -2
  69. package/dist/scene.d.ts.map +1 -1
  70. package/dist/timer/index.d.ts +2 -0
  71. package/dist/timer/index.d.ts.map +1 -0
  72. package/dist/timer/index.js +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 +20 -3
  76. package/package.json +22 -13
  77. package/dist/core/audio.d.ts.map +0 -1
  78. package/dist/core/canvas.d.ts.map +0 -1
  79. package/dist/core/events.d.ts.map +0 -1
  80. package/dist/core/events.js +0 -21
  81. package/dist/core/gamepad-mapping.d.ts +0 -58
  82. package/dist/core/gamepad-mapping.d.ts.map +0 -1
  83. package/dist/core/gamepad-mapping.js +0 -23
  84. package/dist/core/gamepad.d.ts +0 -37
  85. package/dist/core/gamepad.d.ts.map +0 -1
  86. package/dist/core/gamepad.js +0 -103
  87. package/dist/core/graphics.d.ts.map +0 -1
  88. package/dist/core/input-state.d.ts +0 -14
  89. package/dist/core/input-state.d.ts.map +0 -1
  90. package/dist/core/input-state.js +0 -50
  91. package/dist/core/input.d.ts +0 -40
  92. package/dist/core/input.d.ts.map +0 -1
  93. package/dist/core/input.js +0 -105
  94. package/dist/core/keyboard.d.ts +0 -15
  95. package/dist/core/keyboard.d.ts.map +0 -1
  96. package/dist/core/like.d.ts +0 -113
  97. package/dist/core/like.d.ts.map +0 -1
  98. package/dist/core/like.js +0 -9
  99. package/dist/core/mouse.d.ts +0 -52
  100. package/dist/core/mouse.d.ts.map +0 -1
  101. package/dist/core/mouse.js +0 -142
  102. package/dist/core/timer.d.ts +0 -15
  103. package/dist/core/timer.d.ts.map +0 -1
@@ -0,0 +1,181 @@
1
+ import { defaultMapping } from "../input";
2
+ const mapOrder = [
3
+ "BRight",
4
+ "BBottom",
5
+ "Up",
6
+ "Down",
7
+ "Left",
8
+ "Right",
9
+ "MenuLeft",
10
+ "MenuRight",
11
+ // 8: NES buttons
12
+ "L1",
13
+ "R1",
14
+ // 10: GBA buttons
15
+ "BLeft",
16
+ "BTop",
17
+ // 12: SNES buttons
18
+ "L2",
19
+ "R2",
20
+ // 14: PS1 buttons
21
+ "LeftStick",
22
+ "RightStick",
23
+ ];
24
+ export const buttonSetNES = new Set(mapOrder.slice(0, 8));
25
+ export const buttonSetGBA = new Set(mapOrder.slice(0, 10));
26
+ export const buttonSetSNES = new Set(mapOrder.slice(0, 12));
27
+ export const buttonSetPS1 = new Set(mapOrder.slice(0, 14));
28
+ export const buttonSetAll = new Set(mapOrder);
29
+ const drawCircButt = (pos, size) => (like, color) => like.gfx.circle("fill", color, pos, size);
30
+ const drawDpadPart = (rot) => (like, color) => {
31
+ like.gfx.push();
32
+ like.gfx.translate([2.5, 6]);
33
+ like.gfx.rotate(rot);
34
+ like.gfx.rectangle("fill", color, [0.5, -0.5, 1.3, 1]);
35
+ like.gfx.pop();
36
+ };
37
+ const drawShoulder = (y, width, flip) => (like, color) => {
38
+ const r = 0.8;
39
+ const rectPos = [5 - width, y];
40
+ const circPos = [5 - width - r, y];
41
+ like.gfx.push();
42
+ if (flip) {
43
+ like.gfx.translate([16, 0]);
44
+ like.gfx.scale([-1, 1]);
45
+ }
46
+ like.gfx.circle("fill", color, circPos, r, { arc: [Math.PI, Math.PI * 3 / 2], center: false });
47
+ like.gfx.rectangle("fill", color, [...rectPos, width, r]);
48
+ like.gfx.pop();
49
+ };
50
+ // Buttons assume a centered resolution of 16x9px. Transforms exist for a reason lol.
51
+ // LLLLL . RRRRR
52
+ // LLLLLLLLL . RRRRRRRRR
53
+ // .
54
+ // DDD S . S B
55
+ // -.....DDD.....................................
56
+ // DDD DDD . B B
57
+ // DDD LS . RS
58
+ // DDD . B
59
+ // .
60
+ const buttonProps = {
61
+ BLeft: { draw: drawCircButt([12, 6], 0.8) },
62
+ BRight: { draw: drawCircButt([15, 6], 0.8) },
63
+ BTop: { draw: drawCircButt([13.5, 4.5], 0.8) },
64
+ BBottom: { draw: drawCircButt([13.5, 7.5], 0.8) },
65
+ MenuLeft: { draw: drawCircButt([6, 4], 0.5) },
66
+ MenuRight: { draw: drawCircButt([10, 4], 0.5) },
67
+ LeftStick: { draw: drawCircButt([6.5, 7], 1.4) },
68
+ RightStick: { draw: drawCircButt([9.5, 7], 1.4) },
69
+ L1: { draw: drawShoulder(2, 3, false) },
70
+ L2: { draw: drawShoulder(1, 2, false) },
71
+ R1: { draw: drawShoulder(2, 3, true) },
72
+ R2: { draw: drawShoulder(1, 2, true) },
73
+ Right: { draw: drawDpadPart(0) },
74
+ Up: { draw: drawDpadPart(-Math.PI / 2) },
75
+ Left: { draw: drawDpadPart(Math.PI) },
76
+ Down: { draw: drawDpadPart(Math.PI / 2) },
77
+ };
78
+ export class MapGamepad {
79
+ constructor(mapMode, targetPad, next) {
80
+ Object.defineProperty(this, "mapMode", {
81
+ enumerable: true,
82
+ configurable: true,
83
+ writable: true,
84
+ value: mapMode
85
+ });
86
+ Object.defineProperty(this, "targetPad", {
87
+ enumerable: true,
88
+ configurable: true,
89
+ writable: true,
90
+ value: targetPad
91
+ });
92
+ Object.defineProperty(this, "next", {
93
+ enumerable: true,
94
+ configurable: true,
95
+ writable: true,
96
+ value: next
97
+ });
98
+ Object.defineProperty(this, "currentlyUnmapped", {
99
+ enumerable: true,
100
+ configurable: true,
101
+ writable: true,
102
+ value: []
103
+ });
104
+ Object.defineProperty(this, "mapping", {
105
+ enumerable: true,
106
+ configurable: true,
107
+ writable: true,
108
+ value: void 0
109
+ });
110
+ Object.defineProperty(this, "held", {
111
+ enumerable: true,
112
+ configurable: true,
113
+ writable: true,
114
+ value: void 0
115
+ });
116
+ Object.defineProperty(this, "alreadyMapped", {
117
+ enumerable: true,
118
+ configurable: true,
119
+ writable: true,
120
+ value: new Set()
121
+ });
122
+ }
123
+ load(like) {
124
+ this.mapping = like.gamepad.getMapping(this.targetPad) ?? defaultMapping(2);
125
+ for (const btn of mapOrder.reverse()) {
126
+ if (this.mapMode.buttons.has(btn)) {
127
+ this.currentlyUnmapped.push(btn);
128
+ }
129
+ }
130
+ like.canvas.setMode([320, 240]);
131
+ }
132
+ draw(like) {
133
+ const centerText = {
134
+ font: "1px sans-serif",
135
+ align: "center",
136
+ width: 16,
137
+ };
138
+ const active = this.currentlyUnmapped.at(-1);
139
+ like.gfx.clear();
140
+ like.gfx.scale(20);
141
+ like.gfx.translate([0, 1]);
142
+ like.gfx.print("white", "Map gamepad (click to close)", [8, 0.0], centerText);
143
+ for (const prop of this.mapMode.buttons.keys()) {
144
+ const color = this.held == prop
145
+ ? "green"
146
+ : active == prop
147
+ ? "red"
148
+ : this.mapMode.buttons.has(prop)
149
+ ? "gray"
150
+ : "black";
151
+ buttonProps[prop].draw(like, color);
152
+ }
153
+ like.gfx.print("white", active
154
+ ? `Press ${like.gamepad.fullButtonName(active)}!`
155
+ : "Press any button to resume.", [2, 10], { font: "1px sans-serif" });
156
+ }
157
+ gamepadpressed(like, source, _name, num) {
158
+ if (source !== this.targetPad || this.held)
159
+ return;
160
+ const active = this.currentlyUnmapped.pop();
161
+ if (active && !this.alreadyMapped.has(num)) {
162
+ this.alreadyMapped.add(num);
163
+ this.mapping.buttons[num] = active;
164
+ this.held = active;
165
+ }
166
+ else if (!active) {
167
+ like.gamepad.setMapping(this.targetPad, this.mapping);
168
+ setTimeout(() => like.setScene(this.next), 100);
169
+ }
170
+ }
171
+ gamepadreleased(_like, source, _name, num) {
172
+ if (source !== this.targetPad)
173
+ return;
174
+ if (this.held == this.mapping.buttons[num]) {
175
+ this.held = undefined;
176
+ }
177
+ }
178
+ mousepressed(like) {
179
+ like.setScene(this.next);
180
+ }
181
+ }
@@ -31,8 +31,8 @@ import { Like } from '..';
31
31
  *
32
32
  * ```ts
33
33
  * import { type Scene } from 'like/scene';
34
- * import type { ImageHandle } from 'like/core/graphics';
35
- * import { Vec2 } from 'like/math/vector2';
34
+ * import type { ImageHandle } from 'like/graphics';
35
+ * import { Vec2 } from 'like/math';
36
36
  * import { Like } from 'like';
37
37
  * ```
38
38
  *
@@ -31,8 +31,8 @@ const LOGO = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0i
31
31
  *
32
32
  * ```ts
33
33
  * import { type Scene } from 'like/scene';
34
- * import type { ImageHandle } from 'like/core/graphics';
35
- * import { Vec2 } from 'like/math/vector2';
34
+ * import type { ImageHandle } from 'like/graphics';
35
+ * import { Vec2 } from 'like/math';
36
36
  * import { Like } from 'like';
37
37
  * ```
38
38
  *
package/dist/scene.d.ts CHANGED
@@ -3,8 +3,8 @@
3
3
  * @description A helpful callback / state management layer, plus utility scenes.
4
4
  *
5
5
  */
6
- import type { LikeEvent, EventMap } from './core/events';
7
- import type { Like } from './core/like';
6
+ import type { LikeEvent, EventMap } from './events';
7
+ import type { Like } from './like';
8
8
  /**
9
9
  * An interface for creating scenes.
10
10
  *
@@ -1 +1 @@
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"}
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,UAAU,CAAC;AACpD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
@@ -0,0 +1,2 @@
1
+ export { type Timer } from "./timer";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/timer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,32 @@
1
+ import { EngineProps } from "../engine";
2
+ export declare class Timer {
3
+ private currentDelta;
4
+ private totalTime;
5
+ private frameCount;
6
+ private fps;
7
+ private fpsAccumulator;
8
+ private sleepUntil;
9
+ constructor(props: EngineProps<never>);
10
+ private update;
11
+ /** Get `dt` (from the update loop) anywhere.
12
+ * AKA the time since the last frame.
13
+ */
14
+ getDelta(): number;
15
+ /** Get an estimated FPS based on one-second average. */
16
+ getFPS(): number;
17
+ /** Get the ingame time. */
18
+ getTime(): number;
19
+ /**
20
+ * Whether or not the game is (supposed to be) frozen.
21
+ * The only callback while sleeping is `draw`, and
22
+ * calling this outside of `draw` will always return
23
+ * false -- except if you have a custom runtime.
24
+ */
25
+ isSleeping(): boolean;
26
+ /**
27
+ * Freeze the whole game for a time. Audio will keep playing,
28
+ * but update functions won't be called and events won't fire.
29
+ */
30
+ sleep(duration: number): void;
31
+ }
32
+ //# sourceMappingURL=timer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timer.d.ts","sourceRoot":"","sources":["../../src/timer/timer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,qBAAa,KAAK;IAChB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAuB;gBAE7B,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC;IAIrC,OAAO,CAAC,MAAM;IAcd;;OAEG;IACH,QAAQ,IAAI,MAAM;IAIlB,wDAAwD;IACxD,MAAM,IAAI,MAAM;IAIhB,2BAA2B;IAC3B,OAAO,IAAI,MAAM;IAIjB;;;;;OAKG;IACH,UAAU,IAAI,OAAO;IAUrB;;;OAGG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;CAG9B"}
@@ -1,5 +1,5 @@
1
- export class TimerInternal {
2
- constructor() {
1
+ export class Timer {
2
+ constructor(props) {
3
3
  Object.defineProperty(this, "currentDelta", {
4
4
  enumerable: true,
5
5
  configurable: true,
@@ -36,8 +36,10 @@ export class TimerInternal {
36
36
  writable: true,
37
37
  value: null
38
38
  });
39
+ props.canvas.addEventListener("like:update", this.update.bind(this), { signal: props.abort });
39
40
  }
40
- _update(dt) {
41
+ update(ev) {
42
+ const { dt } = ev.detail;
41
43
  this.currentDelta = dt;
42
44
  this.totalTime += dt;
43
45
  this.frameCount++;
@@ -48,15 +50,26 @@ export class TimerInternal {
48
50
  this.fpsAccumulator = 0;
49
51
  }
50
52
  }
53
+ /** Get `dt` (from the update loop) anywhere.
54
+ * AKA the time since the last frame.
55
+ */
51
56
  getDelta() {
52
57
  return this.currentDelta;
53
58
  }
59
+ /** Get an estimated FPS based on one-second average. */
54
60
  getFPS() {
55
61
  return this.fps;
56
62
  }
63
+ /** Get the ingame time. */
57
64
  getTime() {
58
65
  return this.totalTime;
59
66
  }
67
+ /**
68
+ * Whether or not the game is (supposed to be) frozen.
69
+ * The only callback while sleeping is `draw`, and
70
+ * calling this outside of `draw` will always return
71
+ * false -- except if you have a custom runtime.
72
+ */
60
73
  isSleeping() {
61
74
  if (this.sleepUntil === null)
62
75
  return false;
@@ -67,6 +80,10 @@ export class TimerInternal {
67
80
  this.sleepUntil = null;
68
81
  return false;
69
82
  }
83
+ /**
84
+ * Freeze the whole game for a time. Audio will keep playing,
85
+ * but update functions won't be called and events won't fire.
86
+ */
70
87
  sleep(duration) {
71
88
  this.sleepUntil = performance.now() + (duration * 1000);
72
89
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "like2d",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "description": "A web-native game framework inspired by Love2D",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -11,21 +11,29 @@
11
11
  "import": "./dist/index.js",
12
12
  "types": "./dist/index.d.ts"
13
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"
14
+ "./math": {
15
+ "import": "./dist/math/index.js",
16
+ "types": "./dist/math/index.d.ts"
21
17
  },
22
18
  "./prefab-scenes": {
23
19
  "import": "./dist/prefab-scenes/index.js",
24
20
  "types": "./dist/prefab-scenes/index.d.ts"
25
21
  },
26
- "./internal/*": {
27
- "import": "./dist/core/*.js",
28
- "types": "./dist/core/*.d.ts"
22
+ "./graphics": {
23
+ "import": "./dist/graphics/index.js",
24
+ "types": "./dist/graphics/index.d.ts"
25
+ },
26
+ "./audio": {
27
+ "import": "./dist/audio/index.js",
28
+ "types": "./dist/audio/index.d.ts"
29
+ },
30
+ "./input": {
31
+ "import": "./dist/input/index.js",
32
+ "types": "./dist/input/index.d.ts"
33
+ },
34
+ "./timer": {
35
+ "import": "./dist/timer/index.js",
36
+ "types": "./dist/timer/index.d.ts"
29
37
  }
30
38
  },
31
39
  "files": [
@@ -35,11 +43,12 @@
35
43
  "LICENSE"
36
44
  ],
37
45
  "scripts": {
38
- "build": "tsc",
46
+ "build": "tsc && cp src/gamecontrollerdb.txt dist/",
39
47
  "typecheck": "tsc --noEmit",
40
48
  "lint": "echo 'No linting configured'",
41
49
  "clean": "rm -rf dist",
42
- "test": "vitest run"
50
+ "test": "vitest run",
51
+ "bench": "vitest bench"
43
52
  },
44
53
  "keywords": [
45
54
  "game",
@@ -1 +0,0 @@
1
- {"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../../src/core/audio.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAA;AAMD;;;;;;GAMG;AACH,qBAAa,WAAW;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6IAA6I;IAC7I,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAC/C,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,CAAC,SAAS,CAAoE;IACrF,OAAO,CAAC,QAAQ,CAAgB;gBAEpB,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,GAAE,kBAAuB;IAmCnF,OAAO,IAAI,OAAO;IAIlB,IAAI,IAAI,IAAI;IAUZ,IAAI,IAAI,IAAI;IAUZ,KAAK,IAAI,IAAI;IAQb,MAAM,IAAI,IAAI;IAYd,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQ5B,IAAI,IAAI,MAAM;IAKd,SAAS,IAAI,OAAO;IAKpB,QAAQ,IAAI,OAAO;IAKnB,SAAS,IAAI,OAAO;IAKpB,+FAA+F;IAC/F,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK/B,SAAS,IAAI,MAAM;IAInB,WAAW,IAAI,MAAM;CAItB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,YAAY,CAAK;IAEzB;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW;IAMlE;;;QAGI;IACJ,aAAa,IAAI,WAAW,EAAE;IAS9B,OAAO,IAAI,IAAI;IAIf,QAAQ,IAAI,IAAI;IAIhB,SAAS,IAAI,IAAI;IAIjB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAO/B,SAAS,IAAI,MAAM;IAInB,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW;CAGxC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../../src/core/canvas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAQ,SAAS,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,MAAM,iBAAiB,GAAG;IAAE,UAAU,EAAE,OAAO,CAAA;CAAE,CAAC;AACxD,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,qBAAa,cAAc;IAYJ,QAAQ,EAAE,cAAc;IAX3C,mDAAmD;IAC5C,cAAc,EAAE,iBAAiB,CAAC;IACzC;;;MAGE;IACK,aAAa,EAAE,iBAAiB,CAAC;IAExC,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,KAAK,CAAyB;gBAEnB,QAAQ,EAAE,cAAc;IA0D3C,wCAAwC;IACxC,OAAO,IAAI;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,iBAAiB,CAAA;KAAE;IAStD;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,GAAE,OAAO,CAAC,iBAAiB,CAAM;IA2BhE,8CAA8C;IAC9C,OAAO,IAAI,OAAO;IAIlB,wCAAwC;IACxC,OAAO,IAAI,SAAS;IAIpB,uDAAuD;IACvD,oBAAoB,IAAI,OAAO;IAO/B,yBAAyB;IACzB,aAAa,IAAI,OAAO;IAIxB,sBAAsB;IACtB,aAAa,CAAC,UAAU,EAAE,OAAO;IASjC,qDAAqD;IACrD,QAAQ;IAyCR,qCAAqC;IACrC,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO;IAO9E,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO;IAI5D,QAAQ,IAAI,IAAI;CAGnB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/core/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,mBAAmB;QAC3B,CAAC,iBAAiB,CAAC,EAAE,WAAW,CAAC;YAAC,GAAG,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,OAAO,CAAC;YAAC,UAAU,EAAE,OAAO,CAAA;SAAC,CAAC,CAAC;QACtF,CAAC,yBAAyB,CAAC,EAAE,WAAW,CAAC;YAAC,MAAM,EAAE,iBAAiB,CAAA;SAAC,CAAC,CAAC;KACvE;CACF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,+DAA+D;IAC/D,IAAI,EAAE,EAAE,CAAC;IAET,yEAAyE;IACzE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAErB,8DAA8D;IAC9D,IAAI,EAAE,EAAE,CAAC;IAET,sFAAsF;IACtF,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAExB,oFAAoF;IACpF,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAEhD,6BAA6B;IAC7B,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAEjD,iEAAiE;IACjE,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC;IAElC,8DAA8D;IAC9D,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC;IAEjC,iEAAiE;IACjE,UAAU,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAE3C,qFAAqF;IACrF,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IAElD,6BAA6B;IAC7B,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IAEnD,gEAAgE;IAChE,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAEhE,+BAA+B;IAC/B,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAEjE,qEAAqE;IACrE,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhC,8BAA8B;IAC9B,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC;AAEvC;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,SAAS,GAAG;KACrB,CAAC,IAAI,SAAS,GAAG;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;CACpE,CAAC,SAAS,CAAC,CAAC"}
@@ -1,21 +0,0 @@
1
- /**
2
- * @module events
3
- * @description All events that flow through the engine.
4
- *
5
- * ## Overview
6
- *
7
- * LIKE uses events at its core.
8
- * These pass through the engine and down to your
9
- * callbacks or scene.
10
- *
11
- * This module is the single source of truth for what
12
- * events are possible.
13
- *
14
- * Use it as a reference.
15
- *
16
- * @see {@link EventMap} lists every event.
17
- * @see {@link Scene} for implementing callbacks in a class
18
- * @see {@link Like} for global callback assignment
19
- * @see {@link Input} for action mapping
20
- */
21
- export {};
@@ -1,58 +0,0 @@
1
- declare const buttonMap: readonly [{
2
- readonly like: "ButtonBottom";
3
- readonly num: number;
4
- }, {
5
- readonly like: "ButtonRight";
6
- readonly num: 1;
7
- }, {
8
- readonly like: "ButtonLeft";
9
- readonly num: 2;
10
- }, {
11
- readonly like: "ButtonTop";
12
- readonly num: 3;
13
- }, {
14
- readonly like: "ButtonL1";
15
- readonly num: 4;
16
- }, {
17
- readonly like: "ButtonR1";
18
- readonly num: 5;
19
- }, {
20
- readonly like: "ButtonL2";
21
- readonly num: 6;
22
- }, {
23
- readonly like: "ButtonR2";
24
- readonly num: 7;
25
- }, {
26
- readonly like: "ButtonMenuLeft";
27
- readonly num: 8;
28
- }, {
29
- readonly like: "ButtonMenuRight";
30
- readonly num: 9;
31
- }, {
32
- readonly like: "ButtonMenuCenter";
33
- readonly num: 16;
34
- }, {
35
- readonly like: "ButtonLeftStick";
36
- readonly num: 10;
37
- }, {
38
- readonly like: "ButtonRightStick";
39
- readonly num: 11;
40
- }, {
41
- readonly like: "DPadUp";
42
- readonly num: 12;
43
- }, {
44
- readonly like: "DPadDown";
45
- readonly num: 13;
46
- }, {
47
- readonly like: "DPadLeft";
48
- readonly num: 14;
49
- }, {
50
- readonly like: "DPadRight";
51
- readonly num: 15;
52
- }];
53
- type extraButton = `Button${number}`;
54
- export type LikeButton = (typeof buttonMap)[number]["like"] | extraButton;
55
- export declare const numberToName: Map<number, LikeButton>;
56
- export declare const nameToNumber: Map<LikeButton, number>;
57
- export {};
58
- //# sourceMappingURL=gamepad-mapping.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gamepad-mapping.d.ts","sourceRoot":"","sources":["../../src/core/gamepad-mapping.ts"],"names":[],"mappings":"AAGA,QAAA,MAAM,SAAS;;kBACqB,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqBhC,CAAC;AAEX,KAAK,WAAW,GAAG,SAAS,MAAM,EAAE,CAAC;AAErC,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC;AAE1E,eAAO,MAAM,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAEhD,CAAC;AACF,eAAO,MAAM,YAAY,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAEhD,CAAC"}
@@ -1,23 +0,0 @@
1
- // Friendlier names for the buttons.
2
- // https://www.w3.org/TR/gamepad/#dfn-standard-gamepad
3
- const buttonMap = [
4
- { like: "ButtonBottom", num: 0 },
5
- { like: "ButtonRight", num: 1 },
6
- { like: "ButtonLeft", num: 2 },
7
- { like: "ButtonTop", num: 3 },
8
- { like: "ButtonL1", num: 4 },
9
- { like: "ButtonR1", num: 5 },
10
- { like: "ButtonL2", num: 6 },
11
- { like: "ButtonR2", num: 7 },
12
- { like: "ButtonMenuLeft", num: 8 },
13
- { like: "ButtonMenuRight", num: 9 },
14
- { like: "ButtonMenuCenter", num: 16 },
15
- { like: "ButtonLeftStick", num: 10 },
16
- { like: "ButtonRightStick", num: 11 },
17
- { like: "DPadUp", num: 12 },
18
- { like: "DPadDown", num: 13 },
19
- { like: "DPadLeft", num: 14 },
20
- { like: "DPadRight", num: 15 },
21
- ];
22
- export const numberToName = new Map(buttonMap.map(({ like, num }) => [num, like]));
23
- export const nameToNumber = new Map(buttonMap.map(({ like, num }) => [like, num]));
@@ -1,37 +0,0 @@
1
- import { LikeButton } from './gamepad-mapping';
2
- import { EngineDispatch } from '../engine';
3
- export type { LikeButton };
4
- /** A selector for a gamepad. */
5
- export type GamepadTarget = number;
6
- export type ButtonTracker = {
7
- prev: Set<number>;
8
- current: Set<number>;
9
- };
10
- /** LIKE Gamepad Wrapper
11
- *
12
- * - Allows events/callbacks to be sent from joy buttons
13
- * - Extends stateful API with justPressed
14
- *
15
- * # Examples
16
- *
17
- * ### Binding events
18
- * ```ts
19
- * like.gamepadpressed = (idx: number, _num: number, button: string) => {
20
- * console.log(`Button ${button} pressed on controller ${idx}`);
21
- * }
22
- * ```
23
- */
24
- export declare class GamepadInternal {
25
- private dispatch;
26
- private buttonTrackers;
27
- private abort;
28
- constructor(dispatch: EngineDispatch);
29
- _update(): void;
30
- isButtonDown(target: GamepadTarget, buttonRaw: number | LikeButton): boolean | undefined;
31
- isButtonJustPressed(target: GamepadTarget, buttonRaw: LikeButton): boolean | undefined;
32
- getGamepad(target: number): Gamepad | null;
33
- _dispose(): void;
34
- static getButtonName(button: number | LikeButton): LikeButton;
35
- static getButtonNumber(button: number | LikeButton): number;
36
- }
37
- //# sourceMappingURL=gamepad.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gamepad.d.ts","sourceRoot":"","sources":["../../src/core/gamepad.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA8B,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,YAAY,EAAE,UAAU,EAAE,CAAC;AAE3B,gCAAgC;AAChC,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClB,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACtB,CAAA;AAKD;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAe;IAId,OAAO,CAAC,QAAQ;IAH5B,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,KAAK,CAAyB;gBAElB,QAAQ,EAAE,cAAc;IAwB5C,OAAO,IAAI,IAAI;IA4Bf,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS;IAKxF,mBAAmB,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS;IAQtF,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IAI1C,QAAQ,IAAI,IAAI;WAIF,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU;WAMtD,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM;CAMnE"}
@@ -1,103 +0,0 @@
1
- import { nameToNumber, numberToName } from './gamepad-mapping';
2
- const newButtonTracker = () => ({ prev: new Set(), current: new Set() });
3
- /** LIKE Gamepad Wrapper
4
- *
5
- * - Allows events/callbacks to be sent from joy buttons
6
- * - Extends stateful API with justPressed
7
- *
8
- * # Examples
9
- *
10
- * ### Binding events
11
- * ```ts
12
- * like.gamepadpressed = (idx: number, _num: number, button: string) => {
13
- * console.log(`Button ${button} pressed on controller ${idx}`);
14
- * }
15
- * ```
16
- */
17
- export class GamepadInternal {
18
- constructor(dispatch) {
19
- Object.defineProperty(this, "dispatch", {
20
- enumerable: true,
21
- configurable: true,
22
- writable: true,
23
- value: dispatch
24
- });
25
- Object.defineProperty(this, "buttonTrackers", {
26
- enumerable: true,
27
- configurable: true,
28
- writable: true,
29
- value: new Map()
30
- });
31
- Object.defineProperty(this, "abort", {
32
- enumerable: true,
33
- configurable: true,
34
- writable: true,
35
- value: new AbortController()
36
- });
37
- // Register event listeners
38
- window.addEventListener("gamepadconnected", (ev) => {
39
- if (ev.gamepad.mapping == "standard") {
40
- console.log(`[Gamepad] Connected standard gamepad ${ev.gamepad.id}.`);
41
- }
42
- else {
43
- console.log(`[Gamepad] Connected non-standard gamepad ${ev.gamepad.id}. Consider remapping.`);
44
- }
45
- console.log(`[Gamepad] buttons: ${ev.gamepad.buttons.length}, axes: ${ev.gamepad.axes.length}`);
46
- this.buttonTrackers.set(ev.gamepad.index, newButtonTracker());
47
- }, { signal: this.abort.signal });
48
- window.addEventListener("gamepaddisconnected", (ev) => {
49
- console.log(`[Gamepad] Disconnected ${ev.gamepad.id}`);
50
- this.buttonTrackers.delete(ev.gamepad.index);
51
- }, { signal: this.abort.signal });
52
- window.addEventListener("blur", () => {
53
- this.buttonTrackers.forEach(({ current, prev }) => { current.clear(); prev.clear(); });
54
- }, { signal: this.abort.signal });
55
- }
56
- _update() {
57
- const gamepads = navigator.getGamepads().filter((v) => v !== null);
58
- gamepads.forEach((domGp, gpIndex) => {
59
- const tracker = this.buttonTrackers.get(gpIndex);
60
- if (!tracker)
61
- return;
62
- const prev = tracker.current;
63
- tracker.current = new Set(domGp.buttons
64
- .map((btn, i) => (btn.pressed ? i : null))
65
- .filter((v) => v != null));
66
- domGp.buttons.forEach((_, i) => {
67
- if (i > 15)
68
- return;
69
- if (tracker.prev.has(i) != tracker.current.has(i)) {
70
- this.dispatch(tracker.prev.has(i) ? "gamepadreleased" : "gamepadpressed", [gpIndex, i, GamepadInternal.getButtonName(i)]);
71
- }
72
- });
73
- tracker.prev = prev;
74
- });
75
- }
76
- isButtonDown(target, buttonRaw) {
77
- const btn = GamepadInternal.getButtonNumber(buttonRaw);
78
- return this.buttonTrackers.get(target)?.current.has(btn);
79
- }
80
- isButtonJustPressed(target, buttonRaw) {
81
- const btn = GamepadInternal.getButtonNumber(buttonRaw);
82
- const bt = this.buttonTrackers.get(target);
83
- if (bt) {
84
- return !bt.prev.has(btn) && bt.current.has(btn);
85
- }
86
- }
87
- getGamepad(target) {
88
- return navigator.getGamepads()?.[target] ?? null;
89
- }
90
- _dispose() {
91
- this.abort.abort();
92
- }
93
- static getButtonName(button) {
94
- return typeof button == "number"
95
- ? (numberToName.get(button) ?? `Button${button}`)
96
- : button;
97
- }
98
- static getButtonNumber(button) {
99
- return typeof button == "number"
100
- ? button
101
- : (nameToNumber.get(button) ?? Number(button.substring(6)));
102
- }
103
- }