js-game-zero 0.0.0-stage → 0.3.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 (53) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +138 -2
  3. package/dist/active-service.d.ts +21 -0
  4. package/dist/actor.d.ts +182 -0
  5. package/dist/animation.d.ts +61 -0
  6. package/dist/assets.d.ts +148 -0
  7. package/dist/audio.d.ts +150 -0
  8. package/dist/browser-asset-backends.d.ts +8 -0
  9. package/dist/browser.d.ts +10 -0
  10. package/dist/chunk-brk0rjcy.js +7846 -0
  11. package/dist/clock.d.ts +29 -0
  12. package/dist/color.d.ts +15 -0
  13. package/dist/events.d.ts +145 -0
  14. package/dist/friendly-names.d.ts +43 -0
  15. package/dist/geometry.d.ts +125 -0
  16. package/dist/helpers.d.ts +28 -0
  17. package/dist/host.d.ts +58 -0
  18. package/dist/host.js +435 -0
  19. package/dist/index.d.ts +340 -0
  20. package/dist/index.js +258 -0
  21. package/dist/input.d.ts +200 -0
  22. package/dist/inspection.d.ts +58 -0
  23. package/dist/jgz.js +8419 -0
  24. package/dist/node.d.ts +14 -0
  25. package/dist/node.js +145 -0
  26. package/dist/pixel-density.d.ts +23 -0
  27. package/dist/random.d.ts +31 -0
  28. package/dist/reference/actor.md +197 -0
  29. package/dist/reference/audio.md +128 -0
  30. package/dist/reference/clock.md +150 -0
  31. package/dist/reference/helpers.md +46 -0
  32. package/dist/reference/hooks.md +379 -0
  33. package/dist/reference/index.d.ts +2 -0
  34. package/dist/reference/index.js +39 -0
  35. package/dist/reference/loaders.md +164 -0
  36. package/dist/reference/rect.md +129 -0
  37. package/dist/reference/runtime.md +478 -0
  38. package/dist/reference/screen.md +313 -0
  39. package/dist/reference/storage.md +90 -0
  40. package/dist/rendering.d.ts +188 -0
  41. package/dist/runtime-contracts.d.ts +117 -0
  42. package/dist/runtime-diagnostics.d.ts +37 -0
  43. package/dist/runtime-persistence.d.ts +32 -0
  44. package/dist/runtime-source.d.ts +82 -0
  45. package/dist/runtime.d.ts +81 -0
  46. package/dist/source-scan.d.ts +49 -0
  47. package/dist/storage-path.d.ts +3 -0
  48. package/dist/storage.d.ts +88 -0
  49. package/dist/tone.d.ts +81 -0
  50. package/dist/touch-controls.d.ts +24 -0
  51. package/dist/touch-pointer.d.ts +11 -0
  52. package/dist/util.d.ts +62 -0
  53. package/package.json +69 -4
package/dist/host.js ADDED
@@ -0,0 +1,435 @@
1
+ /*!
2
+ * js-game-zero 0.3.0
3
+ * https://github.com/Leaf-Learning/js-game-zero
4
+ *
5
+ * MIT License
6
+ *
7
+ * Copyright (c) 2026 Taha Rafiq
8
+ * Copyright (c) 2001 Robert Penner (easing equations)
9
+ *
10
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ * of this software and associated documentation files (the "Software"), to deal
12
+ * in the Software without restriction, including without limitation the rights
13
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ * copies of the Software, and to permit persons to whom the Software is
15
+ * furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in all
18
+ * copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ * SOFTWARE.
27
+ */
28
+ import {
29
+ Actor,
30
+ AudioUnlockState,
31
+ BrowserSoundAsset,
32
+ InputDispatcher,
33
+ MusicPlayer,
34
+ Rect,
35
+ ToneGenerator,
36
+ ZRect,
37
+ assetUrl,
38
+ audioUnlock,
39
+ buttonsFromBrowserButtons,
40
+ clampVolume,
41
+ collectRuntimeDiagnostics,
42
+ createAssetLoaders,
43
+ createBrowserSoundAsset,
44
+ createFontLoader,
45
+ createImageLoader,
46
+ createInputDispatcher,
47
+ createLocalStorageAdapter,
48
+ createMusicLoader,
49
+ createMusicPlayer,
50
+ createSeededRandom,
51
+ createSoundLoader,
52
+ createStorage,
53
+ createToneGenerator,
54
+ dispatchHook,
55
+ drawnOn,
56
+ fitTextboxFontSize,
57
+ getParameterNames,
58
+ getScreen,
59
+ getSourceInspector,
60
+ layoutText,
61
+ loadImages,
62
+ mapBrowserKeyEvent,
63
+ mapBrowserMouseButton,
64
+ mapBrowserMouseEvent,
65
+ mapBrowserWheelEvent,
66
+ normalizeColor,
67
+ normalizeWaveform,
68
+ noteToFrequency,
69
+ parseToneFrequency,
70
+ setScreen,
71
+ validateAssetName
72
+ } from "./chunk-brk0rjcy.js";
73
+
74
+ // packages/js-game-zero/src/inspection.ts
75
+ var MAX_DEPTH = 6;
76
+ var MAX_COLLECTION_SIZE = 100;
77
+ var MAX_STRING_LENGTH = 1e4;
78
+ function serializeGameValue(value) {
79
+ return serialize(value, 0, new WeakSet);
80
+ }
81
+ function serialize(value, depth, ancestors) {
82
+ if (value === null || typeof value === "boolean")
83
+ return value;
84
+ if (typeof value === "string") {
85
+ return value.length <= MAX_STRING_LENGTH ? value : `${value.slice(0, MAX_STRING_LENGTH)}…`;
86
+ }
87
+ if (typeof value === "number") {
88
+ if (Number.isNaN(value))
89
+ return tagged("Number", { value: "NaN" });
90
+ if (value === Infinity)
91
+ return tagged("Number", { value: "Infinity" });
92
+ if (value === -Infinity)
93
+ return tagged("Number", { value: "-Infinity" });
94
+ if (Object.is(value, -0))
95
+ return tagged("Number", { value: "-0" });
96
+ return value;
97
+ }
98
+ if (value === undefined)
99
+ return tagged("Undefined");
100
+ if (typeof value === "bigint") {
101
+ return tagged("BigInt", { value: String(value) });
102
+ }
103
+ if (typeof value === "symbol") {
104
+ return tagged("Symbol", { value: value.description ?? "" });
105
+ }
106
+ if (typeof value === "function") {
107
+ return tagged("Function", { name: value.name || "anonymous" });
108
+ }
109
+ if (depth >= MAX_DEPTH)
110
+ return tagged("Truncated", { reason: "depth" });
111
+ if (ancestors.has(value))
112
+ return tagged("Circular");
113
+ ancestors.add(value);
114
+ try {
115
+ if (value instanceof Actor)
116
+ return serializeActor(value, depth, ancestors);
117
+ if (value instanceof ZRect)
118
+ return serializeRect(value, "ZRect");
119
+ if (value instanceof Rect)
120
+ return serializeRect(value, "Rect");
121
+ if (value instanceof Date) {
122
+ return tagged("Date", {
123
+ value: Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString()
124
+ });
125
+ }
126
+ if (value instanceof Error) {
127
+ return tagged("Error", { name: value.name, message: value.message });
128
+ }
129
+ if (Array.isArray(value)) {
130
+ const items = value.slice(0, MAX_COLLECTION_SIZE).map((item) => serialize(item, depth + 1, ancestors));
131
+ if (value.length > MAX_COLLECTION_SIZE) {
132
+ items.push(tagged("Truncated", {
133
+ reason: "collection",
134
+ omitted: value.length - MAX_COLLECTION_SIZE
135
+ }));
136
+ }
137
+ return items;
138
+ }
139
+ if (value instanceof Set) {
140
+ return tagged("Set", {
141
+ values: serializeCollection([...value], depth, ancestors),
142
+ size: value.size
143
+ });
144
+ }
145
+ if (value instanceof Map) {
146
+ const entries = [...value.entries()].slice(0, MAX_COLLECTION_SIZE).map(([key, item]) => [
147
+ serialize(key, depth + 1, ancestors),
148
+ serialize(item, depth + 1, ancestors)
149
+ ]);
150
+ return tagged("Map", {
151
+ entries,
152
+ size: value.size,
153
+ ...value.size > MAX_COLLECTION_SIZE ? { omitted: value.size - MAX_COLLECTION_SIZE } : {}
154
+ });
155
+ }
156
+ return serializeObject(value, depth, ancestors);
157
+ } finally {
158
+ ancestors.delete(value);
159
+ }
160
+ }
161
+ var actorInternalKeys = new Set([
162
+ "loader",
163
+ "screen",
164
+ "_image",
165
+ "_surface",
166
+ "_pos",
167
+ "_anchor",
168
+ "_angle",
169
+ "_opacity",
170
+ "_scale",
171
+ "_native",
172
+ "sizeSource",
173
+ "positionSource",
174
+ "imageLoadPromise",
175
+ "_images",
176
+ "_fps",
177
+ "_loop",
178
+ "animationStart",
179
+ "clockSource"
180
+ ]);
181
+ function serializeActor(actor, depth, ancestors) {
182
+ let rect = null;
183
+ try {
184
+ rect = actor.rect();
185
+ } catch {}
186
+ const properties = {};
187
+ for (const key of Object.keys(actor).sort()) {
188
+ if (actorInternalKeys.has(key))
189
+ continue;
190
+ properties[key] = readProperty(actor, key, depth + 1, ancestors);
191
+ }
192
+ return tagged("Actor", {
193
+ image: actor.image,
194
+ pos: actor.pos,
195
+ x: actor.x,
196
+ y: actor.y,
197
+ width: safeNumber(() => actor.width),
198
+ height: safeNumber(() => actor.height),
199
+ angle: actor.angle,
200
+ opacity: actor.opacity,
201
+ scale: actor.scale,
202
+ anchor: [...actor.anchor],
203
+ rect: rect ? serializeRect(rect, "Rect") : null,
204
+ properties
205
+ });
206
+ }
207
+ function serializeRect(rect, type) {
208
+ return tagged(type, {
209
+ left: rect.left,
210
+ top: rect.top,
211
+ right: rect.right,
212
+ bottom: rect.bottom,
213
+ width: rect.width,
214
+ height: rect.height,
215
+ center: [...rect.center]
216
+ });
217
+ }
218
+ function serializeObject(value, depth, ancestors) {
219
+ const output = {};
220
+ const keys = Object.keys(value).sort();
221
+ for (const key of keys.slice(0, MAX_COLLECTION_SIZE)) {
222
+ output[key] = readProperty(value, key, depth + 1, ancestors);
223
+ }
224
+ if (keys.length > MAX_COLLECTION_SIZE) {
225
+ output.$truncated = tagged("Truncated", {
226
+ reason: "collection",
227
+ omitted: keys.length - MAX_COLLECTION_SIZE
228
+ });
229
+ }
230
+ const prototype = Object.getPrototypeOf(value);
231
+ const constructorName = prototype?.constructor?.name;
232
+ if (prototype !== Object.prototype && prototype !== null && typeof constructorName === "string" && constructorName !== "Object") {
233
+ return tagged(constructorName || "Object", { properties: output });
234
+ }
235
+ return output;
236
+ }
237
+ function readProperty(value, key, depth, ancestors) {
238
+ try {
239
+ return serialize(Reflect.get(value, key), depth, ancestors);
240
+ } catch (error) {
241
+ return tagged("Unreadable", {
242
+ message: error instanceof Error ? error.message : String(error)
243
+ });
244
+ }
245
+ }
246
+ function serializeCollection(values, depth, ancestors) {
247
+ const serialized = values.slice(0, MAX_COLLECTION_SIZE).map((value) => serialize(value, depth + 1, ancestors));
248
+ if (values.length > MAX_COLLECTION_SIZE) {
249
+ serialized.push(tagged("Truncated", {
250
+ reason: "collection",
251
+ omitted: values.length - MAX_COLLECTION_SIZE
252
+ }));
253
+ }
254
+ return serialized;
255
+ }
256
+ function safeNumber(read) {
257
+ try {
258
+ return serializeGameValue(read());
259
+ } catch {
260
+ return tagged("Unavailable");
261
+ }
262
+ }
263
+ function tagged(type, fields = {}) {
264
+ return { $type: type, ...fields };
265
+ }
266
+ var identifier = /^[\p{ID_Start}$_][\p{ID_Continue}$\u200C\u200D]*/u;
267
+ var unsafeProperties = new Set(["__proto__", "prototype", "constructor"]);
268
+ function parseStatePath(source) {
269
+ const invalid = () => {
270
+ throw new TypeError(`Invalid state path: ${JSON.stringify(source)}. Use a binding with .name and [index] after it, such as player.x or fish[0].y.`);
271
+ };
272
+ if (typeof source !== "string")
273
+ invalid();
274
+ const bindingMatch = identifier.exec(source);
275
+ if (!bindingMatch)
276
+ invalid();
277
+ const binding = bindingMatch[0];
278
+ const segments = [];
279
+ let cursor = binding.length;
280
+ while (cursor < source.length) {
281
+ if (source[cursor] === ".") {
282
+ const match = identifier.exec(source.slice(cursor + 1));
283
+ if (!match)
284
+ invalid();
285
+ if (unsafeProperties.has(match[0]))
286
+ invalid();
287
+ segments.push(match[0]);
288
+ cursor += match[0].length + 1;
289
+ continue;
290
+ }
291
+ if (source[cursor] === "[") {
292
+ const end = source.indexOf("]", cursor + 1);
293
+ if (end === -1)
294
+ invalid();
295
+ const raw = source.slice(cursor + 1, end);
296
+ if (!/^\d+$/.test(raw))
297
+ invalid();
298
+ const index = Number(raw);
299
+ if (!Number.isSafeInteger(index))
300
+ invalid();
301
+ segments.push(index);
302
+ cursor = end + 1;
303
+ continue;
304
+ }
305
+ invalid();
306
+ }
307
+ if (unsafeProperties.has(binding))
308
+ invalid();
309
+ return { source, binding, segments };
310
+ }
311
+ var DRAWN = "$drawn";
312
+ function createGameInspector(source, screen) {
313
+ const read = (path) => {
314
+ const parsed = typeof path === "string" ? parseStatePath(path) : path;
315
+ let value = parsed.binding === DRAWN && screen ? drawnOn(screen) : source.read(parsed.binding);
316
+ for (const segment of parsed.segments) {
317
+ if (value === null || typeof value !== "object" && typeof value !== "function") {
318
+ throw new TypeError(`Cannot read ${parsed.source}: ${String(segment)} has no parent value.`);
319
+ }
320
+ value = Reflect.get(value, segment);
321
+ }
322
+ return value;
323
+ };
324
+ return {
325
+ bindings: () => source.bindings(),
326
+ functions: () => source.functions(),
327
+ read,
328
+ inspect(path) {
329
+ if (path !== undefined)
330
+ return serializeGameValue(read(path));
331
+ const snapshot = {};
332
+ for (const binding of source.bindings()) {
333
+ try {
334
+ snapshot[binding] = serializeGameValue(source.read(binding));
335
+ } catch (error) {
336
+ snapshot[binding] = serializeGameValue(error);
337
+ }
338
+ }
339
+ return snapshot;
340
+ }
341
+ };
342
+ }
343
+ var hostInspectors = new WeakMap;
344
+ function getGameInspector(handle) {
345
+ const source = getSourceInspector(handle);
346
+ if (!source)
347
+ return null;
348
+ let inspector = hostInspectors.get(source);
349
+ if (!inspector) {
350
+ inspector = createGameInspector(source, handle.screen);
351
+ hostInspectors.set(source, inspector);
352
+ }
353
+ return inspector;
354
+ }
355
+
356
+ // packages/js-game-zero/src/host.ts
357
+ var assetUrl2 = assetUrl;
358
+ var audioUnlock2 = audioUnlock;
359
+ var buttonsFromBrowserButtons2 = buttonsFromBrowserButtons;
360
+ var clampVolume2 = clampVolume;
361
+ var collectRuntimeDiagnostics2 = collectRuntimeDiagnostics;
362
+ var createAssetLoaders2 = createAssetLoaders;
363
+ var createBrowserSoundAsset2 = createBrowserSoundAsset;
364
+ var createFontLoader2 = createFontLoader;
365
+ var createImageLoader2 = createImageLoader;
366
+ var createInputDispatcher2 = createInputDispatcher;
367
+ var createLocalStorageAdapter2 = createLocalStorageAdapter;
368
+ var createSeededRandom2 = createSeededRandom;
369
+ var createMusicLoader2 = createMusicLoader;
370
+ var createMusicPlayer2 = createMusicPlayer;
371
+ var createSoundLoader2 = createSoundLoader;
372
+ var createStorage2 = createStorage;
373
+ var createToneGenerator2 = createToneGenerator;
374
+ var dispatchHook2 = dispatchHook;
375
+ var fitTextboxFontSize2 = fitTextboxFontSize;
376
+ var getParameterNames2 = getParameterNames;
377
+ var getGameInspector2 = getGameInspector;
378
+ var getScreen2 = getScreen;
379
+ var layoutText2 = layoutText;
380
+ var loadImages2 = loadImages;
381
+ var mapBrowserKeyEvent2 = mapBrowserKeyEvent;
382
+ var mapBrowserMouseButton2 = mapBrowserMouseButton;
383
+ var mapBrowserMouseEvent2 = mapBrowserMouseEvent;
384
+ var mapBrowserWheelEvent2 = mapBrowserWheelEvent;
385
+ var normalizeColor2 = normalizeColor;
386
+ var normalizeWaveform2 = normalizeWaveform;
387
+ var parseStatePath2 = parseStatePath;
388
+ var noteToFrequency2 = noteToFrequency;
389
+ var parseToneFrequency2 = parseToneFrequency;
390
+ var serializeGameValue2 = serializeGameValue;
391
+ var setScreen2 = setScreen;
392
+ var validateAssetName2 = validateAssetName;
393
+ export {
394
+ validateAssetName2 as validateAssetName,
395
+ setScreen2 as setScreen,
396
+ serializeGameValue2 as serializeGameValue,
397
+ parseToneFrequency2 as parseToneFrequency,
398
+ parseStatePath2 as parseStatePath,
399
+ noteToFrequency2 as noteToFrequency,
400
+ normalizeWaveform2 as normalizeWaveform,
401
+ normalizeColor2 as normalizeColor,
402
+ mapBrowserWheelEvent2 as mapBrowserWheelEvent,
403
+ mapBrowserMouseEvent2 as mapBrowserMouseEvent,
404
+ mapBrowserMouseButton2 as mapBrowserMouseButton,
405
+ mapBrowserKeyEvent2 as mapBrowserKeyEvent,
406
+ loadImages2 as loadImages,
407
+ layoutText2 as layoutText,
408
+ getScreen2 as getScreen,
409
+ getParameterNames2 as getParameterNames,
410
+ getGameInspector2 as getGameInspector,
411
+ fitTextboxFontSize2 as fitTextboxFontSize,
412
+ dispatchHook2 as dispatchHook,
413
+ createToneGenerator2 as createToneGenerator,
414
+ createStorage2 as createStorage,
415
+ createSoundLoader2 as createSoundLoader,
416
+ createSeededRandom2 as createSeededRandom,
417
+ createMusicPlayer2 as createMusicPlayer,
418
+ createMusicLoader2 as createMusicLoader,
419
+ createLocalStorageAdapter2 as createLocalStorageAdapter,
420
+ createInputDispatcher2 as createInputDispatcher,
421
+ createImageLoader2 as createImageLoader,
422
+ createFontLoader2 as createFontLoader,
423
+ createBrowserSoundAsset2 as createBrowserSoundAsset,
424
+ createAssetLoaders2 as createAssetLoaders,
425
+ collectRuntimeDiagnostics2 as collectRuntimeDiagnostics,
426
+ clampVolume2 as clampVolume,
427
+ buttonsFromBrowserButtons2 as buttonsFromBrowserButtons,
428
+ audioUnlock2 as audioUnlock,
429
+ assetUrl2 as assetUrl,
430
+ ToneGenerator,
431
+ MusicPlayer,
432
+ InputDispatcher,
433
+ BrowserSoundAsset,
434
+ AudioUnlockState
435
+ };