like2d 2.9.0 → 2.10.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.
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/{core → graphics}/canvas.d.ts +18 -11
  18. package/dist/graphics/canvas.d.ts.map +1 -0
  19. package/dist/{core → graphics}/canvas.js +73 -58
  20. package/dist/{core/graphics.d.ts → graphics/drawing.d.ts} +25 -25
  21. package/dist/graphics/drawing.d.ts.map +1 -0
  22. package/dist/{core/graphics.js → graphics/drawing.js} +59 -52
  23. package/dist/graphics/index.d.ts +19 -0
  24. package/dist/graphics/index.d.ts.map +1 -0
  25. package/dist/graphics/index.js +13 -0
  26. package/dist/index.d.ts +3 -30
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +0 -21
  29. package/dist/input/controllerdb.json +1 -0
  30. package/dist/input/gamepad-mapping.d.ts +119 -0
  31. package/dist/input/gamepad-mapping.d.ts.map +1 -0
  32. package/dist/input/gamepad-mapping.js +114 -0
  33. package/dist/input/gamepad.d.ts +73 -0
  34. package/dist/input/gamepad.d.ts.map +1 -0
  35. package/dist/input/gamepad.js +291 -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 +163 -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 +30 -0
  64. package/dist/prefab-scenes/mapGamepad.d.ts.map +1 -0
  65. package/dist/prefab-scenes/mapGamepad.js +192 -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 +21 -12
  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
@@ -1,129 +1,111 @@
1
- import { mod as mmod } from ".";
2
- /** Library of Vec2 functions. See {@link Vector2} for overview. */
3
- export var Vec2;
4
- (function (Vec2) {
5
- function add(a, b) {
6
- return [a[0] + b[0], a[1] + b[1]];
7
- }
8
- Vec2.add = add;
9
- function sub(a, b) {
10
- return [a[0] - b[0], a[1] - b[1]];
11
- }
12
- Vec2.sub = sub;
13
- function mul(v, other) {
14
- if (typeof other === 'number') {
15
- return [v[0] * other, v[1] * other];
16
- }
17
- return [v[0] * other[0], v[1] * other[1]];
18
- }
19
- Vec2.mul = mul;
20
- function div(v, other) {
21
- if (typeof other === 'number') {
22
- return [v[0] / other, v[1] / other];
23
- }
24
- return [v[0] / other[0], v[1] / other[1]];
25
- }
26
- Vec2.div = div;
27
- function mod(v, other) {
28
- if (typeof other === 'number') {
29
- return [mmod(v[0], other), mmod(v[1], other)];
30
- }
31
- return [mmod(v[0], other[0]), mmod(v[1], other[1])];
32
- }
33
- Vec2.mod = mod;
34
- function eq(v, other) {
35
- return v[0] == other[0] && v[1] == other[1];
36
- }
37
- Vec2.eq = eq;
38
- function dot(a, b) {
1
+ import { mod as mmod } from "./index.js";
2
+ /**
3
+ * According to benchmarks, constructing funcs with these helpers is just as fast as loose coords in v8.
4
+ * Why not, then?
5
+ * If you're writing hyper-optimized Vector2 code, just use loose math anyway
6
+ * -- it will likely logically optimize down further, if you do the algebra.
7
+ */
8
+ /** @see {@link Vec2.map} */
9
+ function map2x1(op) {
10
+ return (a) => [op(a[0]), op(a[1])];
11
+ }
12
+ /** @see {@link Vec2.map2} */
13
+ function map2x2(op) {
14
+ return (a, b) => typeof b == "object" && b instanceof Array
15
+ ? [op(a[0], b[0]), op(a[1], b[1])]
16
+ : [op(a[0], b), op(a[1], b)];
17
+ }
18
+ export const Vec2 = {
19
+ /**
20
+ * Turn a unary function into a pair-wise unary function.
21
+ * @param op A function that takes one arg and returns something.
22
+ * @returns A function that takes a pair such as `[number, number]` (Vector2) and transforms it with `op`.
23
+ */
24
+ map: map2x1,
25
+ /**
26
+ * Turn a binary function into a pair-wise binary function, for example one that operates on two `Vector2`s.
27
+ * @param op A function that takes two values and calculates one.
28
+ * @returns A function that runs `op` pair-wise on both arguments, constructing a new pair.
29
+ */
30
+ map2: map2x2,
31
+ add: map2x2((a, b) => a + b),
32
+ sub: map2x2((a, b) => a - b),
33
+ mul: map2x2((a, b) => a * b),
34
+ div: map2x2((a, b) => a / b),
35
+ /** Returns the maximum of two coordinates,
36
+ * i.e. the lower right corner of a bounding box containing them. */
37
+ max: map2x2(Math.max),
38
+ /** Returns the minimum of two coordinates,
39
+ * i.e. the upper left corner of a bounding box containing them. */
40
+ min: map2x2(Math.min),
41
+ /** Apply a true modulus (i.e. where -1 % 3 == 2) to a Vector2.
42
+ *
43
+ * For JS-style modulus (who wants that?) use `Vec2.map2((a,b) => a % b)` */
44
+ mod: map2x2(mmod),
45
+ /** Apply deep (not referential) equality to a pair of Vec2s.
46
+ * @param epsilon Tolerance factor for inexact matches.
47
+ */
48
+ eq(v, other, epsilon) {
49
+ return epsilon == 0
50
+ ? v[0] == other[0] && v[1] == other[1]
51
+ : Vec2.lengthSq(Vec2.sub(v, other)) < epsilon ** 2;
52
+ },
53
+ dot(a, b) {
39
54
  return a[0] * b[0] + a[1] * b[1];
40
- }
41
- Vec2.dot = dot;
42
- function cross(a, b) {
55
+ },
56
+ cross(a, b) {
43
57
  return a[0] * b[1] - a[1] * b[0];
44
- }
45
- Vec2.cross = cross;
46
- function lengthSq(v) {
58
+ },
59
+ lengthSq(v) {
47
60
  return v[0] * v[0] + v[1] * v[1];
48
- }
49
- Vec2.lengthSq = lengthSq;
50
- function length(v) {
51
- return Math.sqrt(lengthSq(v));
52
- }
53
- Vec2.length = length;
54
- function normalize(v) {
55
- const len = length(v);
61
+ },
62
+ length(v) {
63
+ return Math.sqrt(this.lengthSq(v));
64
+ },
65
+ /** Set the length of a Vector2 to 1.0 while preserving its angle. */
66
+ normalize(v) {
67
+ const len = this.length(v);
56
68
  if (len === 0)
57
69
  return [0, 0];
58
- return div(v, len);
59
- }
60
- Vec2.normalize = normalize;
61
- function distance(a, b) {
62
- return length(sub(a, b));
63
- }
64
- Vec2.distance = distance;
65
- function lerp(a, b, t) {
70
+ return this.div(v, len);
71
+ },
72
+ distance(a, b) {
73
+ return this.length(this.sub(a, b));
74
+ },
75
+ lerp(a, b, t) {
66
76
  return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
67
- }
68
- Vec2.lerp = lerp;
69
- function toPolar(v) {
77
+ },
78
+ toPolar(v) {
70
79
  return {
71
- r: Vec2.length(v),
72
- angle: Vec2.angle(v),
80
+ r: this.length(v),
81
+ angle: this.angle(v),
73
82
  };
74
- }
75
- Vec2.toPolar = toPolar;
76
- function fromPolar(r, angle) {
83
+ },
84
+ fromPolar(r, angle) {
77
85
  return [r * Math.cos(angle), r * Math.sin(angle)];
78
- }
79
- Vec2.fromPolar = fromPolar;
80
- function angle(v) {
86
+ },
87
+ angle(v) {
81
88
  return Math.atan2(v[1], v[0]);
82
- }
83
- Vec2.angle = angle;
84
- function rotate(v, angle) {
89
+ },
90
+ rotate(v, angle) {
85
91
  const cos = Math.cos(angle);
86
92
  const sin = Math.sin(angle);
87
93
  return [v[0] * cos - v[1] * sin, v[0] * sin + v[1] * cos];
88
- }
89
- Vec2.rotate = rotate;
90
- function negate(v) {
91
- return [-v[0], -v[1]];
92
- }
93
- Vec2.negate = negate;
94
- function floor(v) {
95
- return [Math.floor(v[0]), Math.floor(v[1])];
96
- }
97
- Vec2.floor = floor;
98
- function ceil(v) {
99
- return [Math.ceil(v[0]), Math.ceil(v[1])];
100
- }
101
- Vec2.ceil = ceil;
102
- function round(v) {
103
- return [Math.round(v[0]), Math.round(v[1])];
104
- }
105
- Vec2.round = round;
106
- function min(a, b) {
107
- return [Math.min(a[0], b[0]), Math.min(a[1], b[1])];
108
- }
109
- Vec2.min = min;
110
- function max(a, b) {
111
- return [Math.max(a[0], b[0]), Math.max(a[1], b[1])];
112
- }
113
- Vec2.max = max;
114
- function clamp(v, min, max) {
94
+ },
95
+ negate: map2x1((a) => -a),
96
+ floor: map2x1(Math.floor),
97
+ ceil: map2x1(Math.ceil),
98
+ round: map2x1(Math.round),
99
+ clamp(v, min, max) {
115
100
  return [
116
101
  Math.max(min[0], Math.min(v[0], max[0])),
117
102
  Math.max(min[1], Math.min(v[1], max[1])),
118
103
  ];
119
- }
120
- Vec2.clamp = clamp;
121
- function fromAngle(angle, len = 1) {
104
+ },
105
+ fromAngle(angle, len = 1) {
122
106
  return [Math.cos(angle) * len, Math.sin(angle) * len];
123
- }
124
- Vec2.fromAngle = fromAngle;
125
- function zero() {
107
+ },
108
+ zero() {
126
109
  return [0, 0];
127
- }
128
- Vec2.zero = zero;
129
- })(Vec2 || (Vec2 = {}));
110
+ },
111
+ };
@@ -4,4 +4,5 @@
4
4
  * A set of built-in scenes to aid with game development.
5
5
  */
6
6
  export { StartScreen } from "./startScreen";
7
+ export { MapGamepad, buttonSetAll, buttonSetNES, buttonSetPS1, buttonSetSNES } from "./mapGamepad";
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prefab-scenes/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prefab-scenes/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
@@ -4,3 +4,4 @@
4
4
  * A set of built-in scenes to aid with game development.
5
5
  */
6
6
  export { StartScreen } from "./startScreen";
7
+ export { MapGamepad, buttonSetAll, buttonSetNES, buttonSetPS1, buttonSetSNES } from "./mapGamepad";
@@ -0,0 +1,30 @@
1
+ import type { Like } from "..";
2
+ import { type LikeButton } from "../input";
3
+ import { Scene } from "../scene";
4
+ export declare const buttonSetNES: Set<LikeButton>;
5
+ export declare const buttonSetGBA: Set<LikeButton>;
6
+ export declare const buttonSetSNES: Set<LikeButton>;
7
+ export declare const buttonSetPS1: Set<LikeButton>;
8
+ export declare const buttonSetAll: Set<LikeButton>;
9
+ export type MapMode = {
10
+ buttons: Set<LikeButton>;
11
+ stickCount: number;
12
+ };
13
+ export declare class MapGamepad implements Scene {
14
+ private mapMode;
15
+ private targetPad;
16
+ private next?;
17
+ private currentlyUnmapped;
18
+ private mapping;
19
+ private held?;
20
+ private alreadyMapped;
21
+ private frameWait;
22
+ constructor(mapMode: MapMode, targetPad: number, next?: Scene | undefined);
23
+ load(like: Like): void;
24
+ update(): void;
25
+ draw(like: Like): void;
26
+ gamepadpressed(like: Like, source: number, _name: LikeButton, num: number): void;
27
+ gamepadreleased(_like: Like, source: number, _name: LikeButton, num: number): void;
28
+ mousepressed(like: Like): void;
29
+ }
30
+ //# sourceMappingURL=mapGamepad.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapGamepad.d.ts","sourceRoot":"","sources":["../../src/prefab-scenes/mapGamepad.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE/B,OAAO,EAAE,KAAK,UAAU,EAAkC,MAAM,UAAU,CAAC;AAE3E,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAyBjC,eAAO,MAAM,YAAY,iBAA4C,CAAC;AACtE,eAAO,MAAM,YAAY,iBAA6C,CAAC;AACvE,eAAO,MAAM,aAAa,iBAA6C,CAAC;AACxE,eAAO,MAAM,YAAY,iBAA6C,CAAC;AACvE,eAAO,MAAM,YAAY,iBAAgC,CAAC;AA6D1D,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,qBAAa,UAAW,YAAW,KAAK;IAQpC,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,IAAI,CAAC;IATf,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,IAAI,CAAC,CAAa;IAC1B,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,SAAS,CAAK;gBAGZ,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,KAAK,YAAA;IAGtB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IActB,MAAM,IAAI,IAAI;IAId,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAqCtB,cAAc,CACZ,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,MAAM,GACV,IAAI;IAaP,eAAe,CACb,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,MAAM,GACV,IAAI;IAOP,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;CAG/B"}
@@ -0,0 +1,192 @@
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
+ Object.defineProperty(this, "frameWait", {
123
+ enumerable: true,
124
+ configurable: true,
125
+ writable: true,
126
+ value: 0
127
+ });
128
+ }
129
+ load(like) {
130
+ this.frameWait = 10;
131
+ this.mapping = like.gamepad.getMapping(this.targetPad) ?? defaultMapping(2);
132
+ const alreadyMapped = new Set(Object.values(this.mapping.buttons));
133
+ for (const btn of mapOrder.reverse()) {
134
+ if (this.mapMode.buttons.has(btn) && !alreadyMapped.has(btn)) {
135
+ this.currentlyUnmapped.push(btn);
136
+ }
137
+ }
138
+ like.canvas.setMode([320, 240]);
139
+ }
140
+ update() {
141
+ this.frameWait--;
142
+ }
143
+ draw(like) {
144
+ const centerText = {
145
+ font: "1px sans-serif",
146
+ align: "center",
147
+ width: 16,
148
+ };
149
+ const active = this.currentlyUnmapped.at(-1);
150
+ like.gfx.clear();
151
+ like.gfx.scale(20);
152
+ like.gfx.translate([0, 1]);
153
+ like.gfx.print("white", `Map gamepad ${this.targetPad}`, [8, 0.0], centerText);
154
+ for (const prop of this.mapMode.buttons.keys()) {
155
+ const color = this.held == prop
156
+ ? "green"
157
+ : active == prop
158
+ ? "red"
159
+ : this.mapMode.buttons.has(prop)
160
+ ? "gray"
161
+ : "black";
162
+ buttonProps[prop].draw(like, color);
163
+ }
164
+ like.gfx.print("white", active
165
+ ? `Press ${like.gamepad.fullButtonName(active)}!`
166
+ : "Press any button to resume.", [2, 10], { font: "1px sans-serif" });
167
+ }
168
+ gamepadpressed(like, source, _name, num) {
169
+ if (source !== this.targetPad || this.held || this.frameWait > 0)
170
+ return;
171
+ const active = this.currentlyUnmapped.pop();
172
+ if (active && !this.alreadyMapped.has(num)) {
173
+ this.alreadyMapped.add(num);
174
+ this.mapping.buttons[num] = active;
175
+ this.held = active;
176
+ }
177
+ else if (!active) {
178
+ like.gamepad.setMapping(this.targetPad, this.mapping);
179
+ setTimeout(() => like.setScene(this.next), 100);
180
+ }
181
+ }
182
+ gamepadreleased(_like, source, _name, num) {
183
+ if (source !== this.targetPad)
184
+ return;
185
+ if (this.held == this.mapping.buttons[num]) {
186
+ this.held = undefined;
187
+ }
188
+ }
189
+ mousepressed(like) {
190
+ like.setScene(this.next);
191
+ }
192
+ }
@@ -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
  }