like2d 2.11.1 → 2.12.1
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.
- package/README.md +33 -5
- package/assets/logo-banner-optimized.svg +15 -27
- package/assets/logo-banner.svg +76 -132
- package/assets/logo-icon.svg +33 -23
- package/assets/logo.svg +78 -123
- package/dist/engine.d.ts +2 -0
- package/dist/engine.js +34 -12
- package/dist/events.d.ts +0 -3
- package/dist/graphics/canvas.d.ts +15 -7
- package/dist/graphics/canvas.js +64 -68
- package/dist/graphics/graphics.d.ts +55 -40
- package/dist/graphics/graphics.js +100 -72
- package/dist/graphics/index.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +0 -2
- package/dist/input/controllerdb.json +1 -1
- package/dist/input/gamepad-mapping.js +2 -1
- package/dist/input/gamepad.d.ts +1 -1
- package/dist/input/gamepad.js +1 -1
- package/dist/input/input.d.ts +2 -2
- package/dist/input/input.js +2 -2
- package/dist/input/mouse.d.ts +7 -7
- package/dist/input/mouse.js +7 -7
- package/dist/like.d.ts +48 -10
- package/dist/math/rect.d.ts +1 -0
- package/dist/math/rect.js +1 -0
- package/dist/math/vector2.d.ts +4 -1
- package/dist/math/vector2.js +3 -0
- package/dist/prefab-scenes/mapGamepad.d.ts +2 -3
- package/dist/prefab-scenes/mapGamepad.js +17 -23
- package/dist/prefab-scenes/startScreen.d.ts +2 -3
- package/dist/prefab-scenes/startScreen.js +41 -12
- package/dist/scene.d.ts +49 -7
- package/package.json +3 -2
- package/dist/__benchmarks__/vector2.bench.d.ts +0 -2
- package/dist/__benchmarks__/vector2.bench.d.ts.map +0 -1
- package/dist/__benchmarks__/vector2.bench.js +0 -74
- package/dist/audio/audio.d.ts.map +0 -1
- package/dist/audio/index.d.ts.map +0 -1
- package/dist/engine.d.ts.map +0 -1
- package/dist/events.d.ts.map +0 -1
- package/dist/graphics/canvas.d.ts.map +0 -1
- package/dist/graphics/graphics.d.ts.map +0 -1
- package/dist/graphics/image.d.ts.map +0 -1
- package/dist/graphics/index.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/input/gamepad-mapping.d.ts.map +0 -1
- package/dist/input/gamepad.d.ts.map +0 -1
- package/dist/input/index.d.ts.map +0 -1
- package/dist/input/input.d.ts.map +0 -1
- package/dist/input/keyboard.d.ts.map +0 -1
- package/dist/input/mouse.d.ts.map +0 -1
- package/dist/like.d.ts.map +0 -1
- package/dist/math/index.d.ts.map +0 -1
- package/dist/math/rect.d.ts.map +0 -1
- package/dist/math/vector2.d.ts.map +0 -1
- package/dist/prefab-scenes/index.d.ts.map +0 -1
- package/dist/prefab-scenes/mapGamepad.d.ts.map +0 -1
- package/dist/prefab-scenes/startScreen.d.ts.map +0 -1
- package/dist/scene.d.ts.map +0 -1
- package/dist/timer/index.d.ts.map +0 -1
- package/dist/timer/timer.d.ts.map +0 -1
|
@@ -58,6 +58,7 @@ export const defaultMapping = (stickCount) => ({
|
|
|
58
58
|
]),
|
|
59
59
|
});
|
|
60
60
|
export const standardButtonMapping = () => Object.fromEntries(buttonMap.map(({ like, num }) => [num, like]));
|
|
61
|
+
const numToName = standardButtonMapping();
|
|
61
62
|
/** @private */
|
|
62
63
|
export const allButtons = new Set(buttonMap.map(({ like }) => like));
|
|
63
64
|
export const fullButtonName = new Map(buttonMap.map(({ like, name }) => [like, name]));
|
|
@@ -70,7 +71,7 @@ const mappingDb = new Map(Object.entries(mappingDbRaw[detectedOs]).map(([k, v])
|
|
|
70
71
|
Number(k),
|
|
71
72
|
{
|
|
72
73
|
...v,
|
|
73
|
-
mapping: Object.fromEntries(Object.entries(v.mapping).map(([k, v]) => [Number(k), v])),
|
|
74
|
+
mapping: Object.fromEntries(Object.entries(v.mapping).map(([k, v]) => [Number(k), numToName[Number(v)]])),
|
|
74
75
|
},
|
|
75
76
|
]));
|
|
76
77
|
export function getSdlMapping(gamepad) {
|
package/dist/input/gamepad.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export type GamepadTarget = number | "any";
|
|
|
12
12
|
*
|
|
13
13
|
* If you're planning on supporting gamepads, please include a
|
|
14
14
|
* way to generate {@link GamepadMapping} and set it with {@link Gamepad.setMapping}.
|
|
15
|
-
* Perhaps trigger it on {@link index.EventMap.gamepadconnected} events.
|
|
15
|
+
* Perhaps trigger it on {@link index.EventMap.gamepadconnected | gamepadconnected} events.
|
|
16
16
|
*
|
|
17
17
|
* If you don't want to make your own, take a look at {@link prefab-scenes.MapGamepad}
|
|
18
18
|
*
|
package/dist/input/gamepad.js
CHANGED
|
@@ -7,7 +7,7 @@ import { defaultMapping, fullButtonName, getSdlMapping, mapStick, standardButton
|
|
|
7
7
|
*
|
|
8
8
|
* If you're planning on supporting gamepads, please include a
|
|
9
9
|
* way to generate {@link GamepadMapping} and set it with {@link Gamepad.setMapping}.
|
|
10
|
-
* Perhaps trigger it on {@link index.EventMap.gamepadconnected} events.
|
|
10
|
+
* Perhaps trigger it on {@link index.EventMap.gamepadconnected | gamepadconnected} events.
|
|
11
11
|
*
|
|
12
12
|
* If you don't want to make your own, take a look at {@link prefab-scenes.MapGamepad}
|
|
13
13
|
*
|
package/dist/input/input.d.ts
CHANGED
|
@@ -81,7 +81,7 @@ export declare class Input {
|
|
|
81
81
|
/**
|
|
82
82
|
* This is the easiest way to set-and-forget input => action mapping.
|
|
83
83
|
*
|
|
84
|
-
* Or, it's a helper to remove actions -- `setAction(action)`
|
|
84
|
+
* Or, it's a helper to remove actions -- `setAction(action, [])`
|
|
85
85
|
* will simply clear the action away.
|
|
86
86
|
*
|
|
87
87
|
* For input strings:
|
|
@@ -109,7 +109,7 @@ export declare class Input {
|
|
|
109
109
|
* @param action
|
|
110
110
|
* @param inputs
|
|
111
111
|
*/
|
|
112
|
-
setAction(action: string, inputs
|
|
112
|
+
setAction(action: string, inputs: (string | InputBinding)[]): void;
|
|
113
113
|
/**
|
|
114
114
|
* Map a single input onto an action.
|
|
115
115
|
*/
|
package/dist/input/input.js
CHANGED
|
@@ -103,7 +103,7 @@ export class Input {
|
|
|
103
103
|
/**
|
|
104
104
|
* This is the easiest way to set-and-forget input => action mapping.
|
|
105
105
|
*
|
|
106
|
-
* Or, it's a helper to remove actions -- `setAction(action)`
|
|
106
|
+
* Or, it's a helper to remove actions -- `setAction(action, [])`
|
|
107
107
|
* will simply clear the action away.
|
|
108
108
|
*
|
|
109
109
|
* For input strings:
|
|
@@ -131,7 +131,7 @@ export class Input {
|
|
|
131
131
|
* @param action
|
|
132
132
|
* @param inputs
|
|
133
133
|
*/
|
|
134
|
-
setAction(action, inputs
|
|
134
|
+
setAction(action, inputs) {
|
|
135
135
|
if (inputs.length) {
|
|
136
136
|
this.actionTable[action] = inputs.map(parseInput);
|
|
137
137
|
}
|
package/dist/input/mouse.d.ts
CHANGED
|
@@ -98,13 +98,13 @@ export declare class Mouse {
|
|
|
98
98
|
* Avoid binding the `ESC` key in captured mode. This will exit the capture and
|
|
99
99
|
* reset mode to default.
|
|
100
100
|
*
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
101
|
+
* ### Note on `pos` vs `delta`
|
|
102
|
+
* Event {@link index.EventMap.mousemoved} passes both `pos` and `delta` args.
|
|
103
|
+
*
|
|
104
|
+
* Though the emulated cursor in locked mode
|
|
105
|
+
* (locked mode doesn't natively track absolute position)
|
|
106
|
+
* may be stuck on canvas edges, the `delta` field always
|
|
107
|
+
* represents mouse movement, even against edges.
|
|
108
108
|
*/
|
|
109
109
|
setMode(mode: MouseSetMode): void;
|
|
110
110
|
getMode(): MouseMode;
|
package/dist/input/mouse.js
CHANGED
|
@@ -200,13 +200,13 @@ export class Mouse {
|
|
|
200
200
|
* Avoid binding the `ESC` key in captured mode. This will exit the capture and
|
|
201
201
|
* reset mode to default.
|
|
202
202
|
*
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
203
|
+
* ### Note on `pos` vs `delta`
|
|
204
|
+
* Event {@link index.EventMap.mousemoved} passes both `pos` and `delta` args.
|
|
205
|
+
*
|
|
206
|
+
* Though the emulated cursor in locked mode
|
|
207
|
+
* (locked mode doesn't natively track absolute position)
|
|
208
|
+
* may be stuck on canvas edges, the `delta` field always
|
|
209
|
+
* represents mouse movement, even against edges.
|
|
210
210
|
*/
|
|
211
211
|
setMode(mode) {
|
|
212
212
|
this.lockPointer(mode.lock);
|
package/dist/like.d.ts
CHANGED
|
@@ -17,12 +17,11 @@ export type Callbacks = {
|
|
|
17
17
|
[K in EventType]?: Callback<K>;
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
|
-
* The main
|
|
21
|
-
*
|
|
22
|
-
* This is the interface returned by {@link createLike}.
|
|
20
|
+
* The main modules and builtins of `like`, aside from {@link EventMap | optional callbacks}.
|
|
21
|
+
* @interface
|
|
23
22
|
*/
|
|
24
|
-
export type
|
|
25
|
-
/** Handle a pool of
|
|
23
|
+
export type LikeBase = {
|
|
24
|
+
/** Handle a pool of audio sources with global volume control and more. */
|
|
26
25
|
readonly audio: Audio;
|
|
27
26
|
/** Misc. time functions, including sleeping the game. ZZZ */
|
|
28
27
|
readonly timer: Timer;
|
|
@@ -53,21 +52,52 @@ export type Like = Callbacks & {
|
|
|
53
52
|
*/
|
|
54
53
|
dispose(): void;
|
|
55
54
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
55
|
+
* Push a scene to the scene stack.
|
|
56
|
+
*
|
|
57
|
+
* If the engine is running, this is the new running scene replacing the old one
|
|
58
|
+
* which can, in some cases, call out to the lower scene.
|
|
59
|
+
*
|
|
60
|
+
* @param overlay Set to true, and the current scene (before pushing) will stay loaded. Otherwise not.
|
|
61
|
+
*/
|
|
62
|
+
pushScene(scene: Scene, overlay: boolean): void;
|
|
63
|
+
/**
|
|
64
|
+
* Pop the current scene off the stack.
|
|
65
|
+
*
|
|
66
|
+
* To clear the stack, just run:
|
|
67
|
+
* ```ts
|
|
68
|
+
* while (like.popScene());
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
popScene(): Scene | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Set the current scene at the top of the scene stack.
|
|
74
|
+
* If the stack is empty, push it onto the stack.
|
|
75
|
+
*
|
|
76
|
+
* Equivalent to `popScene` + `pushScene`.
|
|
77
|
+
*
|
|
78
|
+
* Use {@link index.Like | popScene} to clear away the current scene,
|
|
79
|
+
* and to possibly revert to callback mode.
|
|
80
|
+
*/
|
|
81
|
+
setScene(scene: Scene): void;
|
|
82
|
+
/**
|
|
83
|
+
* Get the current scene, or a specific index.
|
|
84
|
+
*
|
|
85
|
+
* Uses `Array.at` under the hood, so -1 is the
|
|
86
|
+
* top scene, -2 is the parent scene, etc.
|
|
58
87
|
*/
|
|
59
|
-
|
|
88
|
+
getScene(index?: number): Scene | undefined;
|
|
60
89
|
/**
|
|
61
90
|
* LIKE's runtime is built around calling handleEvent.
|
|
62
91
|
*
|
|
63
92
|
* This function recieves all events. If set to undefined,
|
|
64
|
-
|
|
93
|
+
* {@link index.Like | Like.callOwnHandlers} is the default behavior.
|
|
65
94
|
*
|
|
66
95
|
* Otherwise, you can really customize LIKE by setting this
|
|
67
96
|
* to a custom handler.
|
|
68
97
|
*
|
|
69
98
|
* For example, the scene architecture is built around
|
|
70
|
-
* setting this function.
|
|
99
|
+
* setting this function. Setting it to a custom
|
|
100
|
+
* function will disable the scene system.
|
|
71
101
|
*/
|
|
72
102
|
handleEvent?: TopLevelEventHandler;
|
|
73
103
|
/**
|
|
@@ -77,4 +107,12 @@ export type Like = Callbacks & {
|
|
|
77
107
|
*/
|
|
78
108
|
callOwnHandlers(event: LikeEvent): void;
|
|
79
109
|
};
|
|
110
|
+
/**
|
|
111
|
+
* The main Like instance.
|
|
112
|
+
* Use this object much how you would the `love` object in Love2D.
|
|
113
|
+
* This is the interface returned by {@link createLike}.
|
|
114
|
+
*
|
|
115
|
+
* Check out all the {@link EventMap | callbacks}.
|
|
116
|
+
*/
|
|
117
|
+
export type Like = Callbacks & LikeBase;
|
|
80
118
|
//# sourceMappingURL=like.d.ts.map
|
package/dist/math/rect.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ import { type Vector2 } from '../math/vector2';
|
|
|
41
41
|
*
|
|
42
42
|
* */
|
|
43
43
|
export type Rectangle = [number, number, number, number];
|
|
44
|
+
/** The full library of {@link Rectangle} functions. */
|
|
44
45
|
export declare const Rect: {
|
|
45
46
|
fromPoints(a: Vector2, b: Vector2): Rectangle;
|
|
46
47
|
fromCenter(center: Vector2, size: Vector2): Rectangle;
|
package/dist/math/rect.js
CHANGED
package/dist/math/vector2.d.ts
CHANGED
|
@@ -59,7 +59,7 @@ export type Pair<T> = [T, T];
|
|
|
59
59
|
* #### Squaring each element of a Vector2
|
|
60
60
|
* ```ts
|
|
61
61
|
* const squareVec2 = Vec2.map(a: number => a**2);
|
|
62
|
-
* squareVec2([6, 7]) // returns [36,
|
|
62
|
+
* squareVec2([6, 7]) // returns [36, 49]
|
|
63
63
|
* // one in one line...
|
|
64
64
|
* Vec2.map(a: number => a**2)([6, 7]);
|
|
65
65
|
* ```
|
|
@@ -76,6 +76,9 @@ export type Vector2 = Pair<number>;
|
|
|
76
76
|
declare function map2x1<I, O>(op: (a: I) => O): (a: Pair<I>) => Pair<O>;
|
|
77
77
|
/** @see {@link Vec2.map2} */
|
|
78
78
|
declare function map2x2<I, O>(op: (a: I, b: I) => O): (a: Pair<I>, b: I | Pair<I>) => Pair<O>;
|
|
79
|
+
/**
|
|
80
|
+
* The full library of {@link Vector2} functions.
|
|
81
|
+
*/
|
|
79
82
|
export declare const Vec2: {
|
|
80
83
|
/**
|
|
81
84
|
* Turn a unary function into a pair-wise unary function.
|
package/dist/math/vector2.js
CHANGED
|
@@ -15,7 +15,7 @@ export type MapMode = {
|
|
|
15
15
|
*
|
|
16
16
|
* ```ts
|
|
17
17
|
* like.gamepadconnected = (index) =>
|
|
18
|
-
* like.
|
|
18
|
+
* like.pushScene(new MapGamepad({buttons: buttonSetGBA, sticks: 0}), index)
|
|
19
19
|
* ```
|
|
20
20
|
*
|
|
21
21
|
* Add this to your codebase and activating a gamepad causes a button mapping screen to pop up.
|
|
@@ -26,13 +26,12 @@ export type MapMode = {
|
|
|
26
26
|
export declare class MapGamepad implements Scene {
|
|
27
27
|
private mapMode;
|
|
28
28
|
private targetPad;
|
|
29
|
-
private next?;
|
|
30
29
|
private currentlyUnmapped;
|
|
31
30
|
private mapping;
|
|
32
31
|
private held?;
|
|
33
32
|
private alreadyMapped;
|
|
34
33
|
private frameWait;
|
|
35
|
-
constructor(mapMode: MapMode, targetPad: number
|
|
34
|
+
constructor(mapMode: MapMode, targetPad: number);
|
|
36
35
|
load(like: Like): void;
|
|
37
36
|
update(): void;
|
|
38
37
|
draw(like: Like): void;
|
|
@@ -28,24 +28,24 @@ export const buttonSetPS1 = new Set(mapOrder.slice(0, 14));
|
|
|
28
28
|
export const buttonSetAll = new Set(mapOrder);
|
|
29
29
|
const drawCircButt = (pos, size) => (like, color) => like.gfx.circle("fill", color, pos, size);
|
|
30
30
|
const drawDpadPart = (rot) => (like, color) => {
|
|
31
|
-
like.gfx.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
like.gfx.withTransform(() => {
|
|
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
|
+
});
|
|
36
36
|
};
|
|
37
37
|
const drawShoulder = (y, width, flip) => (like, color) => {
|
|
38
38
|
const r = 0.8;
|
|
39
39
|
const rectPos = [5 - width, y];
|
|
40
40
|
const circPos = [5 - width - r, y];
|
|
41
|
-
like.gfx.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
like.gfx.withTransform(() => {
|
|
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
|
+
});
|
|
49
49
|
};
|
|
50
50
|
// Buttons assume a centered resolution of 16x9px. Transforms exist for a reason lol.
|
|
51
51
|
// LLLLL . RRRRR
|
|
@@ -80,7 +80,7 @@ const buttonProps = {
|
|
|
80
80
|
*
|
|
81
81
|
* ```ts
|
|
82
82
|
* like.gamepadconnected = (index) =>
|
|
83
|
-
* like.
|
|
83
|
+
* like.pushScene(new MapGamepad({buttons: buttonSetGBA, sticks: 0}), index)
|
|
84
84
|
* ```
|
|
85
85
|
*
|
|
86
86
|
* Add this to your codebase and activating a gamepad causes a button mapping screen to pop up.
|
|
@@ -89,7 +89,7 @@ const buttonProps = {
|
|
|
89
89
|
* Note: many browsers do this on first button press, so always writing "P2: press any button" is a fine idea.
|
|
90
90
|
*/
|
|
91
91
|
export class MapGamepad {
|
|
92
|
-
constructor(mapMode, targetPad
|
|
92
|
+
constructor(mapMode, targetPad) {
|
|
93
93
|
Object.defineProperty(this, "mapMode", {
|
|
94
94
|
enumerable: true,
|
|
95
95
|
configurable: true,
|
|
@@ -102,12 +102,6 @@ export class MapGamepad {
|
|
|
102
102
|
writable: true,
|
|
103
103
|
value: targetPad
|
|
104
104
|
});
|
|
105
|
-
Object.defineProperty(this, "next", {
|
|
106
|
-
enumerable: true,
|
|
107
|
-
configurable: true,
|
|
108
|
-
writable: true,
|
|
109
|
-
value: next
|
|
110
|
-
});
|
|
111
105
|
Object.defineProperty(this, "currentlyUnmapped", {
|
|
112
106
|
enumerable: true,
|
|
113
107
|
configurable: true,
|
|
@@ -189,7 +183,7 @@ export class MapGamepad {
|
|
|
189
183
|
}
|
|
190
184
|
else if (!active) {
|
|
191
185
|
like.gamepad.setMapping(this.targetPad, this.mapping);
|
|
192
|
-
setTimeout(() => like.
|
|
186
|
+
setTimeout(() => like.popScene(), 100);
|
|
193
187
|
}
|
|
194
188
|
}
|
|
195
189
|
gamepadreleased(_like, source, _name, num) {
|
|
@@ -200,6 +194,6 @@ export class MapGamepad {
|
|
|
200
194
|
}
|
|
201
195
|
}
|
|
202
196
|
mousepressed(like) {
|
|
203
|
-
like.
|
|
197
|
+
like.popScene();
|
|
204
198
|
}
|
|
205
199
|
}
|
|
@@ -22,7 +22,7 @@ import { Like } from '..';
|
|
|
22
22
|
* like.draw = function () { ... }
|
|
23
23
|
*
|
|
24
24
|
* // Set up the start screen
|
|
25
|
-
* like.
|
|
25
|
+
* like.pushScene(new StartScreen())
|
|
26
26
|
* like.start();
|
|
27
27
|
* ```
|
|
28
28
|
*
|
|
@@ -48,10 +48,9 @@ import { Like } from '..';
|
|
|
48
48
|
* ```
|
|
49
49
|
*/
|
|
50
50
|
export declare class StartScreen implements Scene {
|
|
51
|
-
private next;
|
|
52
51
|
private onDraw?;
|
|
53
52
|
private logo;
|
|
54
|
-
constructor(
|
|
53
|
+
constructor(onDraw?: ((like: Like) => void) | undefined);
|
|
55
54
|
load(like: Like): void;
|
|
56
55
|
draw(like: Like): void;
|
|
57
56
|
mousepressed(like: Like): void;
|
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
import { Vec2 } from '../math/vector2';
|
|
2
|
-
const LOGO = 'data:image/svg+xml;base64,
|
|
2
|
+
const LOGO = 'data:image/svg+xml;base64,' +
|
|
3
|
+
'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBDcmVhdGVkIHdpdGgg' +
|
|
4
|
+
'SW5rc2NhcGUgKGh0dHA6Ly93d3cuaW5rc2NhcGUub3JnLykgLS0+Cjxzdmcgd2lkdGg9IjI1Nm1t' +
|
|
5
|
+
'IiBoZWlnaHQ9Ijg1bW0iIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDI1NiA4NSIgeG1sbnM9' +
|
|
6
|
+
'Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KIDxyZWN0IHg9IjguNDk0OSIgeT0iMTQuODQx' +
|
|
7
|
+
'IiB3aWR0aD0iMjM5LjEzIiBoZWlnaHQ9IjYwLjMzNyIgcnk9IjE0LjM2OSIvPgogPHBhdGggZD0i' +
|
|
8
|
+
'bTQ5LjUxOSAyLjE5MzMtMjIuODQxIDIyLjg1NC0wLjAxMTkzIDAuMDExOTNhMTYuMTU5IDE2LjE2' +
|
|
9
|
+
'OCAwIDAgMCAwIDIyLjg2NiAxNi4xNTkgMTYuMTY4IDAgMCAwIDIwLjUzOSAxLjkxODkgMTYuMTU5' +
|
|
10
|
+
'IDE2LjE2OCAwIDAgMSAwLjAwNDggMC4zOTA1NSAxNi4xNTkgMTYuMTY4IDAgMCAxLTE2LjE1OSAx' +
|
|
11
|
+
'Ni4xNjloMzYuOTM1YTE2LjE1OSAxNi4xNjggMCAwIDEtMTYuMTU5LTE2LjE2OSAxNi4xNTkgMTYu' +
|
|
12
|
+
'MTY4IDAgMCAxIDAuMDA1NC0wLjM5MDU1IDE2LjE1OSAxNi4xNjggMCAwIDAgMjAuNTM5LTEuOTE5' +
|
|
13
|
+
'MyAxNi4xNTkgMTYuMTY4IDAgMCAwLTQuNzZlLTQgLTIyLjg2NnoiIGZpbGw9IiNiYTJiMmIiIHN0' +
|
|
14
|
+
'cm9rZT0iI2ZmY2Y0MiIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIuNSIv' +
|
|
15
|
+
'PgogPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZmZjZjQyIiBzdHJva2Utd2lkdGg9Ii41Ij4KICA8' +
|
|
16
|
+
'Y2lyY2xlIHRyYW5zZm9ybT0ibWF0cml4KC0uNzA2OSAuNzA3MzEgLS43MDY5IC0uNzA3MzEgMCAw' +
|
|
17
|
+
'KSIgY3g9Ii0xNy4zMTEiIGN5PSItNjguOTAzIiByPSIxNi4xNjQiLz4KICA8Y2lyY2xlIHRyYW5z' +
|
|
18
|
+
'Zm9ybT0ibWF0cml4KC0uNzA2OSAuNzA3MzEgLS43MDY5IC0uNzA3MzEgMCAwKSIgY3g9Ii0xLjE0' +
|
|
19
|
+
'NyIgY3k9Ii01Mi43MzkiIHI9IjE2LjE2NCIvPgogIDxlbGxpcHNlIGN4PSI2Ny45ODYiIGN5PSI1' +
|
|
20
|
+
'MC4yMzQiIHJ4PSIxNi4xNTkiIHJ5PSIxNi4xNjgiLz4KICA8ZWxsaXBzZSBjeD0iMzEuMDUxIiBj' +
|
|
21
|
+
'eT0iNTAuMjM0IiByeD0iMTYuMTU5IiByeT0iMTYuMTY4Ii8+CiA8L2c+CiA8ZyBmaWxsPSIjZmZj' +
|
|
22
|
+
'ZjQyIiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iLjUiPgogIDxwYXRoIGQ9Im04OS45MjQg' +
|
|
23
|
+
'MjEuOTc5djM2LjM3NWgyOC4xMDN2LTE0Ljc3MWgtMTIuMDI5di0yMS42MDR6Ii8+CiAgPHBhdGgg' +
|
|
24
|
+
'ZD0ibTEyNy45NCAyNC42Nzh2Ny42NjVoNS4wNDUzdjExLjA0NmgtNS4wNDUzdjE0Ljk2NmgyNC43' +
|
|
25
|
+
'NDh2LTE0Ljk2NmgtNS4wNDh2LTExLjA0Nmg1LjA0OHYtNy42NjVoLTEyLjM3N3oiLz4KICA8cGF0' +
|
|
26
|
+
'aCBkPSJtMjA2Ljg5IDIyLjA4OHYzNi4zNzVoMzMuNzM5di0xMy4xNzloLTEwLjkwOHYtNS4wNjc4' +
|
|
27
|
+
'aDEwLjkwOHYtNy4xMDloLTEwLjkwOHYtNS4wNjloMTAuOTA4di01Ljk1MDR6Ii8+CiAgPHBhdGgg' +
|
|
28
|
+
'ZD0ibTE2Mi43NiAxOS43N3YzOC42OTNoMTIuMjgxdi01LjA2OWgxMS41MjN2NS4wNjloMTIuMjgx' +
|
|
29
|
+
'czEuMDQ4Mi0xNS4xMTUtMi4yMDEyLTE4Ljc2OGMtMy40NzA0LTMuOTAxOC02LjM3MjMtNC41MjA5' +
|
|
30
|
+
'LTYuMzcyMy00LjUyMDlsOC44ODQ4LTEzLjA4N2gtMTMuNjE1bC02LjQxMDggMTMuMDIyLTQuMzQy' +
|
|
31
|
+
'MyAwLjAzNjk4LThlLTMgLTE1LjM3N3oiLz4KICA8ZWxsaXBzZSBjeD0iMTMyLjk5IiBjeT0iMTYu' +
|
|
32
|
+
'MTIyIiByeD0iNi4wMjIxIiByeT0iNi4xMTgyIi8+CiAgPGVsbGlwc2UgY3g9IjE0Ny40OSIgY3k9' +
|
|
33
|
+
'IjE2LjEyMiIgcng9IjYuMDIyMSIgcnk9IjYuMTE4MiIvPgogPC9nPgo8L3N2Zz4K';
|
|
3
34
|
/**
|
|
4
35
|
* ## Why
|
|
5
36
|
*
|
|
@@ -22,7 +53,7 @@ const LOGO = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0i
|
|
|
22
53
|
* like.draw = function () { ... }
|
|
23
54
|
*
|
|
24
55
|
* // Set up the start screen
|
|
25
|
-
* like.
|
|
56
|
+
* like.pushScene(new StartScreen())
|
|
26
57
|
* like.start();
|
|
27
58
|
* ```
|
|
28
59
|
*
|
|
@@ -48,13 +79,7 @@ const LOGO = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0i
|
|
|
48
79
|
* ```
|
|
49
80
|
*/
|
|
50
81
|
export class StartScreen {
|
|
51
|
-
constructor(
|
|
52
|
-
Object.defineProperty(this, "next", {
|
|
53
|
-
enumerable: true,
|
|
54
|
-
configurable: true,
|
|
55
|
-
writable: true,
|
|
56
|
-
value: next
|
|
57
|
-
});
|
|
82
|
+
constructor(onDraw) {
|
|
58
83
|
Object.defineProperty(this, "onDraw", {
|
|
59
84
|
enumerable: true,
|
|
60
85
|
configurable: true,
|
|
@@ -76,13 +101,17 @@ export class StartScreen {
|
|
|
76
101
|
this.onDraw(like);
|
|
77
102
|
}
|
|
78
103
|
else if (this.logo.isReady()) {
|
|
79
|
-
like.gfx.clear([0.
|
|
104
|
+
like.gfx.clear([0.5, 0, 0.5, 1]);
|
|
80
105
|
const winSize = like.canvas.getSize();
|
|
81
106
|
const scale = (winSize[0] * 0.5) / this.logo.size[0];
|
|
82
|
-
like.gfx.draw(this.logo, Vec2.div(winSize, 2), {
|
|
107
|
+
like.gfx.draw(this.logo, Vec2.div(winSize, 2), {
|
|
108
|
+
scale,
|
|
109
|
+
origin: Vec2.div(this.logo.size, 2),
|
|
110
|
+
});
|
|
111
|
+
like.gfx.print([1, 1, 0, 0.5 + 0.5 * Math.sin(like.timer.getTime() * 3)], "▶️ click to start ◀️", Vec2.mul(winSize, [0.5, 0.8]), { align: "center", font: "25px sans" });
|
|
83
112
|
}
|
|
84
113
|
}
|
|
85
114
|
mousepressed(like) {
|
|
86
|
-
like.
|
|
115
|
+
like.popScene();
|
|
87
116
|
}
|
|
88
117
|
}
|
package/dist/scene.d.ts
CHANGED
|
@@ -15,13 +15,21 @@ import type { Like } from './like';
|
|
|
15
15
|
* your running scene and shows up as an additional first argument
|
|
16
16
|
* to every callback.
|
|
17
17
|
*
|
|
18
|
+
* ## The scene stack
|
|
19
|
+
*
|
|
20
|
+
* There is a stack of scenes for state management and/or overlays.
|
|
21
|
+
*
|
|
22
|
+
* Use {@link LikeBase.pushScene | pushScene} and {@link LikeBase.popScene | Like.popScene} to manage the stack.
|
|
23
|
+
*
|
|
24
|
+
* {@link LikeBase.setScene | setScene} Sets the top of the stack only, replacing the current scene if any.
|
|
25
|
+
*
|
|
18
26
|
* ## Quick Start
|
|
19
27
|
*
|
|
20
28
|
* Have a scene handle all the callbacks, disabling global
|
|
21
29
|
* callbacks.
|
|
22
30
|
* ```typescript
|
|
23
31
|
* // set up a scene
|
|
24
|
-
* class MagicalGrowingRectangle
|
|
32
|
+
* class MagicalGrowingRectangle implements Scene {
|
|
25
33
|
* rectangleSize = 10;
|
|
26
34
|
* constructor() {}
|
|
27
35
|
*
|
|
@@ -35,16 +43,16 @@ import type { Like } from './like';
|
|
|
35
43
|
* }
|
|
36
44
|
* }
|
|
37
45
|
*
|
|
38
|
-
* like.
|
|
46
|
+
* like.pushScene(new MagicalGrowingRectangle(), false);
|
|
39
47
|
* ```
|
|
40
48
|
*
|
|
41
|
-
* To get back to global callbacks, just use
|
|
49
|
+
* To get back to global callbacks, just use {@link Like.popScene | like.popScene}
|
|
42
50
|
*
|
|
43
51
|
* ## Scene Lifecycle
|
|
44
52
|
*
|
|
45
53
|
* Works a lot like global callbacks.
|
|
46
54
|
*
|
|
47
|
-
* 1. `like.setScene(scene)` is called
|
|
55
|
+
* 1. `like.setScene(scene)` or `like.pushScene(scene)` is called
|
|
48
56
|
* 2. Scene's `load` callback fires immediately
|
|
49
57
|
* 3. `update` and `draw` begin on next frame
|
|
50
58
|
* 4. Scene receives input events as they occur
|
|
@@ -57,9 +65,9 @@ import type { Like } from './like';
|
|
|
57
65
|
*
|
|
58
66
|
* ```typescript
|
|
59
67
|
* class UI implements Scene {
|
|
60
|
-
* constructor(public game:
|
|
68
|
+
* constructor(public game: Scene) {}
|
|
61
69
|
*
|
|
62
|
-
* handleEvent(like: Like, event:
|
|
70
|
+
* handleEvent(like: Like, event: LikeEvent) {
|
|
63
71
|
* // Block mouse events in order to create a top bar.
|
|
64
72
|
* const mouseY = like.mouse.getPosition()[1];
|
|
65
73
|
* if (!event.type.startsWith('mouse') || mouseY > 100) {
|
|
@@ -77,11 +85,45 @@ import type { Like } from './like';
|
|
|
77
85
|
* ...
|
|
78
86
|
* }
|
|
79
87
|
*
|
|
80
|
-
* like.
|
|
88
|
+
* like.pushScene(new UI(new Game()), false)
|
|
81
89
|
* ```
|
|
82
90
|
*
|
|
83
91
|
* Composing scenes lets you filter events, layer game elements,
|
|
84
92
|
* and more. Don't sleep on it.
|
|
93
|
+
*
|
|
94
|
+
* The main advance of composing scenes versus the stack-overlay
|
|
95
|
+
* technique is that the parent scene knows about its child.
|
|
96
|
+
* Because there's a **known interface**, the two scenes
|
|
97
|
+
* can communicate.
|
|
98
|
+
*
|
|
99
|
+
* This makes it perfect for reusable UI,
|
|
100
|
+
* level editors, debug viewers, and more.
|
|
101
|
+
*
|
|
102
|
+
* ## Overlay scenes
|
|
103
|
+
*
|
|
104
|
+
* You might assume that the purpose of a scene stack is
|
|
105
|
+
* visual: first push the BG, then the FG, etc.
|
|
106
|
+
*
|
|
107
|
+
* Actually, composing scenes (above) is a
|
|
108
|
+
* better pattern for that, since it's both explicit
|
|
109
|
+
* _and_ the parent can have a known interface on its child.
|
|
110
|
+
* Here, the **upper** scene only knows that the
|
|
111
|
+
* **lower** scene _is_ a scene.
|
|
112
|
+
*
|
|
113
|
+
* That's the tradeoff. Overlay scenes are good for things
|
|
114
|
+
* like pause screens or gamepad overlays. Anything where
|
|
115
|
+
* the upper doesn't care _what_ the lower is, and where
|
|
116
|
+
* the upper scene should be easily addable/removable.
|
|
117
|
+
*
|
|
118
|
+
* Using `like.getScene(-2)`, the overlay scene can see
|
|
119
|
+
* the lower scene and choose how to propagate events.
|
|
120
|
+
*
|
|
121
|
+
* The only technical difference between overlay and
|
|
122
|
+
* opaque is whether or not the scene we've pushed
|
|
123
|
+
* on top of stays loaded.
|
|
124
|
+
*
|
|
125
|
+
* @interface
|
|
126
|
+
*
|
|
85
127
|
*/
|
|
86
128
|
export type Scene = {
|
|
87
129
|
[K in keyof EventMap]?: (like: Like, ...args: EventMap[K]) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "like2d",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.12.1",
|
|
4
4
|
"description": "A web-native game framework inspired by Love2D",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"files": [
|
|
39
39
|
"dist/**/*",
|
|
40
|
+
"!dist/**/*.ts.map",
|
|
40
41
|
"assets/**/*",
|
|
41
42
|
"README.md",
|
|
42
43
|
"LICENSE"
|
|
@@ -62,7 +63,7 @@
|
|
|
62
63
|
"license": "MIT",
|
|
63
64
|
"repository": {
|
|
64
65
|
"type": "git",
|
|
65
|
-
"url": "https://github.com/
|
|
66
|
+
"url": "https://github.com/likeOrg/Like2D"
|
|
66
67
|
},
|
|
67
68
|
"devDependencies": {
|
|
68
69
|
"typescript": "^5.9.3"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vector2.bench.d.ts","sourceRoot":"","sources":["../../src/__benchmarks__/vector2.bench.ts"],"names":[],"mappings":""}
|