@typeonce/ritmo-browser 0.10.0 → 0.11.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 (58) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +6 -1
  3. package/dist/Controls.d.ts +495 -0
  4. package/dist/Controls.d.ts.map +1 -0
  5. package/dist/Controls.js +343 -0
  6. package/dist/Controls.js.map +1 -0
  7. package/dist/Gamepad.d.ts +375 -0
  8. package/dist/Gamepad.d.ts.map +1 -0
  9. package/dist/Gamepad.js +452 -0
  10. package/dist/Gamepad.js.map +1 -0
  11. package/dist/InputCapture.d.ts +46 -16
  12. package/dist/InputCapture.d.ts.map +1 -1
  13. package/dist/InputCapture.js +1 -1
  14. package/dist/InputCapture.js.map +1 -1
  15. package/dist/Keyboard.d.ts +184 -21
  16. package/dist/Keyboard.d.ts.map +1 -1
  17. package/dist/Keyboard.js +257 -91
  18. package/dist/Keyboard.js.map +1 -1
  19. package/dist/Pointer.d.ts +231 -62
  20. package/dist/Pointer.d.ts.map +1 -1
  21. package/dist/Pointer.js +205 -145
  22. package/dist/Pointer.js.map +1 -1
  23. package/dist/Touch.d.ts +73 -27
  24. package/dist/Touch.d.ts.map +1 -1
  25. package/dist/Touch.js +25 -30
  26. package/dist/Touch.js.map +1 -1
  27. package/dist/index.d.ts +10 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +10 -1
  30. package/dist/index.js.map +1 -1
  31. package/dist/internal/buttons.d.ts +52 -0
  32. package/dist/internal/buttons.d.ts.map +1 -0
  33. package/dist/internal/buttons.js +211 -0
  34. package/dist/internal/buttons.js.map +1 -0
  35. package/dist/internal/introspect.d.ts +14 -0
  36. package/dist/internal/introspect.d.ts.map +1 -0
  37. package/dist/internal/introspect.js +19 -0
  38. package/dist/internal/introspect.js.map +1 -0
  39. package/dist/internal/used.d.ts +8 -0
  40. package/dist/internal/used.d.ts.map +1 -0
  41. package/dist/internal/used.js +14 -0
  42. package/dist/internal/used.js.map +1 -0
  43. package/dist/internal/vectors.d.ts +24 -0
  44. package/dist/internal/vectors.d.ts.map +1 -0
  45. package/dist/internal/vectors.js +22 -0
  46. package/dist/internal/vectors.js.map +1 -0
  47. package/package.json +4 -3
  48. package/src/Controls.ts +799 -0
  49. package/src/Gamepad.ts +747 -0
  50. package/src/InputCapture.ts +43 -24
  51. package/src/Keyboard.ts +395 -68
  52. package/src/Pointer.ts +392 -164
  53. package/src/Touch.ts +111 -54
  54. package/src/index.ts +10 -1
  55. package/src/internal/buttons.ts +222 -0
  56. package/src/internal/introspect.ts +23 -0
  57. package/src/internal/used.ts +14 -0
  58. package/src/internal/vectors.ts +36 -0
@@ -0,0 +1,211 @@
1
+ import * as Result from "@typeonce/ritmo/Result";
2
+ import { directionName, directions, isVectorBinding, zero } from "./vectors.js";
3
+ const idleState = { held: false, pressed: false, released: false };
4
+ /**
5
+ * The held buttons, the bound actions, and the edges since the previous
6
+ * take, shared by devices with named buttons (`Gamepad`, `Pointer`) and by
7
+ * their live and scripted forms, so all of them build snapshots the same way.
8
+ */
9
+ export const buttonTracker = (buttonNames, initial) => {
10
+ // Fixed at creation: a rebind swaps buttons, never the actions.
11
+ const names = Object.keys(initial);
12
+ let bindings = initial;
13
+ const actionsByButton = new Map();
14
+ const index = () => {
15
+ actionsByButton.clear();
16
+ for (const name of names) {
17
+ for (const button of bindings[name]) {
18
+ const bound = actionsByButton.get(button);
19
+ if (bound)
20
+ bound.push(name);
21
+ else
22
+ actionsByButton.set(button, [name]);
23
+ }
24
+ }
25
+ };
26
+ index();
27
+ const held = new Set();
28
+ const pressed = new Set();
29
+ const released = new Set();
30
+ /**
31
+ * Each held button and the actions it holds: those bound to it when it
32
+ * went down that are still bound to it.
33
+ */
34
+ const holding = new Map();
35
+ const pressedActions = new Set();
36
+ const releasedActions = new Set();
37
+ const isHeld = (name) => bindings[name].some((button) => holding.get(button)?.has(name) === true);
38
+ const up = (button) => {
39
+ if (!held.delete(button))
40
+ return;
41
+ released.add(button);
42
+ for (const name of holding.get(button) ?? [])
43
+ releasedActions.add(name);
44
+ holding.delete(button);
45
+ };
46
+ return {
47
+ held,
48
+ down(button) {
49
+ if (held.has(button))
50
+ return;
51
+ held.add(button);
52
+ pressed.add(button);
53
+ const bound = actionsByButton.get(button) ?? [];
54
+ holding.set(button, new Set(bound));
55
+ for (const name of bound)
56
+ pressedActions.add(name);
57
+ },
58
+ up,
59
+ upAll() {
60
+ for (const button of [...held])
61
+ up(button);
62
+ },
63
+ rebind(next) {
64
+ const before = names.filter(isHeld);
65
+ bindings = next;
66
+ index();
67
+ // A held button keeps only the actions still bound to it; new ones wait for a fresh press.
68
+ for (const [button, actions] of holding) {
69
+ const bound = actionsByButton.get(button) ?? [];
70
+ for (const name of actions)
71
+ if (!bound.includes(name))
72
+ actions.delete(name);
73
+ }
74
+ for (const name of before)
75
+ if (!isHeld(name))
76
+ releasedActions.add(name);
77
+ },
78
+ /** The buttons and actions since the previous take; starts a new press/release window. */
79
+ take() {
80
+ const buttons = {};
81
+ for (const name of buttonNames) {
82
+ const isDown = held.has(name);
83
+ buttons[name] = isDown || pressed.has(name) || released.has(name)
84
+ ? { held: isDown, pressed: pressed.has(name), released: released.has(name) && !isDown }
85
+ : idleState;
86
+ }
87
+ const actions = {};
88
+ for (const name of names) {
89
+ const isDown = isHeld(name);
90
+ actions[name] = { held: isDown, pressed: pressedActions.has(name), released: releasedActions.has(name) && !isDown };
91
+ }
92
+ pressed.clear();
93
+ released.clear();
94
+ pressedActions.clear();
95
+ releasedActions.clear();
96
+ return { actions, buttons };
97
+ }
98
+ };
99
+ };
100
+ /** Every button idle, by name. */
101
+ export const idleButtons = (buttonNames) => {
102
+ const buttons = {};
103
+ for (const name of buttonNames)
104
+ buttons[name] = idleState;
105
+ return buttons;
106
+ };
107
+ /** Every button action of `bindings` idle (vector actions are in {@link idleVectors}). */
108
+ export const idleActions = (bindings) => {
109
+ const actions = {};
110
+ for (const [name, entry] of Object.entries(bindings))
111
+ if (!isVectorBinding(entry))
112
+ actions[name] = idleState;
113
+ return actions;
114
+ };
115
+ /** Every vector action of `bindings` at rest. */
116
+ export const idleVectors = (bindings) => {
117
+ const vectors = {};
118
+ for (const [name, entry] of Object.entries(bindings))
119
+ if (isVectorBinding(entry))
120
+ vectors[name] = zero;
121
+ return vectors;
122
+ };
123
+ /**
124
+ * Each action's buttons for the button tracker, with the digital part of
125
+ * every vector action split into its four directions (`move.up`, ...).
126
+ */
127
+ export const flattenButtons = (bindings) => {
128
+ const flat = {};
129
+ for (const [name, entry] of Object.entries(bindings)) {
130
+ if (isVectorBinding(entry)) {
131
+ const vector = entry;
132
+ // All four, empty when unbound (a stick-only vector), so the tracker's
133
+ // names stay the same whichever way a rebind binds the vector.
134
+ for (const direction of directions) {
135
+ flat[directionName(name, direction)] = (vector[direction] ?? []);
136
+ }
137
+ }
138
+ else
139
+ flat[name] = entry;
140
+ }
141
+ return flat;
142
+ };
143
+ /** Splits taken flat actions into the button actions of `bindings`, and whether each vector direction is held. */
144
+ export const splitActions = (bindings, taken) => {
145
+ const actions = {};
146
+ for (const [name, entry] of Object.entries(bindings))
147
+ if (!isVectorBinding(entry))
148
+ actions[name] = taken[name];
149
+ return { actions, held: (vector, direction) => taken[directionName(vector, direction)]?.held === true };
150
+ };
151
+ /**
152
+ * Validates `data` as new buttons for exactly the actions of `bindings`:
153
+ * an object with the same action names, each a non-empty array of button
154
+ * names.
155
+ */
156
+ export const parseButtonRebinding = (buttonNames, bindings, data, sticks = []) => {
157
+ const invalid = (path, message) => Result.failure({ _tag: "InvalidRebinding", path, message });
158
+ if (typeof data !== "object" || data === null || Array.isArray(data))
159
+ return invalid("", "expected an object of action names");
160
+ const fields = data;
161
+ const names = Object.keys(bindings);
162
+ for (const name of Object.keys(fields)) {
163
+ if (!names.includes(name))
164
+ return invalid(name, `unknown action, expected one of ${names.join(", ")}`);
165
+ }
166
+ const known = new Set(buttonNames);
167
+ const buttonsAt = (value, path) => {
168
+ if (!Array.isArray(value) || value.length === 0)
169
+ return invalid(path, "expected a non-empty array of button names");
170
+ for (let offset = 0; offset < value.length; offset++) {
171
+ if (!known.has(value[offset]))
172
+ return invalid(`${path}[${offset}]`, `expected one of ${buttonNames.join(", ")}`);
173
+ }
174
+ return Result.success([...value]);
175
+ };
176
+ const rebinding = {};
177
+ for (const name of names) {
178
+ const value = fields[name];
179
+ if (isVectorBinding(bindings[name])) {
180
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
181
+ return invalid(name, "expected { stick } and/or { up, down, left, right } buttons for a vector action");
182
+ }
183
+ const parts = value;
184
+ const vector = { _tag: "Vector" };
185
+ if (parts["stick"] !== undefined) {
186
+ if (typeof parts["stick"] !== "string" || !sticks.includes(parts["stick"]))
187
+ return invalid(`${name}.stick`, `expected one of ${sticks.join(", ")}`);
188
+ vector["stick"] = parts["stick"];
189
+ }
190
+ const given = directions.filter((direction) => parts[direction] !== undefined);
191
+ if (given.length > 0) {
192
+ for (const direction of directions) {
193
+ const buttons = buttonsAt(parts[direction], `${name}.${direction}`);
194
+ if (!buttons.ok)
195
+ return buttons;
196
+ vector[direction] = buttons.value;
197
+ }
198
+ }
199
+ else if (vector["stick"] === undefined)
200
+ return invalid(name, "expected a stick or buttons for up, down, left, and right");
201
+ rebinding[name] = vector;
202
+ continue;
203
+ }
204
+ const buttons = buttonsAt(value, name);
205
+ if (!buttons.ok)
206
+ return buttons;
207
+ rebinding[name] = buttons.value;
208
+ }
209
+ return Result.success(rebinding);
210
+ };
211
+ //# sourceMappingURL=buttons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buttons.js","sourceRoot":"","sources":["../../src/internal/buttons.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The keys a keyboard device binds now, as they read in a lint (`" "`,
3
+ * `KeyW`): what a player pool compares to report two players sharing a key.
4
+ * Live and scripted keyboards implement it.
5
+ */
6
+ export declare const boundKeys: unique symbol;
7
+ export interface ReportsBoundKeys {
8
+ readonly [boundKeys]?: () => ReadonlyArray<string>;
9
+ }
10
+ /** Records that `owner` takes the snapshots of `device`. */
11
+ export declare const claim: (device: object, owner: string) => void;
12
+ /** The sources that take the snapshots of `device`. */
13
+ export declare const ownersOf: (device: object) => ReadonlyArray<string>;
14
+ //# sourceMappingURL=introspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect.d.ts","sourceRoot":"","sources":["../../src/internal/introspect.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,SAAS,eAAoC,CAAA;AAE1D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,aAAa,CAAC,MAAM,CAAC,CAAA;CACnD;AAKD,4DAA4D;AAC5D,eAAO,MAAM,KAAK,WAAY,MAAM,SAAS,MAAM,KAAG,IAIrD,CAAA;AAED,uDAAuD;AACvD,eAAO,MAAM,QAAQ,WAAY,MAAM,KAAG,aAAa,CAAC,MAAM,CAA6B,CAAA"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The keys a keyboard device binds now, as they read in a lint (`" "`,
3
+ * `KeyW`): what a player pool compares to report two players sharing a key.
4
+ * Live and scripted keyboards implement it.
5
+ */
6
+ export const boundKeys = Symbol("ritmo-browser/boundKeys");
7
+ /** Every source a device was handed to (a merge, a pool), to report a device used twice. */
8
+ const owners = new WeakMap();
9
+ /** Records that `owner` takes the snapshots of `device`. */
10
+ export const claim = (device, owner) => {
11
+ const list = owners.get(device);
12
+ if (list === undefined)
13
+ owners.set(device, [owner]);
14
+ else
15
+ list.push(owner);
16
+ };
17
+ /** The sources that take the snapshots of `device`. */
18
+ export const ownersOf = (device) => owners.get(device) ?? [];
19
+ //# sourceMappingURL=introspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect.js","sourceRoot":"","sources":["../../src/internal/introspect.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAA;AAM1D,4FAA4F;AAC5F,MAAM,MAAM,GAAG,IAAI,OAAO,EAAyB,CAAA;AAEnD,4DAA4D;AAC5D,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,MAAc,EAAE,KAAa,EAAQ,EAAE;IAC3D,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAC/B,IAAI,IAAI,KAAK,SAAS;QAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;;QAC9C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AACvB,CAAC,CAAA;AAED,uDAAuD;AACvD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAyB,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAA"}
@@ -0,0 +1,8 @@
1
+ import type { ActionState } from "../Keyboard.ts";
2
+ /**
3
+ * Whether any action in a snapshot was pressed or is held: the `used` of a
4
+ * device's snapshot. Releases do not count, since a blur or a disconnect
5
+ * releases everything without the player touching the device.
6
+ */
7
+ export declare const anyUsed: (actions: Readonly<Record<string, ActionState>>) => boolean;
8
+ //# sourceMappingURL=used.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"used.d.ts","sourceRoot":"","sources":["../../src/internal/used.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD;;;;GAIG;AACH,eAAO,MAAM,OAAO,YAAa,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,KAAG,OAMxE,CAAA"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Whether any action in a snapshot was pressed or is held: the `used` of a
3
+ * device's snapshot. Releases do not count, since a blur or a disconnect
4
+ * releases everything without the player touching the device.
5
+ */
6
+ export const anyUsed = (actions) => {
7
+ for (const name in actions) {
8
+ const state = actions[name];
9
+ if (state.held || state.pressed)
10
+ return true;
11
+ }
12
+ return false;
13
+ };
14
+ //# sourceMappingURL=used.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"used.js","sourceRoot":"","sources":["../../src/internal/used.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAA8C,EAAW,EAAE;IACjF,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAE,CAAA;QAC5B,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,OAAO;YAAE,OAAO,IAAI,CAAA;IAC9C,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
@@ -0,0 +1,24 @@
1
+ /** A direction and strength, with length at most 1. `y` grows down the screen. */
2
+ export interface Vector {
3
+ readonly x: number;
4
+ readonly y: number;
5
+ }
6
+ /** The four directions a digital vector binding names. */
7
+ export declare const directions: readonly ["up", "down", "left", "right"];
8
+ /** One direction of a vector action; a keyboard timeline names it as `"move.right"`. */
9
+ export type Direction = (typeof directions)[number];
10
+ export declare const zero: Vector;
11
+ /** The internal action name of one direction of a vector, for timelines and the button trackers. */
12
+ export declare const directionName: (vector: string, direction: Direction) => string;
13
+ /**
14
+ * The vector four held directions give: opposite directions cancel and a
15
+ * diagonal has length 1, so it is not faster than a straight line.
16
+ */
17
+ export declare const digital: (up: boolean, down: boolean, left: boolean, right: boolean) => Vector;
18
+ /** The longer of two vectors, the first on a tie: how vectors from several sources combine. */
19
+ export declare const longer: (a: Vector, b: Vector) => Vector;
20
+ /** Whether a binding entry is a vector binding (`Keyboard.vector`, `Gamepad.vector`). */
21
+ export declare const isVectorBinding: (entry: unknown) => entry is {
22
+ readonly _tag: "Vector";
23
+ };
24
+ //# sourceMappingURL=vectors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vectors.d.ts","sourceRoot":"","sources":["../../src/internal/vectors.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,0DAA0D;AAC1D,eAAO,MAAM,UAAU,YAAI,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAU,CAAA;AAElE,wFAAwF;AACxF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;AAEnD,eAAO,MAAM,IAAI,EAAE,MAAuB,CAAA;AAE1C,oGAAoG;AACpG,eAAO,MAAM,aAAa,WAAY,MAAM,aAAa,SAAS,KAAG,MAAkC,CAAA;AAEvG;;;GAGG;AACH,eAAO,MAAM,OAAO,OAAQ,OAAO,QAAQ,OAAO,QAAQ,OAAO,SAAS,OAAO,KAAG,MAKnF,CAAA;AAID,+FAA+F;AAC/F,eAAO,MAAM,MAAM,MAAO,MAAM,KAAK,MAAM,KAAG,MAAqD,CAAA;AAEnG,yFAAyF;AACzF,eAAO,MAAM,eAAe,UAAW,OAAO,KAAG,KAAK,IAAI;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAC+C,CAAA"}
@@ -0,0 +1,22 @@
1
+ /** The four directions a digital vector binding names. */
2
+ export const directions = ["up", "down", "left", "right"];
3
+ export const zero = { x: 0, y: 0 };
4
+ /** The internal action name of one direction of a vector, for timelines and the button trackers. */
5
+ export const directionName = (vector, direction) => `${vector}.${direction}`;
6
+ /**
7
+ * The vector four held directions give: opposite directions cancel and a
8
+ * diagonal has length 1, so it is not faster than a straight line.
9
+ */
10
+ export const digital = (up, down, left, right) => {
11
+ const x = (right ? 1 : 0) - (left ? 1 : 0);
12
+ const y = (down ? 1 : 0) - (up ? 1 : 0);
13
+ if (x === 0 && y === 0)
14
+ return zero;
15
+ return x !== 0 && y !== 0 ? { x: x * Math.SQRT1_2, y: y * Math.SQRT1_2 } : { x, y };
16
+ };
17
+ const lengthSquared = (vector) => vector.x * vector.x + vector.y * vector.y;
18
+ /** The longer of two vectors, the first on a tie: how vectors from several sources combine. */
19
+ export const longer = (a, b) => lengthSquared(b) > lengthSquared(a) ? b : a;
20
+ /** Whether a binding entry is a vector binding (`Keyboard.vector`, `Gamepad.vector`). */
21
+ export const isVectorBinding = (entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry) && entry._tag === "Vector";
22
+ //# sourceMappingURL=vectors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vectors.js","sourceRoot":"","sources":["../../src/internal/vectors.ts"],"names":[],"mappings":"AAMA,0DAA0D;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAU,CAAA;AAKlE,MAAM,CAAC,MAAM,IAAI,GAAW,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;AAE1C,oGAAoG;AACpG,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAAc,EAAE,SAAoB,EAAU,EAAE,CAAC,GAAG,MAAM,IAAI,SAAS,EAAE,CAAA;AAEvG;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,EAAW,EAAE,IAAa,EAAE,IAAa,EAAE,KAAc,EAAU,EAAE;IAC3F,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1C,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACvC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACnC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;AACrF,CAAC,CAAA;AAED,MAAM,aAAa,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAA;AAE3F,+FAA+F;AAC/F,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAEnG,yFAAyF;AACzF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAc,EAAwC,EAAE,CACtF,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAK,KAAqC,CAAC,IAAI,KAAK,QAAQ,CAAA"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@typeonce/ritmo-browser",
3
- "version": "0.10.0",
4
- "description": "Browser fixed-step loop, keyboard actions, and input capture for Ritmo",
3
+ "version": "0.11.0",
4
+ "description": "Browser fixed-step loop, keyboard, gamepad, pointer, and touch actions, merged input, local multiplayer, and input capture for Ritmo",
5
5
  "author": "Sandro Maglione",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -19,6 +19,7 @@
19
19
  "ritmo",
20
20
  "browser",
21
21
  "keyboard",
22
+ "gamepad",
22
23
  "game-loop"
23
24
  ],
24
25
  "type": "module",
@@ -48,7 +49,7 @@
48
49
  "provenance": true
49
50
  },
50
51
  "dependencies": {
51
- "@typeonce/ritmo": "^0.10.0"
52
+ "@typeonce/ritmo": "^0.11.0"
52
53
  },
53
54
  "engines": {
54
55
  "node": ">=20"