like2d 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +67 -43
  3. package/dist/adapters/callback/index.d.ts +43 -0
  4. package/dist/adapters/callback/index.d.ts.map +1 -0
  5. package/dist/adapters/callback/index.js +80 -0
  6. package/dist/adapters/scene/index.d.ts +42 -0
  7. package/dist/adapters/scene/index.d.ts.map +1 -0
  8. package/dist/adapters/scene/index.js +112 -0
  9. package/dist/adapters/scene/scene.d.ts +18 -0
  10. package/dist/adapters/scene/scene.d.ts.map +1 -0
  11. package/dist/adapters/scene/startup-scene.d.ts +17 -0
  12. package/dist/adapters/scene/startup-scene.d.ts.map +1 -0
  13. package/dist/adapters/scene/startup-scene.js +41 -0
  14. package/dist/core/audio.d.ts +61 -0
  15. package/dist/core/audio.d.ts.map +1 -0
  16. package/dist/core/audio.js +226 -0
  17. package/dist/core/canvas-config.d.ts +22 -0
  18. package/dist/core/canvas-config.d.ts.map +1 -0
  19. package/dist/core/canvas-config.js +14 -0
  20. package/dist/core/canvas-manager.d.ts +26 -0
  21. package/dist/core/canvas-manager.d.ts.map +1 -0
  22. package/dist/core/canvas-manager.js +197 -0
  23. package/dist/core/events.d.ts +52 -0
  24. package/dist/core/events.d.ts.map +1 -0
  25. package/dist/core/gamepad-button-map.d.ts.map +1 -0
  26. package/dist/core/gamepad-buttons.d.ts +23 -0
  27. package/dist/core/gamepad-buttons.d.ts.map +1 -0
  28. package/dist/core/gamepad-buttons.js +36 -0
  29. package/dist/core/gamepad-db.d.ts.map +1 -0
  30. package/dist/{gamepad-mapping.d.ts → core/gamepad-mapping.d.ts} +3 -15
  31. package/dist/core/gamepad-mapping.d.ts.map +1 -0
  32. package/dist/core/gamepad-mapping.js +223 -0
  33. package/dist/{gamepad.d.ts → core/gamepad.d.ts} +22 -17
  34. package/dist/core/gamepad.d.ts.map +1 -0
  35. package/dist/{gamepad.js → core/gamepad.js} +91 -70
  36. package/dist/{graphics.d.ts → core/graphics.d.ts} +2 -8
  37. package/dist/core/graphics.d.ts.map +1 -0
  38. package/dist/{graphics.js → core/graphics.js} +4 -41
  39. package/dist/core/input-state.d.ts.map +1 -0
  40. package/dist/{input.d.ts → core/input.d.ts} +11 -14
  41. package/dist/core/input.d.ts.map +1 -0
  42. package/dist/{input.js → core/input.js} +31 -41
  43. package/dist/core/keyboard.d.ts +15 -0
  44. package/dist/core/keyboard.d.ts.map +1 -0
  45. package/dist/core/keyboard.js +70 -0
  46. package/dist/core/mouse.d.ts +29 -0
  47. package/dist/core/mouse.d.ts.map +1 -0
  48. package/dist/core/mouse.js +130 -0
  49. package/dist/{rect.d.ts → core/rect.d.ts} +1 -2
  50. package/dist/core/rect.d.ts.map +1 -0
  51. package/dist/{rect.js → core/rect.js} +24 -28
  52. package/dist/{timer.d.ts → core/timer.d.ts} +0 -1
  53. package/dist/core/timer.d.ts.map +1 -0
  54. package/dist/{timer.js → core/timer.js} +0 -1
  55. package/dist/{vector2.d.ts → core/vector2.d.ts} +4 -10
  56. package/dist/core/vector2.d.ts.map +1 -0
  57. package/dist/{vector2.js → core/vector2.js} +40 -40
  58. package/dist/engine.d.ts +42 -0
  59. package/dist/engine.d.ts.map +1 -0
  60. package/dist/engine.js +154 -0
  61. package/dist/index.d.ts +38 -44
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +24 -250
  64. package/package.json +8 -23
  65. package/dist/audio.d.ts +0 -52
  66. package/dist/audio.d.ts.map +0 -1
  67. package/dist/audio.js +0 -250
  68. package/dist/events.d.ts +0 -36
  69. package/dist/events.d.ts.map +0 -1
  70. package/dist/gamepad-button-map.d.ts.map +0 -1
  71. package/dist/gamepad-db.d.ts.map +0 -1
  72. package/dist/gamepad-mapping.d.ts.map +0 -1
  73. package/dist/gamepad-mapping.js +0 -191
  74. package/dist/gamepad.d.ts.map +0 -1
  75. package/dist/graphics.d.ts.map +0 -1
  76. package/dist/input-state.d.ts.map +0 -1
  77. package/dist/input.d.ts.map +0 -1
  78. package/dist/keyboard.d.ts +0 -9
  79. package/dist/keyboard.d.ts.map +0 -1
  80. package/dist/keyboard.js +0 -33
  81. package/dist/mouse.d.ts +0 -20
  82. package/dist/mouse.d.ts.map +0 -1
  83. package/dist/mouse.js +0 -84
  84. package/dist/rect.d.ts.map +0 -1
  85. package/dist/scene.d.ts +0 -10
  86. package/dist/scene.d.ts.map +0 -1
  87. package/dist/timer.d.ts.map +0 -1
  88. package/dist/vector2.d.ts.map +0 -1
  89. /package/dist/{scene.js → adapters/scene/scene.js} +0 -0
  90. /package/dist/{events.js → core/events.js} +0 -0
  91. /package/dist/{gamepad-button-map.d.ts → core/gamepad-button-map.d.ts} +0 -0
  92. /package/dist/{gamepad-button-map.js → core/gamepad-button-map.js} +0 -0
  93. /package/dist/{gamepad-db.d.ts → core/gamepad-db.d.ts} +0 -0
  94. /package/dist/{gamepad-db.js → core/gamepad-db.js} +0 -0
  95. /package/dist/{input-state.d.ts → core/input-state.d.ts} +0 -0
  96. /package/dist/{input-state.js → core/input-state.js} +0 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Samuel Pagenkopf
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md CHANGED
@@ -1,66 +1,90 @@
1
- # LÏKE2D Framework Library
1
+ # LÏKE2D
2
2
 
3
- You've reached the more detailed docs for this framework.
4
- For now, the source code is the best API docs we have.
3
+ A web-native 2D game framework inspired by [LÖVE](https://love2d.org/), built for simplicity and the modern web.
5
4
 
6
- ## Features of LIKE
5
+ ## What it is
7
6
 
8
- **Stateless Canvas API**
7
+ Like2D is a thin, performant wrapper around the browser's Canvas and Web Audio APIs. It provides:
8
+ - **Stateless Graphics:** No more `ctx.save()` and `ctx.restore()` for colors and transforms.
9
+ - **Fire-and-forget Assets:** Synchronous handles for images and audio that load in the background.
10
+ - **Unified Input:** Normalized keyboard, mouse, and gamepad support with action mapping.
11
+ - **Scaling Modes:** Built-in support for "fixed" resolution with pixel-perfect stretching.
12
+ - **Flexible Patterns:** Use Love2D-style global callbacks or class-based scenes.
9
13
 
10
- JS canvas has state to keep track of like color and line width.
11
- LIKE abstracts that away so it's easy to reason about.
14
+ ## Installation
12
15
 
13
- **Fire-and-forget asset loading**
16
+ ```bash
17
+ npm install like2d
18
+ # or
19
+ pnpm add like2d
20
+ ```
14
21
 
15
- Loading sound and images in Vanilla JS is clunky and can interrupt your game loop.
16
- LIKE has synchronous asset handles and abstracts away the clunkiness.
22
+ ## Quick Start
17
23
 
18
- **Zero boilerplate, physical game input**
24
+ ### Callback Pattern (Love2D-style)
19
25
 
20
- LIKE does the input boilerplate for you.
21
- - Keeping track of what's held/pressed.
22
- - Controller mapping by physical location. Not every A is in the same spot.
23
- - Mapping inputs into actions for easy remapping.
26
+ Ideal for small games, jams, or prototyping.
24
27
 
25
- **Declarative event system**
28
+ ```typescript
29
+ import { love, graphics, input } from 'like2d/callback';
26
30
 
27
- Don't bother juggling stateful listeners.
28
- LIKE keeps event handling simple by running it all through a single callback.
31
+ love.load = () => {
32
+ love.setScaling({ mode: 'fixed', size: [800, 600] });
33
+ input.map('jump', ['Space', 'ButtonBottom']);
34
+ };
29
35
 
30
- **Build it how you want it**
36
+ love.update = (dt) => {
37
+ if (input.justPressed('jump')) {
38
+ console.log('Jump!');
39
+ }
40
+ };
31
41
 
32
- It's not an engine, it's a framework.
33
- For new developers, this means making simple games easily: no engine, no problem!
34
- For others, get to work faster making your own specialized tooling, engine, and more,
35
- all without banging your head on browser APIs.
42
+ love.draw = () => {
43
+ graphics.clear([0.1, 0.1, 0.1, 1]);
44
+ graphics.circle('fill', 'dodgerblue', [400, 300], 50);
45
+ graphics.print('white', 'Hello Like2D!', [20, 20]);
46
+ };
36
47
 
37
- ## Getting started
48
+ love.init(document.body);
49
+ ```
38
50
 
39
- TODO: fill this in.
51
+ ### Scene Pattern (Class-based)
40
52
 
41
- Then run:
42
- ```bash
43
- pnpm install
44
- pnpm run dev
45
- ```
53
+ Ideal for larger projects with menus, levels, and explicit state management.
46
54
 
47
- ## For LOVE developers
55
+ ```typescript
56
+ import { SceneRunner, type Scene, Vec2 } from 'like2d/scene';
48
57
 
49
- LIKE is not compatible with LOVE.
58
+ class MyScene implements Scene {
59
+ load() {
60
+ console.log('Scene loaded!');
61
+ }
62
+
63
+ update(dt: number) {
64
+ // update logic
65
+ }
66
+
67
+ draw(canvas: HTMLCanvasElement) {
68
+ // draw logic
69
+ }
70
+ }
71
+
72
+ const runner = new SceneRunner(document.body);
73
+ await runner.start(new MyScene());
74
+ ```
50
75
 
51
- To summarize the differences:
52
- - We don't keep track of color etc. as state (via setColor, etc.), so it gets passed in each draw call.
53
- - We use objects for optional arguments, and avoid function overloading.
54
- - We make use of tuples for passing around colors, coordinates, and rects.
55
- - In LOVE, Callbacks such as `love.keypressed` needed to be wrapped in order to make Scenes. This pattern is part of LIKE.
56
- - 2d Canvas so, no shaders.
57
- - No built-in physics.
76
+ ## API Overview
58
77
 
59
- ## Full Disclosure about AI
78
+ Like2D exports pure library functions for math and geometry that work with native arrays.
60
79
 
61
- Yes, this framework was created with the help of heavily supervised AI.
80
+ - **Vec2:** Vector operations using `[number, number]` tuples.
81
+ - **Rect:** Rectangle operations using `[x, y, w, h]` tuples.
82
+ - **Graphics:** Stateless drawing commands.
83
+ - **Audio:** Simple source/playback management.
84
+ - **Input:** Action-based input mapping.
62
85
 
63
- Virtually every design decision was made by me, and I have micro-managed the code output.
86
+ See the [PHILOSOPHY.md](./docs/PHILOSOPHY.md) for the principles behind the design.
64
87
 
65
- Over time, I will rewrite parts of it by hand as desired. Possibly the whole thing.
88
+ ## License
66
89
 
90
+ MIT
@@ -0,0 +1,43 @@
1
+ import { Graphics } from '../../core/graphics';
2
+ import { Audio } from '../../core/audio';
3
+ import { Input } from '../../core/input';
4
+ import { Timer } from '../../core/timer';
5
+ import { Keyboard } from '../../core/keyboard';
6
+ import { Mouse } from '../../core/mouse';
7
+ import { Gamepad } from '../../core/gamepad';
8
+ import type { CanvasConfig } from '../../core/canvas-config';
9
+ import type { Like2DEvent } from '../../core/events';
10
+ import type { Vector2 } from '../../core/vector2';
11
+ export { ImageHandle } from '../../core/graphics';
12
+ export { getGPName, GP } from '../../core/gamepad';
13
+ export { Vec2 } from '../../core/vector2';
14
+ export { Rect } from '../../core/rect';
15
+ export { calcFixedScale } from '../../core/canvas-config';
16
+ export declare let graphics: Graphics;
17
+ export declare const audio: Audio;
18
+ export declare const timer: Timer;
19
+ export declare let keyboard: Keyboard;
20
+ export declare let mouse: Mouse;
21
+ export declare let gamepad: Gamepad;
22
+ export declare let input: Input;
23
+ export declare const like: {
24
+ load: (() => void) | undefined;
25
+ update: ((dt: number) => void) | undefined;
26
+ draw: ((canvas: HTMLCanvasElement) => void) | undefined;
27
+ resize: ((size: Vector2, pixelSize: Vector2, fullscreen: boolean) => void) | undefined;
28
+ keypressed: ((scancode: string, keycode: string) => void) | undefined;
29
+ keyreleased: ((scancode: string, keycode: string) => void) | undefined;
30
+ mousepressed: ((x: number, y: number, button: number) => void) | undefined;
31
+ mousereleased: ((x: number, y: number, button: number) => void) | undefined;
32
+ gamepadpressed: ((i: number, b: number, n: string) => void) | undefined;
33
+ gamepadreleased: ((i: number, b: number, n: string) => void) | undefined;
34
+ actionpressed: ((action: string) => void) | undefined;
35
+ actionreleased: ((action: string) => void) | undefined;
36
+ handleEvent: ((event: Like2DEvent) => void) | undefined;
37
+ toggleFullscreen(): void;
38
+ setScaling(config: CanvasConfig): void;
39
+ init(container: HTMLElement): Promise<void>;
40
+ dispose(): void;
41
+ };
42
+ export { like as love };
43
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/callback/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,eAAO,IAAI,QAAQ,EAAE,QAAQ,CAAC;AAC9B,eAAO,MAAM,KAAK,OAAc,CAAC;AACjC,eAAO,MAAM,KAAK,OAAc,CAAC;AACjC,eAAO,IAAI,QAAQ,EAAE,QAAQ,CAAC;AAC9B,eAAO,IAAI,KAAK,EAAE,KAAK,CAAC;AACxB,eAAO,IAAI,OAAO,EAAE,OAAO,CAAC;AAC5B,eAAO,IAAI,KAAK,EAAE,KAAK,CAAC;AAIxB,eAAO,MAAM,IAAI;UACI,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS;YACtB,CAAC,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS;UACpC,CAAC,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC,GAAG,SAAS;YAC/C,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS;gBAC1E,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS;iBACxD,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS;kBACxD,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS;mBAC3D,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS;oBAC3D,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS;qBACtD,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS;mBACzD,CAAC,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS;oBACrC,CAAC,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS;iBACzC,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,SAAS;wBAEhD,IAAI;uBAIL,YAAY,GAAG,IAAI;oBAIhB,WAAW;eAyBtB,IAAI;CAkBhB,CAAC;AAEF,OAAO,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC"}
@@ -0,0 +1,80 @@
1
+ import { Graphics } from '../../core/graphics';
2
+ import { Audio } from '../../core/audio';
3
+ import { Input } from '../../core/input';
4
+ import { Timer } from '../../core/timer';
5
+ import { Keyboard } from '../../core/keyboard';
6
+ import { Mouse } from '../../core/mouse';
7
+ import { Gamepad } from '../../core/gamepad';
8
+ import { Engine } from '../../engine';
9
+ export { ImageHandle } from '../../core/graphics';
10
+ export { getGPName, GP } from '../../core/gamepad';
11
+ export { Vec2 } from '../../core/vector2';
12
+ export { Rect } from '../../core/rect';
13
+ export { calcFixedScale } from '../../core/canvas-config';
14
+ export let graphics;
15
+ export const audio = new Audio();
16
+ export const timer = new Timer();
17
+ export let keyboard;
18
+ export let mouse;
19
+ export let gamepad;
20
+ export let input;
21
+ let engine = null;
22
+ export const like = {
23
+ load: undefined,
24
+ update: undefined,
25
+ draw: undefined,
26
+ resize: undefined,
27
+ keypressed: undefined,
28
+ keyreleased: undefined,
29
+ mousepressed: undefined,
30
+ mousereleased: undefined,
31
+ gamepadpressed: undefined,
32
+ gamepadreleased: undefined,
33
+ actionpressed: undefined,
34
+ actionreleased: undefined,
35
+ handleEvent: undefined,
36
+ toggleFullscreen() {
37
+ engine?.toggleFullscreen();
38
+ },
39
+ setScaling(config) {
40
+ engine?.setScaling(config);
41
+ },
42
+ async init(container) {
43
+ engine = new Engine(container);
44
+ graphics = new Graphics(engine.getContext());
45
+ keyboard = new Keyboard();
46
+ mouse = new Mouse((cssX, cssY) => engine.transformMousePosition(cssX, cssY));
47
+ gamepad = new Gamepad();
48
+ input = new Input({ keyboard, mouse, gamepad });
49
+ engine.setDeps({ graphics, input, timer, audio, keyboard, mouse, gamepad });
50
+ await gamepad.init();
51
+ engine.start((event) => {
52
+ // 1. handleEvent first
53
+ like.handleEvent?.(event);
54
+ // 2. Direct handlers
55
+ const handler = like[event.type];
56
+ if (handler) {
57
+ handler(...event.args);
58
+ }
59
+ });
60
+ },
61
+ dispose() {
62
+ engine?.stop();
63
+ engine?.dispose();
64
+ engine = null;
65
+ this.load = undefined;
66
+ this.update = undefined;
67
+ this.draw = undefined;
68
+ this.resize = undefined;
69
+ this.keypressed = undefined;
70
+ this.keyreleased = undefined;
71
+ this.mousepressed = undefined;
72
+ this.mousereleased = undefined;
73
+ this.gamepadpressed = undefined;
74
+ this.gamepadreleased = undefined;
75
+ this.actionpressed = undefined;
76
+ this.actionreleased = undefined;
77
+ this.handleEvent = undefined;
78
+ }
79
+ };
80
+ export { like as love };
@@ -0,0 +1,42 @@
1
+ import { Graphics } from '../../core/graphics';
2
+ import { Audio } from '../../core/audio';
3
+ import { Input } from '../../core/input';
4
+ import { Timer } from '../../core/timer';
5
+ import { Keyboard } from '../../core/keyboard';
6
+ import { Mouse } from '../../core/mouse';
7
+ import { Gamepad } from '../../core/gamepad';
8
+ import type { Scene } from './scene';
9
+ import type { CanvasConfig } from '../../core/canvas-config';
10
+ import { StartupScene } from './startup-scene';
11
+ export { Graphics, ImageHandle } from '../../core/graphics';
12
+ export { StartupScene };
13
+ export { Audio } from '../../core/audio';
14
+ export { Input } from '../../core/input';
15
+ export { Timer } from '../../core/timer';
16
+ export { Keyboard } from '../../core/keyboard';
17
+ export { Mouse } from '../../core/mouse';
18
+ export { Gamepad, getGPName, GP } from '../../core/gamepad';
19
+ export type { Like2DEvent as Event } from '../../core/events';
20
+ export type { Scene } from './scene';
21
+ export type { Vector2 } from '../../core/vector2';
22
+ export { Vec2 } from '../../core/vector2';
23
+ export { Rect } from '../../core/rect';
24
+ export type { CanvasConfig } from '../../core/canvas-config';
25
+ export { calcFixedScale } from '../../core/canvas-config';
26
+ export declare class SceneRunner {
27
+ private engine;
28
+ private scene;
29
+ readonly graphics: Graphics;
30
+ readonly audio: Audio;
31
+ readonly timer: Timer;
32
+ readonly input: Input;
33
+ readonly keyboard: Keyboard;
34
+ readonly mouse: Mouse;
35
+ readonly gamepad: Gamepad;
36
+ constructor(container: HTMLElement);
37
+ setScaling(config: CanvasConfig): void;
38
+ setScene(scene: Scene): void;
39
+ start(scene: Scene): Promise<void>;
40
+ dispose(): void;
41
+ }
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/scene/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAC5D,YAAY,EAAE,WAAW,IAAI,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC9D,YAAY,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,YAAY,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAsB;IAEnC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;gBAEd,SAAS,EAAE,WAAW;IAWlC,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAItC,QAAQ,CAAC,KAAK,EAAE,KAAK;IAKf,KAAK,CAAC,KAAK,EAAE,KAAK;IAiBxB,OAAO,IAAI,IAAI;CAKhB"}
@@ -0,0 +1,112 @@
1
+ import { Graphics } from '../../core/graphics';
2
+ import { Audio } from '../../core/audio';
3
+ import { Input } from '../../core/input';
4
+ import { Timer } from '../../core/timer';
5
+ import { Keyboard } from '../../core/keyboard';
6
+ import { Mouse } from '../../core/mouse';
7
+ import { Gamepad } from '../../core/gamepad';
8
+ import { Engine } from '../../engine';
9
+ import { StartupScene } from './startup-scene';
10
+ export { Graphics, ImageHandle } from '../../core/graphics';
11
+ export { StartupScene };
12
+ export { Audio } from '../../core/audio';
13
+ export { Input } from '../../core/input';
14
+ export { Timer } from '../../core/timer';
15
+ export { Keyboard } from '../../core/keyboard';
16
+ export { Mouse } from '../../core/mouse';
17
+ export { Gamepad, getGPName, GP } from '../../core/gamepad';
18
+ export { Vec2 } from '../../core/vector2';
19
+ export { Rect } from '../../core/rect';
20
+ export { calcFixedScale } from '../../core/canvas-config';
21
+ export class SceneRunner {
22
+ constructor(container) {
23
+ Object.defineProperty(this, "engine", {
24
+ enumerable: true,
25
+ configurable: true,
26
+ writable: true,
27
+ value: void 0
28
+ });
29
+ Object.defineProperty(this, "scene", {
30
+ enumerable: true,
31
+ configurable: true,
32
+ writable: true,
33
+ value: null
34
+ });
35
+ Object.defineProperty(this, "graphics", {
36
+ enumerable: true,
37
+ configurable: true,
38
+ writable: true,
39
+ value: void 0
40
+ });
41
+ Object.defineProperty(this, "audio", {
42
+ enumerable: true,
43
+ configurable: true,
44
+ writable: true,
45
+ value: void 0
46
+ });
47
+ Object.defineProperty(this, "timer", {
48
+ enumerable: true,
49
+ configurable: true,
50
+ writable: true,
51
+ value: void 0
52
+ });
53
+ Object.defineProperty(this, "input", {
54
+ enumerable: true,
55
+ configurable: true,
56
+ writable: true,
57
+ value: void 0
58
+ });
59
+ Object.defineProperty(this, "keyboard", {
60
+ enumerable: true,
61
+ configurable: true,
62
+ writable: true,
63
+ value: void 0
64
+ });
65
+ Object.defineProperty(this, "mouse", {
66
+ enumerable: true,
67
+ configurable: true,
68
+ writable: true,
69
+ value: void 0
70
+ });
71
+ Object.defineProperty(this, "gamepad", {
72
+ enumerable: true,
73
+ configurable: true,
74
+ writable: true,
75
+ value: void 0
76
+ });
77
+ this.engine = new Engine(container);
78
+ this.graphics = new Graphics(this.engine.getContext());
79
+ this.keyboard = new Keyboard();
80
+ this.mouse = new Mouse((cssX, cssY) => this.engine.transformMousePosition(cssX, cssY));
81
+ this.gamepad = new Gamepad();
82
+ this.input = new Input({ keyboard: this.keyboard, mouse: this.mouse, gamepad: this.gamepad });
83
+ this.timer = new Timer();
84
+ this.audio = new Audio();
85
+ }
86
+ setScaling(config) {
87
+ this.engine.setScaling(config);
88
+ }
89
+ setScene(scene) {
90
+ this.scene = scene;
91
+ this.scene.load?.();
92
+ }
93
+ async start(scene) {
94
+ this.setScene(scene);
95
+ this.engine.setDeps({ graphics: this.graphics, input: this.input, timer: this.timer, audio: this.audio, keyboard: this.keyboard, mouse: this.mouse, gamepad: this.gamepad });
96
+ await this.gamepad.init();
97
+ this.engine.start((event) => {
98
+ // 1. handleEvent runs first
99
+ this.scene?.handleEvent?.(event);
100
+ // 2. Direct handlers
101
+ const handler = this.scene?.[event.type];
102
+ if (handler) {
103
+ handler.apply(this.scene, event.args);
104
+ }
105
+ });
106
+ }
107
+ dispose() {
108
+ this.engine.stop();
109
+ this.engine.dispose();
110
+ this.scene = null;
111
+ }
112
+ }
@@ -0,0 +1,18 @@
1
+ import type { Vector2 } from '../../core/vector2';
2
+ import type { Like2DEvent } from '../../core/events';
3
+ export type Scene = {
4
+ load?(): void;
5
+ update?(dt: number): void;
6
+ draw?(canvas: HTMLCanvasElement): void;
7
+ resize?(size: Vector2, pixelSize: Vector2, fullscreen: boolean): void;
8
+ keypressed?(scancode: string, keycode: string): void;
9
+ keyreleased?(scancode: string, keycode: string): void;
10
+ mousepressed?(x: number, y: number, button: number): void;
11
+ mousereleased?(x: number, y: number, button: number): void;
12
+ gamepadpressed?(gamepadIndex: number, buttonIndex: number, buttonName: string): void;
13
+ gamepadreleased?(gamepadIndex: number, buttonIndex: number, buttonName: string): void;
14
+ actionpressed?(action: string): void;
15
+ actionreleased?(action: string): void;
16
+ handleEvent?(event: Like2DEvent): void;
17
+ };
18
+ //# sourceMappingURL=scene.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../../../src/adapters/scene/scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,CAAC,IAAI,IAAI,CAAC;IACd,MAAM,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,CAAC,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACvC,MAAM,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;IACtE,UAAU,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACrD,WAAW,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,YAAY,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,aAAa,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3D,cAAc,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACrF,eAAe,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACtF,aAAa,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,cAAc,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,WAAW,CAAC,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;CACxC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { Like2DEvent } from '../../core/events';
2
+ import type { Scene } from './scene';
3
+ import type { Graphics } from '../../core/graphics';
4
+ export type StartupSceneConfig = {
5
+ nextScene: Scene;
6
+ draw?: (g: Graphics, canvas: HTMLCanvasElement) => void;
7
+ };
8
+ export declare class StartupScene implements Scene {
9
+ private graphics;
10
+ private config;
11
+ private onStart;
12
+ private started;
13
+ constructor(graphics: Graphics, config: StartupSceneConfig, onStart: () => void);
14
+ draw(canvas: HTMLCanvasElement): void;
15
+ handleEvent(event: Like2DEvent): void;
16
+ }
17
+ //# sourceMappingURL=startup-scene.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startup-scene.d.ts","sourceRoot":"","sources":["../../../src/adapters/scene/startup-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,KAAK,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACzD,CAAC;AAMF,qBAAa,YAAa,YAAW,KAAK;IAItC,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IALjB,OAAO,CAAC,OAAO,CAAS;gBAGd,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,MAAM,IAAI;IAK7B,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAIrC,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;CAMtC"}
@@ -0,0 +1,41 @@
1
+ function defaultDraw(g, canvas) {
2
+ g.print('white', 'Click to Start', [canvas.width / 2, canvas.height / 2], { align: 'center' });
3
+ }
4
+ export class StartupScene {
5
+ constructor(graphics, config, onStart) {
6
+ Object.defineProperty(this, "graphics", {
7
+ enumerable: true,
8
+ configurable: true,
9
+ writable: true,
10
+ value: graphics
11
+ });
12
+ Object.defineProperty(this, "config", {
13
+ enumerable: true,
14
+ configurable: true,
15
+ writable: true,
16
+ value: config
17
+ });
18
+ Object.defineProperty(this, "onStart", {
19
+ enumerable: true,
20
+ configurable: true,
21
+ writable: true,
22
+ value: onStart
23
+ });
24
+ Object.defineProperty(this, "started", {
25
+ enumerable: true,
26
+ configurable: true,
27
+ writable: true,
28
+ value: false
29
+ });
30
+ this.graphics.setBackgroundColor('black');
31
+ }
32
+ draw(canvas) {
33
+ (this.config.draw ?? defaultDraw)(this.graphics, canvas);
34
+ }
35
+ handleEvent(event) {
36
+ if (event.type === 'mousepressed' && !this.started) {
37
+ this.started = true;
38
+ this.onStart();
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,61 @@
1
+ /** The audio module performs a few things:
2
+ *
3
+ * ## Make audio resources behave as if synchronous
4
+ * Functions like playback and seeking are deferred until the sound is loaded.
5
+ *
6
+ * ## Track and give global control to all audio objects
7
+ * Start, stop, or set global volume for every currently playing sound.
8
+ *
9
+ */
10
+ export type SourceOptions = {
11
+ volume?: number;
12
+ };
13
+ /**
14
+ * Handle to a loaded audio resource.
15
+ * Use `play()`, `stop()`, `pause()`, `resume()` for playback control.
16
+ * Access the underlying HTMLAudioElement via `source.audio` for looping,
17
+ * pitch, etc. Note: Use `source.setVolume()` instead of setting
18
+ * `source.audio.volume` directly to ensure global volume scaling works correctly.
19
+ */
20
+ export declare class Source {
21
+ readonly path: string;
22
+ /** Underlying HTMLAudioElement. Modify directly for looping, pitch, etc. Use methods for playback control. Avoid setting volume directly. */
23
+ readonly audio: HTMLAudioElement;
24
+ readonly options: Required<SourceOptions>;
25
+ /** Resolves when the audio is loaded and ready to play. */
26
+ readonly ready: Promise<void>;
27
+ private loadState;
28
+ private audioRef;
29
+ constructor(path: string, audioRef: Audio, options?: SourceOptions);
30
+ isReady(): boolean;
31
+ play(): void;
32
+ stop(): void;
33
+ pause(): void;
34
+ resume(): void;
35
+ seek(position: number): void;
36
+ tell(): number;
37
+ isPlaying(): boolean;
38
+ isPaused(): boolean;
39
+ isStopped(): boolean;
40
+ /** Set volume (0-1). Applies global volume scaling. Prefer this over `source.audio.volume`. */
41
+ setVolume(volume: number): void;
42
+ getVolume(): number;
43
+ getDuration(): number;
44
+ }
45
+ export declare class Audio {
46
+ private sources;
47
+ private globalVolume;
48
+ newSource(path: string, options?: SourceOptions): Source;
49
+ /** Get all audio sources -- note that sources are tracked
50
+ * using weak references, and storing this list can cause
51
+ * a memory leak.
52
+ */
53
+ private getAllSources;
54
+ stopAll(): void;
55
+ pauseAll(): void;
56
+ resumeAll(): void;
57
+ setVolume(volume: number): void;
58
+ getVolume(): number;
59
+ clone(source: Source): Source;
60
+ }
61
+ //# sourceMappingURL=audio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../../src/core/audio.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAA;AAMD;;;;;;GAMG;AACH,qBAAa,MAAM;IACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6IAA6I;IAC7I,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC1C,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,CAAC,SAAS,CAAoE;IACrF,OAAO,CAAC,QAAQ,CAAQ;gBAEZ,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,GAAE,aAAkB;IAmCtE,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,KAAK;IAChB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,YAAY,CAAK;IAEzB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM;IAMxD;;;QAGI;IACJ,OAAO,CAAC,aAAa;IASrB,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,MAAM,GAAG,MAAM;CAG9B"}