js-game-zero 0.0.0-stage → 0.4.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-q9m20c2h.js +7972 -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 +8545 -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 +392 -0
  39. package/dist/reference/storage.md +90 -0
  40. package/dist/rendering.d.ts +216 -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
@@ -0,0 +1,88 @@
1
+ export type JsonValue = null | boolean | number | string | JsonValue[] | {
2
+ readonly [key: string]: JsonValue;
3
+ };
4
+ export type StorageAdapter = {
5
+ readonly path: string;
6
+ load(): Promise<string | null>;
7
+ loadSync?(): string | null;
8
+ save(text: string): Promise<void> | void;
9
+ };
10
+ export type BrowserStorageLike = {
11
+ getItem(key: string): string | null;
12
+ setItem(key: string, value: string): void;
13
+ };
14
+ export type LocalStorageAdapterOptions = {
15
+ readonly projectId?: string;
16
+ readonly path?: string;
17
+ readonly localStorage?: BrowserStorageLike;
18
+ };
19
+ export type StorageOptions = {
20
+ readonly adapter?: StorageAdapter;
21
+ readonly projectId?: string;
22
+ readonly path?: string;
23
+ };
24
+ export declare class JsonStorageError extends Error {
25
+ readonly path: string;
26
+ constructor(path: string, message: string);
27
+ }
28
+ /** Keyed by a symbol so no storage key can collide with it. */
29
+ declare const savedText: unique symbol;
30
+ export declare class Storage {
31
+ private readonly adapter;
32
+ private readonly values;
33
+ private readonly listeners;
34
+ /** A load() that loadSync() started and found to be asynchronous. */
35
+ private pendingLoad;
36
+ /** The JSON last saved or loaded: what the adapter holds, as far as this storage knows. */
37
+ [savedText]: string;
38
+ constructor(options?: StorageOptions);
39
+ get path(): string;
40
+ get(key: string, defaultValue?: unknown): unknown;
41
+ set(key: string, value: unknown): void;
42
+ setDefault(key: string, defaultValue: unknown): unknown;
43
+ has(key: string): boolean;
44
+ delete(key: string): boolean;
45
+ clear(): void;
46
+ keys(): string[];
47
+ toJSON(): Record<string, JsonValue>;
48
+ /**
49
+ * Subscribes to any mutation (set/delete/clear/setDefault-insert),
50
+ * including mutations made through the PGZero-style proxy (e.g.
51
+ * `storage.score = 5`). Returns an unsubscribe function. Used by the
52
+ * runtime to drive debounced auto-save; loading does not notify.
53
+ */
54
+ onChange(listener: () => void): () => void;
55
+ save(): Promise<void>;
56
+ load(): Promise<void>;
57
+ /**
58
+ * Loads synchronously when the adapter can: with its `loadSync()`, or
59
+ * with a `load()` that returns its text rather than a Promise. A `load()`
60
+ * that turns out to be asynchronous is kept for `load()` to finish, so
61
+ * falling back to it still reads the store only once.
62
+ */
63
+ loadSync(): boolean;
64
+ private applyLoadedText;
65
+ private notify;
66
+ private jsonObject;
67
+ }
68
+ /**
69
+ * Whether `storage` holds anything its last save or load didn't, including a
70
+ * change inside a stored object or list (`storage.highScores.push(...)`),
71
+ * which no set() announces. Throws a JsonStorageError, naming the key, when
72
+ * a stored value has since become one JSON can't hold.
73
+ */
74
+ export declare function hasUnsavedChanges(storage: Storage): boolean;
75
+ export declare function createStorage(options?: StorageOptions): Storage;
76
+ export declare function createLocalStorageAdapter(options?: LocalStorageAdapterOptions): StorageAdapter;
77
+ export declare function validateJsonValue(value: unknown, path?: string): void;
78
+ /** Default backing instance used when no runtime-scoped storage is active. */
79
+ export declare const defaultStorage: Storage;
80
+ export declare function setActiveStorage(nextStorage: Storage | null): Storage | null;
81
+ export declare function getActiveStorage(): Storage;
82
+ /**
83
+ * PGZero-style process-level convenience proxy. Runtime callbacks scope this
84
+ * proxy to their own Storage instance; outside a runtime it uses a default
85
+ * local-storage-backed instance.
86
+ */
87
+ export declare const storage: Storage;
88
+ export {};
package/dist/tone.d.ts ADDED
@@ -0,0 +1,81 @@
1
+ import { type AudioUnlockState } from "./audio.js";
2
+ export type Waveform = OscillatorType;
3
+ /** pgzero's tone.Waveform names that don't match the Web Audio OscillatorType spelling. */
4
+ export type WaveformAlias = "sin" | "saw";
5
+ export type WaveformInput = Waveform | WaveformAlias;
6
+ export type AudioParamLike = {
7
+ value: number;
8
+ setValueAtTime?: (value: number, startTime: number) => void;
9
+ };
10
+ export type OscillatorNodeLike = {
11
+ type: Waveform;
12
+ frequency: AudioParamLike;
13
+ connect(destination: unknown): unknown;
14
+ start(when?: number): void;
15
+ stop(when?: number): void;
16
+ };
17
+ export type GainNodeLike = {
18
+ gain: AudioParamLike;
19
+ connect(destination: unknown): unknown;
20
+ };
21
+ export type AudioContextLike = {
22
+ readonly destination: unknown;
23
+ currentTime: number;
24
+ state?: string;
25
+ resume?: () => Promise<void>;
26
+ createOscillator(): OscillatorNodeLike;
27
+ createGain(): GainNodeLike;
28
+ };
29
+ export type ToneOptions = {
30
+ readonly audioContext?: AudioContextLike;
31
+ readonly unlockState?: AudioUnlockState;
32
+ readonly waveform?: WaveformInput;
33
+ readonly volume?: number;
34
+ };
35
+ export type TonePlayOptions = Omit<ToneOptions, "audioContext" | "unlockState">;
36
+ /** pgzero's tone module defaults to volume 0.8 (see pgzero.tone._convert_args). */
37
+ export declare const DEFAULT_TONE_VOLUME = 0.8;
38
+ export type ToneSpec = {
39
+ readonly frequency: number;
40
+ readonly duration: number;
41
+ readonly waveform: Waveform;
42
+ readonly volume: number;
43
+ };
44
+ export type TonePlayback = ToneSpec & {
45
+ readonly startedAt: number;
46
+ readonly stoppedAt: number;
47
+ };
48
+ export type ToneDebugState = {
49
+ readonly unlocked: boolean;
50
+ readonly contextState: string | null;
51
+ readonly scheduled: readonly TonePlayback[];
52
+ };
53
+ export declare class CreatedTone implements ToneSpec {
54
+ readonly frequency: number;
55
+ readonly duration: number;
56
+ readonly waveform: Waveform;
57
+ readonly volume: number;
58
+ private readonly generator;
59
+ constructor(generator: ToneGenerator, spec: ToneSpec);
60
+ play(options?: TonePlayOptions): Promise<TonePlayback>;
61
+ }
62
+ export declare class ToneGenerator {
63
+ private contextValue;
64
+ private readonly unlockState;
65
+ private readonly scheduledTones;
66
+ constructor(options?: ToneOptions);
67
+ create(noteOrFrequency: string | number, duration?: number, options?: TonePlayOptions): CreatedTone;
68
+ play(noteOrFrequency: string | number, duration?: number, options?: TonePlayOptions): Promise<TonePlayback>;
69
+ private start;
70
+ unlock(): Promise<boolean>;
71
+ isUnlocked(): boolean;
72
+ debugState(): ToneDebugState;
73
+ private createSpec;
74
+ private getContext;
75
+ }
76
+ export declare function createToneGenerator(options?: ToneOptions): ToneGenerator;
77
+ export declare const tone: ToneGenerator;
78
+ export declare function parseToneFrequency(noteOrFrequency: string | number): number;
79
+ export declare function noteToFrequency(noteName: string): number;
80
+ export declare function requireToneDuration(duration: number): number;
81
+ export declare function normalizeWaveform(waveform: WaveformInput): Waveform;
@@ -0,0 +1,24 @@
1
+ import type { InputDispatcher } from "./events.js";
2
+ export type TouchButton = "up" | "down" | "left" | "right" | "a" | "b" | "start" | "select";
3
+ export type TouchControlsOptions = Partial<Record<TouchButton, number>> & {
4
+ /** Auto shows controls on devices with touch input; always also shows them on desktop. */
5
+ readonly show?: "auto" | "always";
6
+ };
7
+ export type TouchControlsConfig = boolean | TouchControlsOptions;
8
+ export type TouchControlsSettings = {
9
+ readonly show: "auto" | "always";
10
+ readonly buttons: ReadonlyArray<readonly [TouchButton, number]>;
11
+ };
12
+ export declare function normalizeTouchControls(value: unknown): TouchControlsSettings | null;
13
+ /**
14
+ * Mount a responsive control dock at the bottom of the game's available
15
+ * space. The canvas is fitted by its logical `screen` size, since density
16
+ * multiplies its pixel size.
17
+ */
18
+ export declare function mountTouchControls(canvas: HTMLCanvasElement, settings: TouchControlsSettings | null, dispatcher: InputDispatcher, invoke: (callback: () => void) => void, screen?: {
19
+ readonly width: number;
20
+ readonly height: number;
21
+ }): {
22
+ reset(): void;
23
+ detach(): void;
24
+ };
@@ -0,0 +1,11 @@
1
+ import type { InputDispatcher } from "./events.js";
2
+ type PointerTarget = Parameters<InputDispatcher["handleMouseDown"]>[1];
3
+ /**
4
+ * Touch and pen use the existing mouse hooks, with one canvas pointer at a
5
+ * time. Positions map onto `target`, which reports the logical screen size.
6
+ */
7
+ export declare function attachTouchPointer(canvas: HTMLCanvasElement, dispatcher: InputDispatcher, invoke: (callback: () => void) => void, target?: PointerTarget): {
8
+ reset(): void;
9
+ detach(): void;
10
+ };
11
+ export {};
package/dist/util.d.ts ADDED
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Internal cross-cutting utilities shared between core modules. This module
3
+ * is intentionally NOT re-exported from `index.ts`, so none of these helpers
4
+ * become part of the public package API. The only geometry dependency is a
5
+ * type-only import, so there is no runtime import cycle.
6
+ */
7
+ import type { Point } from "./geometry.js";
8
+ /** Standard Levenshtein edit distance between two strings. */
9
+ export declare function levenshtein(a: string, b: string): number;
10
+ /**
11
+ * Optimal string alignment distance: Levenshtein where swapping two adjacent
12
+ * characters (`widht` for `width`) costs one edit instead of two.
13
+ */
14
+ export declare function editDistance(a: string, b: string): number;
15
+ /** Case- and underscore-insensitive form, so `filled_circle` meets `filledCircle`. */
16
+ export declare function looseName(name: string): string;
17
+ /**
18
+ * The candidate `name` most plausibly misspells, if any. Capitals and
19
+ * underscores don't count, so another spelling of a name (`filled_circle`,
20
+ * `on_key_down`, `Screen`) is always matched. Short names get one edit of
21
+ * slack and longer ones two (so `drow` and `onKeyDwon` match while `row` and
22
+ * `dow` do not), a transposition counts as one edit, and a name that
23
+ * contains a candidate whole (`redraw`, `updates`) is taken as deliberately
24
+ * derived from it rather than mistyped.
25
+ */
26
+ export declare function closestName(name: string, candidates: Iterable<string>): string | undefined;
27
+ /**
28
+ * A value as an error message should show it: strings quoted, lists as
29
+ * lists, and numbers as written (`NaN`, not JSON's `null`).
30
+ */
31
+ export declare function describeValue(value: unknown): string;
32
+ /** ` Did you mean NAME?` for a likely misspelling, or an empty string. */
33
+ export declare function didYouMean(name: string, candidates: Iterable<string>): string;
34
+ /**
35
+ * Throws a TypeError naming the first key of `options` that `allowed` does
36
+ * not contain, with a suggestion when the key looks like a typo — so a
37
+ * misspelled option fails loudly instead of being silently ignored.
38
+ */
39
+ export declare function rejectUnknownOptions(options: object, allowed: ReadonlySet<string>, label: string): void;
40
+ /** True when `value` is a thenable (a Promise or Promise-like object). */
41
+ export declare function isPromiseLike<T>(value: unknown): value is PromiseLike<T>;
42
+ export declare function clamp(value: number, minimum: number, maximum: number): number;
43
+ export declare function isFiniteNumber(value: unknown): value is number;
44
+ export declare function requireFiniteNumber(value: unknown, label: string): number;
45
+ export declare function isPair(value: unknown): value is readonly [number, number];
46
+ /**
47
+ * Validates that `value` is a `[number, number]` tuple of finite numbers,
48
+ * returning a fresh mutable `Point`. Shared by geometry/actor/assets/
49
+ * rendering, which each used to define an identical private copy.
50
+ */
51
+ export declare function requirePoint(value: unknown, label: string): Point;
52
+ export declare function horizontalAnchorOffset(value: number | "left" | "center" | "middle" | "right", width: number): number;
53
+ export declare function verticalAnchorOffset(value: number | "top" | "center" | "middle" | "bottom", height: number): number;
54
+ /**
55
+ * The compound Rect-anchor position keys (`topLeft`…`center`), shared by the
56
+ * actor, assets, and rendering modules for validating position keywords.
57
+ */
58
+ export declare const rectPositionKeys: readonly ["topLeft", "topRight", "bottomLeft", "bottomRight", "midTop", "midLeft", "midRight", "midBottom", "center"];
59
+ /** Recognized image asset file extensions. */
60
+ export declare const imageExtensions: string[];
61
+ /** Recognized sound asset file extensions. */
62
+ export declare const soundExtensions: string[];
package/package.json CHANGED
@@ -1,6 +1,71 @@
1
1
  {
2
2
  "name": "js-game-zero",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.4.0",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "description": "A beginner-friendly framework for browser games in the spirit of Pygame Zero: set WIDTH and HEIGHT, write draw(), and play. Actors, drawing, input, sound, animation and storage, with a script-tag build.",
7
+ "keywords": [
8
+ "game",
9
+ "gamedev",
10
+ "canvas",
11
+ "education",
12
+ "beginner",
13
+ "pygame-zero"
14
+ ],
15
+ "author": "Taha Rafiq",
16
+ "homepage": "https://github.com/Leaf-Learning/js-game-zero#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/Leaf-Learning/js-game-zero/issues"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/Leaf-Learning/js-game-zero.git",
23
+ "directory": "packages/js-game-zero"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "main": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
+ "jsdelivr": "./dist/jgz.js",
31
+ "unpkg": "./dist/jgz.js",
32
+ "files": [
33
+ "dist",
34
+ "LICENSE"
35
+ ],
36
+ "sideEffects": [
37
+ "./dist/jgz.js"
38
+ ],
39
+ "exports": {
40
+ ".": {
41
+ "types": "./dist/index.d.ts",
42
+ "import": "./dist/index.js",
43
+ "default": "./dist/index.js"
44
+ },
45
+ "./host": {
46
+ "types": "./dist/host.d.ts",
47
+ "import": "./dist/host.js",
48
+ "default": "./dist/host.js"
49
+ },
50
+ "./node": {
51
+ "types": "./dist/node.d.ts",
52
+ "import": "./dist/node.js",
53
+ "default": "./dist/node.js"
54
+ },
55
+ "./reference": {
56
+ "types": "./dist/reference/index.d.ts",
57
+ "import": "./dist/reference/index.js",
58
+ "default": "./dist/reference/index.js"
59
+ },
60
+ "./reference/*.md": "./dist/reference/*.md",
61
+ "./iife": {
62
+ "types": "./dist/browser.d.ts",
63
+ "default": "./dist/jgz.js"
64
+ },
65
+ "./package.json": "./package.json"
66
+ },
67
+ "scripts": {
68
+ "build": "bun ../../scripts/build.ts js-game-zero",
69
+ "test": "bun test"
70
+ }
71
+ }