@simpludify/web 0.1.7 → 0.2.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.
- package/README.md +3 -3
- package/dist/asset-loaders.d.ts +6 -0
- package/dist/assets.d.ts +158 -0
- package/dist/audio.d.ts +97 -0
- package/dist/canvas-visual.d.ts +2 -0
- package/dist/game.d.ts +30 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1425 -197
- package/dist/index.js.map +1 -1
- package/dist/renderer.d.ts +7 -2
- package/dist/shared-images.d.ts +9 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# @simpludify/web
|
|
2
2
|
|
|
3
|
-
Experimental v0.
|
|
3
|
+
Experimental v0.2.0 browser SDK for Simpludify, a code-first TypeScript 2D engine. APIs may change between 0.x releases. Includes Game, PixiJS rendering, browser input and Canvas/DOM UI adapters; re-exports the host-independent Core API. Core and PixiJS are installed as runtime dependencies, not bundled into this package.
|
|
4
4
|
|
|
5
|
-
Registry installation (check availability with `npm view @simpludify/web@0.
|
|
5
|
+
Registry installation (check availability with `npm view @simpludify/web@0.2.0 version`):
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
npm install @simpludify/web@0.
|
|
8
|
+
npm install @simpludify/web@0.2.0
|
|
9
9
|
npm install --save-dev vite typescript
|
|
10
10
|
```
|
|
11
11
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AssetAdapter } from "./assets.js";
|
|
2
|
+
import { type ImageResource, SharedImages } from "./shared-images.js";
|
|
3
|
+
export declare function assetResponse(url: string, signal: AbortSignal, reload: boolean): Promise<Response>;
|
|
4
|
+
export declare function loadImageResource(url: string, signal: AbortSignal, mode?: "explicit" | "reload"): Promise<ImageResource>;
|
|
5
|
+
export declare function createImagePool(load?: typeof loadImageResource): SharedImages;
|
|
6
|
+
export declare function browserAssetAdapter(images: SharedImages, decode: (data: ArrayBuffer) => Promise<AudioBuffer>): AssetAdapter;
|
package/dist/assets.d.ts
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { type LifetimeOwner, type Logger } from "@simpludify/core";
|
|
2
|
+
import type { ImageLease } from "./shared-images.js";
|
|
3
|
+
export interface AssetData {
|
|
4
|
+
image: Readonly<{
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}>;
|
|
8
|
+
audio: AudioBuffer | null;
|
|
9
|
+
font: string;
|
|
10
|
+
json: unknown;
|
|
11
|
+
}
|
|
12
|
+
export type AssetKind = keyof AssetData;
|
|
13
|
+
export type AssetStatus = "loading" | "ready" | "fallback" | "failed" | "released";
|
|
14
|
+
export interface AssetRetry {
|
|
15
|
+
/** One retry for a non-network failure. A promise can represent a caller-owned event. */
|
|
16
|
+
readonly once?: "immediate" | {
|
|
17
|
+
readonly delayMs: number;
|
|
18
|
+
} | {
|
|
19
|
+
readonly until: PromiseLike<unknown>;
|
|
20
|
+
};
|
|
21
|
+
/** Additional attempts after network failures, from zero to five. */
|
|
22
|
+
readonly network?: number;
|
|
23
|
+
readonly networkDelayMs?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface AssetLoadOptions {
|
|
26
|
+
readonly retry?: AssetRetry;
|
|
27
|
+
/** Deadline for the load and its retries, including any wait for a signal. */
|
|
28
|
+
readonly timeoutMs?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface AssetRequest<K extends AssetKind = AssetKind> extends AssetLoadOptions {
|
|
31
|
+
readonly kind: K;
|
|
32
|
+
readonly url: string | URL;
|
|
33
|
+
}
|
|
34
|
+
export interface AssetOptions {
|
|
35
|
+
/** Maximum number of idle, successfully loaded Assets per Game. */
|
|
36
|
+
readonly cacheEntries?: number;
|
|
37
|
+
readonly fallback?: Readonly<Partial<Record<Exclude<AssetKind, "json">, string | URL>>>;
|
|
38
|
+
}
|
|
39
|
+
export interface AssetProgress {
|
|
40
|
+
readonly total: number;
|
|
41
|
+
readonly completed: number;
|
|
42
|
+
readonly failed: number;
|
|
43
|
+
readonly fallback: number;
|
|
44
|
+
readonly loading: number;
|
|
45
|
+
readonly ratio: number;
|
|
46
|
+
readonly state: "idle" | "loading" | "complete";
|
|
47
|
+
}
|
|
48
|
+
export interface ImageAssetSource {
|
|
49
|
+
readonly kind: "image";
|
|
50
|
+
readonly url: string;
|
|
51
|
+
}
|
|
52
|
+
export interface AssetResource {
|
|
53
|
+
readonly value: unknown;
|
|
54
|
+
readonly image?: ImageLease;
|
|
55
|
+
release(): void;
|
|
56
|
+
}
|
|
57
|
+
export interface AssetAdapter {
|
|
58
|
+
load(kind: AssetKind, url: string, signal: AbortSignal, reload: boolean): Promise<AssetResource>;
|
|
59
|
+
fallback(kind: AssetKind, url: string | undefined, signal: AbortSignal): Promise<AssetResource | undefined>;
|
|
60
|
+
}
|
|
61
|
+
interface Entry {
|
|
62
|
+
readonly key: string;
|
|
63
|
+
readonly kind: AssetKind;
|
|
64
|
+
readonly url: string;
|
|
65
|
+
readonly id: string;
|
|
66
|
+
readonly listeners: Set<() => void>;
|
|
67
|
+
readonly validators: Set<(asset: AssetResource) => void>;
|
|
68
|
+
readonly users: Set<() => void>;
|
|
69
|
+
readonly first: Promise<void>;
|
|
70
|
+
usable(): void;
|
|
71
|
+
fail(error: unknown): void;
|
|
72
|
+
status: Exclude<AssetStatus, "released">;
|
|
73
|
+
asset: AssetResource | undefined;
|
|
74
|
+
task: Promise<void> | undefined;
|
|
75
|
+
controller: AbortController | undefined;
|
|
76
|
+
error: unknown;
|
|
77
|
+
}
|
|
78
|
+
export declare class AssetHandle<K extends AssetKind> {
|
|
79
|
+
readonly kind: K;
|
|
80
|
+
private readonly entry;
|
|
81
|
+
private readonly store;
|
|
82
|
+
private readonly remove;
|
|
83
|
+
readonly ready: Promise<this>;
|
|
84
|
+
private readonly cancelled;
|
|
85
|
+
private readonly imageSource;
|
|
86
|
+
/** @internal */
|
|
87
|
+
constructor(kind: K, entry: Entry, store: AssetStore, remove: () => void);
|
|
88
|
+
get id(): string;
|
|
89
|
+
get url(): string;
|
|
90
|
+
get status(): AssetStatus;
|
|
91
|
+
get loading(): boolean;
|
|
92
|
+
get value(): AssetData[K] | undefined;
|
|
93
|
+
get error(): unknown;
|
|
94
|
+
get progress(): AssetProgress;
|
|
95
|
+
/** Stable Renderable source. SpriteSheet accepts its URL. */
|
|
96
|
+
get source(): K extends "image" ? ImageAssetSource : undefined;
|
|
97
|
+
onChange(listener: (asset: this) => void): () => void;
|
|
98
|
+
/** @internal A playback or Game font owns a separate reference. */
|
|
99
|
+
retain(store: AssetStore): AssetHandle<K>;
|
|
100
|
+
reload(options?: AssetLoadOptions): Promise<this>;
|
|
101
|
+
release(): void;
|
|
102
|
+
}
|
|
103
|
+
export declare class AssetScope implements LifetimeOwner {
|
|
104
|
+
private readonly store;
|
|
105
|
+
private readonly global;
|
|
106
|
+
private readonly lifetime;
|
|
107
|
+
private readonly handles;
|
|
108
|
+
private readonly listeners;
|
|
109
|
+
private previous;
|
|
110
|
+
/** @internal */
|
|
111
|
+
constructor(store: AssetStore, owner?: LifetimeOwner, global?: boolean);
|
|
112
|
+
get disposed(): boolean;
|
|
113
|
+
onDispose(callback: () => void): () => void;
|
|
114
|
+
scope(owner?: LifetimeOwner): AssetScope;
|
|
115
|
+
load<K extends AssetKind>(request: AssetRequest<K>): AssetHandle<K>;
|
|
116
|
+
get progress(): AssetProgress;
|
|
117
|
+
onProgress(listener: (value: AssetProgress) => void): () => void;
|
|
118
|
+
private notify;
|
|
119
|
+
dispose(): void;
|
|
120
|
+
}
|
|
121
|
+
/** @internal One resource directory per Game. The adapter owns decoded resources. */
|
|
122
|
+
export declare class AssetStore {
|
|
123
|
+
private readonly adapter;
|
|
124
|
+
private readonly logger;
|
|
125
|
+
private readonly base;
|
|
126
|
+
private readonly prefix;
|
|
127
|
+
private readonly entries;
|
|
128
|
+
private readonly images;
|
|
129
|
+
private readonly idle;
|
|
130
|
+
private readonly listeners;
|
|
131
|
+
private readonly scopes;
|
|
132
|
+
private notifying;
|
|
133
|
+
private notificationScheduled;
|
|
134
|
+
private readonly capacity;
|
|
135
|
+
private readonly customFallback;
|
|
136
|
+
private sequence;
|
|
137
|
+
private dead;
|
|
138
|
+
constructor(adapter: AssetAdapter, logger: Logger, base: string, options?: AssetOptions);
|
|
139
|
+
register(scope: AssetScope): () => void;
|
|
140
|
+
observe(listener: () => void): () => void;
|
|
141
|
+
deliver(listener: () => unknown): void;
|
|
142
|
+
changed(): void;
|
|
143
|
+
get progress(): AssetProgress;
|
|
144
|
+
entry<K extends AssetKind>(request: AssetRequest<K>): Entry;
|
|
145
|
+
retain(entry: Entry, dispose: () => void): () => void;
|
|
146
|
+
private release;
|
|
147
|
+
private evict;
|
|
148
|
+
ready(entry: Entry, signal: AbortSignal): Promise<void>;
|
|
149
|
+
start(entry: Entry, options: AssetLoadOptions, reload: boolean): Promise<void>;
|
|
150
|
+
private attempt;
|
|
151
|
+
private commit;
|
|
152
|
+
private fallback;
|
|
153
|
+
private load;
|
|
154
|
+
image(id: string, signal: AbortSignal): Promise<ImageLease>;
|
|
155
|
+
dispose(): void;
|
|
156
|
+
}
|
|
157
|
+
export declare function isAssetImage(url: string): boolean;
|
|
158
|
+
export {};
|
package/dist/audio.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { type LifetimeOwner, type Logger } from "@simpludify/core";
|
|
2
|
+
import type { AssetHandle, AssetStore } from "./assets.js";
|
|
3
|
+
export interface AudioGroupOptions {
|
|
4
|
+
readonly parent?: string;
|
|
5
|
+
readonly volume?: number;
|
|
6
|
+
readonly maxVoices?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface AudioPlayOptions {
|
|
9
|
+
readonly group?: string;
|
|
10
|
+
readonly owner?: LifetimeOwner;
|
|
11
|
+
readonly volume?: number;
|
|
12
|
+
readonly loop?: boolean;
|
|
13
|
+
/** Optional cap for simultaneous instances of this asset. */
|
|
14
|
+
readonly maxVoices?: number;
|
|
15
|
+
}
|
|
16
|
+
export type AudioEndReason = "ended" | "stopped" | "replaced" | "failed";
|
|
17
|
+
export type AudioPlaybackState = "pending" | "playing" | "paused" | AudioEndReason;
|
|
18
|
+
export declare class AudioGroup {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly parent: AudioGroup | undefined;
|
|
21
|
+
private gain;
|
|
22
|
+
private level;
|
|
23
|
+
readonly maxVoices: number | undefined;
|
|
24
|
+
/** @internal */
|
|
25
|
+
constructor(name: string, parent: AudioGroup | undefined, options?: AudioGroupOptions);
|
|
26
|
+
get volume(): number;
|
|
27
|
+
set volume(value: number);
|
|
28
|
+
/** @internal */
|
|
29
|
+
node(context: AudioContext): GainNode;
|
|
30
|
+
/** @internal */
|
|
31
|
+
disconnect(): void;
|
|
32
|
+
}
|
|
33
|
+
export declare class AudioPlayback {
|
|
34
|
+
private readonly audio;
|
|
35
|
+
private readonly use;
|
|
36
|
+
readonly group: AudioGroup;
|
|
37
|
+
readonly finished: Promise<AudioEndReason>;
|
|
38
|
+
readonly assetId: string;
|
|
39
|
+
private resolve;
|
|
40
|
+
private phase;
|
|
41
|
+
private done;
|
|
42
|
+
private source;
|
|
43
|
+
private gain;
|
|
44
|
+
private buffer;
|
|
45
|
+
private position;
|
|
46
|
+
private startedAt;
|
|
47
|
+
private level;
|
|
48
|
+
private looping;
|
|
49
|
+
private offOwner;
|
|
50
|
+
/** @internal */
|
|
51
|
+
constructor(audio: GameAudio, use: AssetHandle<"audio">, group: AudioGroup, options: AudioPlayOptions);
|
|
52
|
+
get state(): AudioPlaybackState;
|
|
53
|
+
get volume(): number;
|
|
54
|
+
set volume(value: number);
|
|
55
|
+
get loop(): boolean;
|
|
56
|
+
set loop(value: boolean);
|
|
57
|
+
pause(): void;
|
|
58
|
+
resume(): void;
|
|
59
|
+
stop(): void;
|
|
60
|
+
/** @internal */
|
|
61
|
+
replace(): void;
|
|
62
|
+
/** @internal */
|
|
63
|
+
startIfReady(): void;
|
|
64
|
+
private clearSource;
|
|
65
|
+
private fail;
|
|
66
|
+
private finish;
|
|
67
|
+
}
|
|
68
|
+
/** One Web Audio context per Game, created only when audio is requested. */
|
|
69
|
+
export declare class GameAudio {
|
|
70
|
+
private readonly assets;
|
|
71
|
+
private readonly logger;
|
|
72
|
+
private readonly shutdown;
|
|
73
|
+
private readonly groups;
|
|
74
|
+
private readonly voices;
|
|
75
|
+
private context;
|
|
76
|
+
readonly master: AudioGroup;
|
|
77
|
+
/** @internal */
|
|
78
|
+
constructor(host: HTMLElement, assets: AssetStore, logger: Logger);
|
|
79
|
+
get state(): AudioContextState | "idle";
|
|
80
|
+
group(name: string, options?: AudioGroupOptions): AudioGroup;
|
|
81
|
+
play(asset: AssetHandle<"audio">, options?: AudioPlayOptions): AudioPlayback;
|
|
82
|
+
private enforceLimit;
|
|
83
|
+
private assertAlive;
|
|
84
|
+
/** @internal */
|
|
85
|
+
device(): AudioContext;
|
|
86
|
+
/** @internal */
|
|
87
|
+
decode(bytes: ArrayBuffer): Promise<AudioBuffer>;
|
|
88
|
+
/** Call from a trusted user gesture to start pending playback. */
|
|
89
|
+
unlock(): Promise<boolean>;
|
|
90
|
+
private readonly drain;
|
|
91
|
+
/** @internal */
|
|
92
|
+
remove(voice: AudioPlayback): void;
|
|
93
|
+
/** @internal */
|
|
94
|
+
report(cause: unknown, message: string): void;
|
|
95
|
+
/** @internal */
|
|
96
|
+
dispose(): void;
|
|
97
|
+
}
|
package/dist/canvas-visual.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare class CanvasVisual implements CanvasPresentation {
|
|
|
16
16
|
private readonly entries;
|
|
17
17
|
private readonly metrics;
|
|
18
18
|
private dirty;
|
|
19
|
+
private defaultFont;
|
|
19
20
|
private dead;
|
|
20
21
|
private active;
|
|
21
22
|
private cacheResolution;
|
|
@@ -42,6 +43,7 @@ export declare class CanvasVisual implements CanvasPresentation {
|
|
|
42
43
|
private native;
|
|
43
44
|
private button;
|
|
44
45
|
private updateButton;
|
|
46
|
+
private fontFamily;
|
|
45
47
|
update(width: number, height: number): void;
|
|
46
48
|
private releaseEntry;
|
|
47
49
|
dispose(): void;
|
package/dist/game.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { CanvasNode } from "@simpludify/core";
|
|
2
|
-
import { type ActionBindings, ActionController, type ActionSet, type Actor, Aspect, Camera, CanvasUI, type CanvasUIOptions, Engine, type FixedStepOptions, type FrameDriver, type InputCapture, type InputCaptureOptions, type JsonValue, type LogicalResolution, type RendererPort, type ReplayControllers, ReplayPlayer, Scene, ScenePointer, type ScreenPoint, type TweenScheduler, type Viewport, type ViewTransform, VirtualInput, type WorldPoint } from "@simpludify/core";
|
|
2
|
+
import { type ActionBindings, ActionController, type ActionSet, type Actor, Aspect, Camera, CanvasUI, type CanvasUIOptions, Engine, type FixedStepOptions, type FrameDriver, type InputCapture, type InputCaptureOptions, type JsonValue, Logger, type LoggerOptions, type LogicalResolution, type RendererPort, type ReplayControllers, ReplayPlayer, Scene, ScenePointer, type SceneRetention, type ScreenPoint, type TweenScheduler, type Viewport, type ViewTransform, VirtualInput, type WorldPoint } from "@simpludify/core";
|
|
3
|
+
import { type AssetHandle, type AssetOptions, AssetScope } from "./assets.js";
|
|
4
|
+
import { GameAudio } from "./audio.js";
|
|
3
5
|
import { GamepadInput } from "./gamepads.js";
|
|
4
6
|
import { Theme, type ThemeTokens, type UINode } from "./ui.js";
|
|
5
7
|
export interface SceneContext {
|
|
6
8
|
readonly scene: Scene;
|
|
9
|
+
readonly assets: AssetScope;
|
|
7
10
|
readonly signal: AbortSignal;
|
|
8
11
|
readonly tweens: TweenScheduler;
|
|
9
12
|
readonly presentationTweens: TweenScheduler;
|
|
@@ -19,6 +22,13 @@ export interface SceneContext {
|
|
|
19
22
|
onDispose(callback: () => void): () => void;
|
|
20
23
|
}
|
|
21
24
|
export type SceneSetup = (context: SceneContext) => void | Promise<void>;
|
|
25
|
+
export interface SceneOptions {
|
|
26
|
+
readonly retention?: SceneRetention;
|
|
27
|
+
}
|
|
28
|
+
export interface GameLoggingOptions extends Omit<LoggerOptions, "sink"> {
|
|
29
|
+
/** Controls Console output only. Diagnostic subscribers remain active. */
|
|
30
|
+
readonly console?: boolean;
|
|
31
|
+
}
|
|
22
32
|
export interface GameOptions {
|
|
23
33
|
parent?: HTMLElement;
|
|
24
34
|
resolution?: LogicalResolution;
|
|
@@ -33,6 +43,10 @@ export interface GameOptions {
|
|
|
33
43
|
fixedStep?: FixedStepOptions;
|
|
34
44
|
renderer?: (host: HTMLElement) => RendererPort;
|
|
35
45
|
frames?: FrameDriver;
|
|
46
|
+
logging?: GameLoggingOptions;
|
|
47
|
+
assets?: AssetOptions;
|
|
48
|
+
sceneRetention?: SceneRetention;
|
|
49
|
+
/** @deprecated Subscribe to Game.logger for structured diagnostics. */
|
|
36
50
|
onError?: (error: unknown) => void;
|
|
37
51
|
}
|
|
38
52
|
export declare class Game<SceneId extends string = string> {
|
|
@@ -40,6 +54,13 @@ export declare class Game<SceneId extends string = string> {
|
|
|
40
54
|
readonly element: HTMLDivElement;
|
|
41
55
|
readonly camera: Camera;
|
|
42
56
|
readonly gamepads: GamepadInput;
|
|
57
|
+
readonly logger: Logger;
|
|
58
|
+
readonly assets: AssetScope;
|
|
59
|
+
readonly audio: GameAudio;
|
|
60
|
+
private readonly defaultFont;
|
|
61
|
+
private fontUse;
|
|
62
|
+
private readonly imagePool;
|
|
63
|
+
private readonly assetStore;
|
|
43
64
|
private readonly renderer;
|
|
44
65
|
private readonly keyboard;
|
|
45
66
|
private readonly captures;
|
|
@@ -89,6 +110,10 @@ export declare class Game<SceneId extends string = string> {
|
|
|
89
110
|
private height;
|
|
90
111
|
private ratio;
|
|
91
112
|
private readonly scenes;
|
|
113
|
+
private readonly retainedScenes;
|
|
114
|
+
private readonly sceneRetention;
|
|
115
|
+
private activeRetention;
|
|
116
|
+
private detachPresentation;
|
|
92
117
|
private pendingScene;
|
|
93
118
|
private readonly defaultUI;
|
|
94
119
|
private ui;
|
|
@@ -105,6 +130,8 @@ export declare class Game<SceneId extends string = string> {
|
|
|
105
130
|
private readonly shutdown;
|
|
106
131
|
private readonly errorBox;
|
|
107
132
|
constructor(options?: GameOptions);
|
|
133
|
+
/** Choose the Game default font for DOM and Canvas UI. */
|
|
134
|
+
setFont(asset?: AssetHandle<"font">): void;
|
|
108
135
|
private assertAlive;
|
|
109
136
|
get tweens(): TweenScheduler;
|
|
110
137
|
get presentationTweens(): TweenScheduler;
|
|
@@ -124,11 +151,12 @@ export declare class Game<SceneId extends string = string> {
|
|
|
124
151
|
remove(actor: Actor | string): boolean;
|
|
125
152
|
canvasUI(root: CanvasNode, options?: CanvasUIOptions): CanvasUI;
|
|
126
153
|
uiOverlay(...nodes: UINode[]): void;
|
|
127
|
-
scene(id: SceneId, setup: SceneSetup): this;
|
|
154
|
+
scene(id: SceneId, setup: SceneSetup, options?: SceneOptions): this;
|
|
128
155
|
private wait;
|
|
129
156
|
run(initialScene?: SceneId): Promise<void>;
|
|
130
157
|
changeScene(id: SceneId): Promise<void>;
|
|
131
158
|
private navigate;
|
|
159
|
+
private reportPreparation;
|
|
132
160
|
private present;
|
|
133
161
|
get viewport(): Viewport;
|
|
134
162
|
get view(): ViewTransform;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import "./style.css";
|
|
2
2
|
export * from "@simpludify/core";
|
|
3
|
+
export type { AssetData, AssetHandle, AssetKind, AssetLoadOptions, AssetOptions, AssetProgress, AssetRequest, AssetRetry, AssetScope, AssetStatus, ImageAssetSource, } from "./assets.js";
|
|
4
|
+
export type { AudioEndReason, AudioGroup, AudioGroupOptions, AudioPlayback, AudioPlaybackState, AudioPlayOptions, GameAudio, } from "./audio.js";
|
|
3
5
|
export { browserAbortSignal, CanvasButton } from "./canvas-node.js";
|
|
4
6
|
export type { CanvasPresentation } from "./canvas-visual.js";
|
|
5
7
|
export * from "./game.js";
|