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
package/dist/engine.js CHANGED
@@ -1,116 +1,99 @@
1
- import { Audio } from './core/audio';
2
- import { Input } from './core/input';
3
- import { Timer } from './core/timer';
4
- import { Keyboard } from './core/keyboard';
5
- import { Mouse } from './core/mouse';
6
- import { Gamepad } from './core/gamepad';
7
- import { newState, bindGraphics } from './core/graphics';
8
- import { CanvasManager } from './core/canvas-manager';
1
+ /**
2
+ * @module engine
3
+ * @description Core game engine - lifecycle management and event dispatch.
4
+ *
5
+ * You've reached the most evil part of the codebase -- the man
6
+ * behind the curtain.
7
+ *
8
+ * The secret force gluing everything together.
9
+ *
10
+ * If you want to use modules independently, look here first.
11
+ *
12
+ * ## Memory Management
13
+ *
14
+ * Always call `dispose()` when destroying an engine instance:
15
+ * - Removes all event listeners
16
+ * - Stops the game loop
17
+ * - Removes canvas from DOM
18
+ * - Cleans up canvas manager resources
19
+ *
20
+ */
21
+ import { AudioInternal } from './core/audio';
22
+ import { InputInternal } from './core/input';
23
+ import { TimerInternal } from './core/timer';
24
+ import { KeyboardInternal } from './core/keyboard';
25
+ import { MouseInternal } from './core/mouse';
26
+ import { GamepadInternal } from './core/gamepad';
27
+ import { bindGraphics } from './core/graphics';
28
+ import { CanvasInternal } from './core/canvas';
29
+ import { sceneDispatch } from './scene';
30
+ /**
31
+ * Core game engine managing the event loop and subsystems.
32
+ *
33
+ * Normally you don't instantiate this directly - use {@link createLike} instead.
34
+ * The Engine class is exposed for advanced use cases like testing or
35
+ * custom initialization sequences.
36
+ *
37
+ * All subsystems are accessible via the {@link like} property.
38
+ */
9
39
  export class Engine {
10
40
  constructor(container) {
11
- Object.defineProperty(this, "canvas", {
12
- enumerable: true,
13
- configurable: true,
14
- writable: true,
15
- value: void 0
16
- });
17
- Object.defineProperty(this, "isRunning", {
18
- enumerable: true,
19
- configurable: true,
20
- writable: true,
21
- value: false
22
- });
23
- Object.defineProperty(this, "lastTime", {
24
- enumerable: true,
25
- configurable: true,
26
- writable: true,
27
- value: 0
28
- });
29
41
  Object.defineProperty(this, "container", {
30
42
  enumerable: true,
31
43
  configurable: true,
32
44
  writable: true,
33
- value: void 0
34
- });
35
- Object.defineProperty(this, "canvasManager", {
36
- enumerable: true,
37
- configurable: true,
38
- writable: true,
39
- value: void 0
40
- });
41
- Object.defineProperty(this, "handleEvent", {
42
- enumerable: true,
43
- configurable: true,
44
- writable: true,
45
- value: null
45
+ value: container
46
46
  });
47
- Object.defineProperty(this, "currentScene", {
48
- enumerable: true,
49
- configurable: true,
50
- writable: true,
51
- value: null
52
- });
53
- Object.defineProperty(this, "gfxState", {
47
+ Object.defineProperty(this, "canvas", {
54
48
  enumerable: true,
55
49
  configurable: true,
56
50
  writable: true,
57
51
  value: void 0
58
52
  });
59
- // Event handler references for cleanup
60
- Object.defineProperty(this, "windowFocusHandler", {
61
- enumerable: true,
62
- configurable: true,
63
- writable: true,
64
- value: null
65
- });
66
- Object.defineProperty(this, "windowBlurHandler", {
67
- enumerable: true,
68
- configurable: true,
69
- writable: true,
70
- value: null
71
- });
72
- Object.defineProperty(this, "canvasFocusHandler", {
53
+ Object.defineProperty(this, "isRunning", {
73
54
  enumerable: true,
74
55
  configurable: true,
75
56
  writable: true,
76
- value: null
57
+ value: false
77
58
  });
78
- Object.defineProperty(this, "canvasBlurHandler", {
59
+ Object.defineProperty(this, "lastTime", {
79
60
  enumerable: true,
80
61
  configurable: true,
81
62
  writable: true,
82
- value: null
63
+ value: 0
83
64
  });
84
- Object.defineProperty(this, "fullscreenChangeHandler", {
65
+ Object.defineProperty(this, "abort", {
85
66
  enumerable: true,
86
67
  configurable: true,
87
68
  writable: true,
88
- value: null
69
+ value: new AbortController()
89
70
  });
71
+ /**
72
+ * The Like interface providing access to all engine subsystems.
73
+ * This object is passed to all scene callbacks and game code.
74
+ */
90
75
  Object.defineProperty(this, "like", {
91
76
  enumerable: true,
92
77
  configurable: true,
93
78
  writable: true,
94
79
  value: void 0
95
80
  });
96
- this.canvas = document.createElement('canvas');
97
- this.canvas.style.border = '1px solid #ccc';
98
- this.canvas.style.display = 'block';
99
- const ctx = this.canvas.getContext('2d');
100
- if (!ctx)
101
- throw new Error('Failed to get 2D context');
102
- this.container = container;
103
- this.container.appendChild(this.canvas);
104
- this.canvasManager = new CanvasManager(this.canvas, this.container, ctx, { pixelResolution: null, fullscreen: false });
105
- const renderTarget = this.canvasManager.getRenderTarget();
106
- this.gfxState = newState(renderTarget.ctx);
107
- let gfx = bindGraphics(this.gfxState);
108
- const audio = new Audio();
109
- const timer = new Timer();
110
- const keyboard = new Keyboard(this.canvas);
111
- const mouse = new Mouse(this.canvas, (cssX, cssY) => this.canvasManager.transformMousePosition(cssX, cssY));
112
- const gamepad = new Gamepad();
113
- const input = new Input({ keyboard, mouse, gamepad });
81
+ this.canvas = new CanvasInternal(this.dispatch.bind(this));
82
+ const canvas = this.canvas._displayCanvas;
83
+ canvas.addEventListener("like:updateRenderTarget", (event) => {
84
+ if (!(event instanceof CustomEvent))
85
+ return;
86
+ this.like.gfx = bindGraphics(event.detail.target.getContext('2d'));
87
+ });
88
+ this.container.appendChild(canvas);
89
+ let gfx = bindGraphics(canvas.getContext('2d'));
90
+ const dispatch = this.dispatch.bind(this);
91
+ const audio = new AudioInternal();
92
+ const timer = new TimerInternal();
93
+ const keyboard = new KeyboardInternal(canvas, dispatch);
94
+ const mouse = new MouseInternal(canvas, dispatch);
95
+ const gamepad = new GamepadInternal(dispatch);
96
+ const input = new InputInternal({ keyboard, mouse, gamepad });
114
97
  this.like = {
115
98
  audio,
116
99
  timer,
@@ -119,76 +102,50 @@ export class Engine {
119
102
  mouse,
120
103
  gamepad,
121
104
  gfx,
122
- setMode: (m) => this.setMode(m),
123
- getMode: () => this.canvasManager.getMode(),
124
- getCanvasSize: () => this.canvasManager.getCanvasSize(),
105
+ canvas: this.canvas,
106
+ start: this.start.bind(this),
107
+ dispose: this.dispose.bind(this),
125
108
  setScene: (scene) => {
126
- this.currentScene = scene;
127
- scene?.load?.(this.like);
109
+ if (scene) {
110
+ this.like.handleEvent = (event) => sceneDispatch(scene, this.like, event);
111
+ this.dispatch("load", []);
112
+ }
113
+ else {
114
+ this.like.handleEvent = undefined;
115
+ }
128
116
  },
129
- };
130
- this.canvasManager.onResize = () => {
131
- const target = this.canvasManager.getRenderTarget();
132
- this.gfxState = newState(target.ctx);
133
- this.like.gfx = bindGraphics(this.gfxState);
134
- };
135
- keyboard.onKeyEvent = (scancode, keycode, type) => {
136
- this.dispatch(type === 'keydown' ? 'keypressed' : 'keyreleased', [scancode, keycode]);
137
- };
138
- mouse.onMouseMove = (pos, relative) => {
139
- this.dispatch('mousemoved', [pos, relative]);
140
- };
141
- mouse.onMouseDown = (pos, button) => {
142
- this.dispatch('mousepressed', [pos, button]);
143
- };
144
- mouse.onMouseUp = (pos, button) => {
145
- this.dispatch('mousereleased', [pos, button]);
146
- };
147
- gamepad.onButtonEvent = (gpIndex, buttonIndex, buttonName, pressed) => {
148
- this.dispatch(pressed ? 'gamepadpressed' : 'gamepadreleased', [gpIndex, buttonIndex, buttonName]);
149
- };
150
- this.windowFocusHandler = () => this.dispatch('focus', []);
151
- this.windowBlurHandler = () => this.dispatch('blur', []);
152
- this.canvasFocusHandler = () => this.dispatch('focus', []);
153
- this.canvasBlurHandler = () => this.dispatch('blur', []);
154
- this.fullscreenChangeHandler = () => {
155
- const mode = this.canvasManager.getMode();
156
- const isFullscreen = !!document.fullscreenElement;
157
- if (mode.fullscreen !== isFullscreen) {
158
- this.canvasManager.setMode({ ...mode, fullscreen: isFullscreen });
117
+ callOwnHandlers: (event) => {
118
+ if (event.type in this.like)
119
+ this.like[event.type](...event.args);
159
120
  }
160
121
  };
161
- window.addEventListener('focus', this.windowFocusHandler);
162
- window.addEventListener('blur', this.windowBlurHandler);
163
- this.canvas.addEventListener('focus', this.canvasFocusHandler);
164
- this.canvas.addEventListener('blur', this.canvasBlurHandler);
165
- document.addEventListener('fullscreenchange', this.fullscreenChangeHandler);
122
+ window.addEventListener('focus', () => this.dispatch('focus', ['tab']));
123
+ window.addEventListener('blur', () => this.dispatch('blur', ['tab']));
124
+ canvas.addEventListener('focus', () => this.dispatch('focus', ['canvas']));
125
+ canvas.addEventListener('focus', () => this.dispatch('focus', ['canvas']));
166
126
  }
167
127
  dispatch(type, args) {
168
- if (!this.handleEvent)
169
- return;
170
- const event = { type, args, timestamp: performance.now() };
171
- if (this.currentScene) {
172
- this.currentScene.handleEvent?.(this.like, event);
173
- const method = this.currentScene[event.type];
174
- method?.call(this.currentScene, this.like, ...args);
128
+ const event = { type, args, timestamp: this.like.timer.getTime() };
129
+ if (this.like.handleEvent) {
130
+ this.like.handleEvent(event);
175
131
  }
176
132
  else {
177
- this.handleEvent(event);
178
- }
179
- }
180
- setMode(mode) {
181
- const currentMode = this.canvasManager.getMode();
182
- if ('fullscreen' in mode && mode.fullscreen !== currentMode.fullscreen) {
183
- mode.fullscreen ? this.container.requestFullscreen().catch(console.error) : document.exitFullscreen();
133
+ this.like.callOwnHandlers(event);
184
134
  }
185
- this.canvasManager.setMode({ ...currentMode, ...mode });
186
135
  }
187
- async start(handleEvent) {
188
- this.handleEvent = handleEvent;
136
+ /**
137
+ * Start the game loop.
138
+ *
139
+ * @remarks
140
+ * This method:
141
+ * 1. Dispatches the initial `load` event
142
+ * 2. Starts the requestAnimationFrame loop
143
+ *
144
+ * The engine runs until dispose() is called.
145
+ */
146
+ async start() {
189
147
  this.isRunning = true;
190
148
  this.lastTime = performance.now();
191
- await this.like.gamepad.init();
192
149
  const loop = () => {
193
150
  if (!this.isRunning)
194
151
  return;
@@ -196,37 +153,41 @@ export class Engine {
196
153
  const dt = (now - this.lastTime) / 1000;
197
154
  this.lastTime = now;
198
155
  if (!this.like.timer.isSleeping()) {
199
- this.like.timer.update(dt);
200
- const { pressed, released } = this.like.input.update();
156
+ this.like.timer._update(dt);
157
+ const { pressed, released } = this.like.input._update();
201
158
  pressed.forEach(action => this.dispatch('actionpressed', [action]));
202
159
  released.forEach(action => this.dispatch('actionreleased', [action]));
203
160
  this.dispatch('update', [dt]);
204
161
  }
205
162
  this.dispatch('draw', []);
206
- this.canvasManager.present();
163
+ this.canvas._present();
207
164
  requestAnimationFrame(loop);
208
165
  };
209
166
  this.dispatch('load', []);
210
167
  requestAnimationFrame(loop);
211
168
  }
169
+ /**
170
+ * Clean up all resources and stop the engine.
171
+ *
172
+ * @remarks
173
+ * This method:
174
+ * - Stops the game loop
175
+ * - Removes all event listeners (keyboard, mouse, window, fullscreen)
176
+ * - Disposes canvas manager (removes resize observer)
177
+ * - Removes the canvas element from the DOM
178
+ *
179
+ * The engine cannot be restarted after disposal - create a new instance.
180
+ */
212
181
  dispose() {
182
+ const canvas = this.canvas._displayCanvas;
213
183
  this.isRunning = false;
214
- this.like.keyboard.dispose();
215
- this.like.mouse.dispose();
216
- this.like.gamepad.dispose();
217
- this.canvasManager.dispose();
218
- if (this.windowFocusHandler)
219
- window.removeEventListener('focus', this.windowFocusHandler);
220
- if (this.windowBlurHandler)
221
- window.removeEventListener('blur', this.windowBlurHandler);
222
- if (this.canvasFocusHandler)
223
- this.canvas.removeEventListener('focus', this.canvasFocusHandler);
224
- if (this.canvasBlurHandler)
225
- this.canvas.removeEventListener('blur', this.canvasBlurHandler);
226
- if (this.fullscreenChangeHandler)
227
- document.removeEventListener('fullscreenchange', this.fullscreenChangeHandler);
228
- if (this.canvas.parentNode === this.container) {
229
- this.container.removeChild(this.canvas);
184
+ this.like.keyboard._dispose();
185
+ this.like.mouse._dispose();
186
+ this.like.gamepad._dispose();
187
+ this.canvas._dispose();
188
+ this.abort.abort();
189
+ if (canvas.parentNode === this.container) {
190
+ this.container.removeChild(canvas);
230
191
  }
231
192
  }
232
193
  }
package/dist/index.d.ts CHANGED
@@ -1,25 +1,46 @@
1
- import type { EventMap, EventType } from './core/events';
1
+ /**
2
+ * @module like2d
3
+ * @description A cozy web-native 2D game framework.
4
+ *
5
+ * See main like/README.md file an for overview of Like2D.
6
+ */
7
+ import type { LikeEvent } from './core/events';
2
8
  import type { Like } from './core/like';
3
9
  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 type { LikeEvent, EventType, EventMap } from './core/events';
11
+ export type { CanvasSize, CanvasModeOptions as CanvasModeFlags } from './core/canvas';
12
+ export type { Color, ShapeProps, DrawProps, PrintProps } from './core/graphics';
10
13
  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;
14
+ export type { AudioSource, AudioSourceOptions } from './core/audio';
15
+ export { type LikeButton } from './core/gamepad';
16
+ export type TopLevelEventHandler = (event: LikeEvent) => void;
17
+ /**
18
+ * Create a new Like2D game instance attached to a DOM container.
19
+ *
20
+ * This is the entry point for all Like2D games. It creates a canvas element,
21
+ * initializes all subsystems (graphics, audio, input), and returns an object
22
+ * where you can assign game callbacks.
23
+ *
24
+ * ### How to bind callbacks
25
+ *
26
+ * ```ts
27
+ * export const like = createLike();
28
+ *
29
+ * like.start();
30
+ *
31
+ * like.draw = () => { like.gfx.clear('yellow') }
32
+ *
33
+ * like.update = function (dt: number) {
34
+ * if (dt === Math.random()) {
35
+ * console.log("You just won the Powerball!")
36
+ * }
37
+ * }
38
+ * ```
39
+ *
40
+ * @param container - The HTML element to attach the game canvas to.
41
+ * Must be in the DOM.
42
+ * @returns A {@link Like} instance ready for callback assignment
43
+ *
44
+ */
45
+ export declare function createLike(container: HTMLElement): Like;
25
46
  //# 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;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,YAAY,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACpE,YAAY,EAAE,UAAU,EAAE,iBAAiB,IAAI,eAAe,EAAE,MAAM,eAAe,CAAC;AACtF,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI,CAGvD"}
package/dist/index.js CHANGED
@@ -1,19 +1,40 @@
1
+ /**
2
+ * @module like2d
3
+ * @description A cozy web-native 2D game framework.
4
+ *
5
+ * See main like/README.md file an for overview of Like2D.
6
+ */
1
7
  import { Engine } from './engine';
2
- export { Vec2 } from './core/vector2';
3
- export { Rect } from './core/rect';
4
8
  export { ImageHandle } from './core/graphics';
5
- export { StartupScene } from './scenes/startup';
6
- export { getGPName, GP } from './core/gamepad';
9
+ /**
10
+ * Create a new Like2D game instance attached to a DOM container.
11
+ *
12
+ * This is the entry point for all Like2D games. It creates a canvas element,
13
+ * initializes all subsystems (graphics, audio, input), and returns an object
14
+ * where you can assign game callbacks.
15
+ *
16
+ * ### How to bind callbacks
17
+ *
18
+ * ```ts
19
+ * export const like = createLike();
20
+ *
21
+ * like.start();
22
+ *
23
+ * like.draw = () => { like.gfx.clear('yellow') }
24
+ *
25
+ * like.update = function (dt: number) {
26
+ * if (dt === Math.random()) {
27
+ * console.log("You just won the Powerball!")
28
+ * }
29
+ * }
30
+ * ```
31
+ *
32
+ * @param container - The HTML element to attach the game canvas to.
33
+ * Must be in the DOM.
34
+ * @returns A {@link Like} instance ready for callback assignment
35
+ *
36
+ */
7
37
  export function createLike(container) {
8
38
  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
- });
39
+ return engine.like;
19
40
  }
@@ -0,0 +1,2 @@
1
+ export declare const mod: (a: number, b: number) => number;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/math/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,GAAG,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,WAAsB,CAAC"}
@@ -0,0 +1 @@
1
+ export const mod = (a, b) => ((a % b) + b) % b;
@@ -0,0 +1,71 @@
1
+ import { type Vector2 } from '../math/vector2';
2
+ /**
3
+ * A four-coordinate type `[x, y, width, height]`.
4
+ * Full reference {@link Rect}.
5
+ *
6
+ * ## Examples
7
+ *
8
+ * ### Construct a rectangle
9
+ * ```ts
10
+ * const beastPen: Rectangle = [20, 25, 40, 50];
11
+ * ```
12
+ *
13
+ * ### Construct around a center point and size
14
+ * ```ts
15
+ * const beastPen: Rectangle = Rect.setCenter(
16
+ * [0, 0, ...penSize],
17
+ * beastPos
18
+ * );
19
+ * ```
20
+ * ### Deconstruct a rect
21
+ * ```ts
22
+ * [x, y, w, h] = beastPen;
23
+ * ```
24
+ * ### Deconstruct into points
25
+ * ```ts
26
+ * const penPos = Rect.position(beastPen);
27
+ * const penSize = Rect.size(beastPen);
28
+ * ```
29
+ *
30
+ * ### Check if beast is in his pen
31
+ * ```ts
32
+ * const isInPen = Rect.containsPoint(
33
+ * beastPen,
34
+ * beast.pos,
35
+ * )
36
+ * ```
37
+ * ### Put the beast back in his pen
38
+ * ```ts
39
+ * beast.pos = Rect.clampPoint(beast.pos, beastPen)
40
+ * ```
41
+ *
42
+ * */
43
+ export type Rectangle = [number, number, number, number];
44
+ /**
45
+ * A set of
46
+ */
47
+ export declare namespace Rect {
48
+ function fromPoints(a: Vector2, b: Vector2): Rectangle;
49
+ function fromCenter(center: Vector2, size: Vector2): Rectangle;
50
+ function position(r: Rectangle): Vector2;
51
+ function size(r: Rectangle): Vector2;
52
+ function center(r: Rectangle): Vector2;
53
+ function topLeft(r: Rectangle): Vector2;
54
+ function topRight(r: Rectangle): Vector2;
55
+ function bottomLeft(r: Rectangle): Vector2;
56
+ function bottomRight(r: Rectangle): Vector2;
57
+ function area(r: Rectangle): number;
58
+ function isEmpty(r: Rectangle): boolean;
59
+ function clampPoint(r: Rectangle, point: Vector2): Vector2;
60
+ function containsPoint(r: Rectangle, point: Vector2): boolean;
61
+ function containsRect(r: Rectangle, other: Rectangle): boolean;
62
+ function intersects(r: Rectangle, other: Rectangle): boolean;
63
+ function intersection(r: Rectangle, other: Rectangle): Rectangle;
64
+ function union(r: Rectangle, other: Rectangle): Rectangle;
65
+ function inflate(r: Rectangle, amount: number): Rectangle;
66
+ function offset(r: Rectangle, delta: Vector2): Rectangle;
67
+ function setPosition(r: Rectangle, pos: Vector2): Rectangle;
68
+ function setSize(r: Rectangle, size: Vector2): Rectangle;
69
+ function setCenter(r: Rectangle, center: Vector2): Rectangle;
70
+ }
71
+ //# sourceMappingURL=rect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rect.d.ts","sourceRoot":"","sources":["../../src/math/rect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAwCK;AACL,MAAM,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEzD;;GAEG;AACH,yBAAiB,IAAI,CAAC;IACpB,SAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,SAAS,CAM5D;IAED,SAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,CAOpE;IAED,SAAgB,QAAQ,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAE9C;IAED,SAAgB,IAAI,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAE1C;IAED,SAAgB,MAAM,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAE5C;IAED,SAAgB,OAAO,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAE7C;IAED,SAAgB,QAAQ,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAE9C;IAED,SAAgB,UAAU,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAEhD;IAED,SAAgB,WAAW,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAEjD;IAED,SAAgB,IAAI,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAEzC;IAED,SAAgB,OAAO,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAE7C;IAED,SAAgB,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAEhE;IAED,SAAgB,aAAa,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAOnE;IAED,SAAgB,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAOpE;IAED,SAAgB,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAOlE;IAED,SAAgB,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,SAAS,CAWtE;IAED,SAAgB,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,SAAS,CAM/D;IAED,SAAgB,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAO/D;IAED,SAAgB,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,SAAS,CAE9D;IAED,SAAgB,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,GAAG,SAAS,CAEjE;IAED,SAAgB,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,CAE9D;IAED,SAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAG,SAAS,CAOlE;CACF"}
@@ -1,3 +1,7 @@
1
+ import { Vec2 } from '../math/vector2';
2
+ /**
3
+ * A set of
4
+ */
1
5
  export var Rect;
2
6
  (function (Rect) {
3
7
  function fromPoints(a, b) {
@@ -53,6 +57,10 @@ export var Rect;
53
57
  return r[2] <= 0 || r[3] <= 0;
54
58
  }
55
59
  Rect.isEmpty = isEmpty;
60
+ function clampPoint(r, point) {
61
+ return Vec2.clamp(point, Rect.position(r), Rect.bottomRight(r));
62
+ }
63
+ Rect.clampPoint = clampPoint;
56
64
  function containsPoint(r, point) {
57
65
  return (point[0] >= r[0] &&
58
66
  point[0] <= r[0] + r[2] &&