@zakkster/lite-camera-pro 1.0.1 → 1.1.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/CHANGELOG.md +47 -0
- package/README.md +7 -0
- package/llms.txt +14 -1
- package/package.json +44 -5
- package/src/BoundsSystem.d.ts +54 -0
- package/src/CameraSequence.d.ts +75 -0
- package/src/FollowMode.d.ts +25 -0
- package/src/MultiTarget.d.ts +49 -0
- package/src/ParallaxManager.d.ts +60 -0
- package/src/Shake.d.ts +82 -0
- package/src/Shake.js +7 -0
- package/src/index.d.ts +37 -130
- package/src/index.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,53 @@ Versioning. Version lives in three places at once -- `package.json`, the
|
|
|
6
6
|
`VERSION` const in `src/index.js`, and the `Version:` header in `llms.txt` --
|
|
7
7
|
bumped together or not at all.
|
|
8
8
|
|
|
9
|
+
## [1.1.0] -- 2026-08-26
|
|
10
|
+
|
|
11
|
+
Subpath exports. A consumer who needs only screen shake now imports
|
|
12
|
+
`@zakkster/lite-camera-pro/shake` and pays for the shake engine plus its
|
|
13
|
+
tree-shaken noise sampler -- nothing else. No runtime behavior changed: the hot
|
|
14
|
+
bodies (`computeShake`, `updateShake`, `apply`, `updateParallax`, `applyBounds`,
|
|
15
|
+
`updateMultiTarget`) are byte-identical, and the camera class imports the same
|
|
16
|
+
module files the subpaths expose (one engine, no fork -- proven by the T8
|
|
17
|
+
Object.is identity check).
|
|
18
|
+
|
|
19
|
+
Measured: the Las Vegas scratch-card consumer (BRIEF.md) reported a 73.5 KB gz
|
|
20
|
+
whole-package pull for a three-tier win-shake ramp that touches only the shake
|
|
21
|
+
API. Through `@zakkster/lite-camera-pro/shake` the same integration measures
|
|
22
|
+
**2.82 KB gz** (2,883 B; 8.79 KB raw, esbuild esm, minify=false, gzip -9) --
|
|
23
|
+
about **26x smaller**. Of that bundle, lite-noise's `Noise.js` contributes
|
|
24
|
+
2,009 B (5.1% of its 39,613 B source), so tree-shaking through the noise
|
|
25
|
+
dependency works as intended.
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **Subpath exports map.** Seven entries beside `.`: `./shake`, `./parallax`,
|
|
30
|
+
`./bounds`, `./multi`, `./follow`, `./sequence`, and `./package.json`. Each
|
|
31
|
+
runtime entry carries a sibling `types` condition (declared first, per the
|
|
32
|
+
TypeScript exports-map requirement). Per-subpath gz weights (esm, unminified,
|
|
33
|
+
gzip -9): `./shake` 2.82 KB, `./parallax` 0.89 KB, `./bounds` 1.13 KB,
|
|
34
|
+
`./multi` 0.89 KB, `./follow` 0.71 KB, `./sequence` 5.94 KB, `.` 21.70 KB.
|
|
35
|
+
`./sequence` drags `@zakkster/lite-timeline` + `@zakkster/lite-ease` by design
|
|
36
|
+
-- it is the only subpath that does.
|
|
37
|
+
- **`src/Shake.js` barrel.** A two-line re-export over `ShakeEngine.js` +
|
|
38
|
+
`ShakePresets.js` (never a copy), so a shake-only consumer gets the engine,
|
|
39
|
+
the presets, and `getPreset`/`registerPreset`/`listPresets` from one import.
|
|
40
|
+
- **Typed functional layer (CP-16a).** `src/index.d.ts` now re-exports six
|
|
41
|
+
per-subsystem sibling declarations (`Shake.d.ts`, `ParallaxManager.d.ts`,
|
|
42
|
+
`BoundsSystem.d.ts`, `MultiTarget.d.ts`, `FollowMode.d.ts`,
|
|
43
|
+
`CameraSequence.d.ts`), each declaring its module's complete runtime surface
|
|
44
|
+
-- state interfaces, enums, defaults, no `any`. The standalone functions are
|
|
45
|
+
now visible and typed at the main entry, not just the class.
|
|
46
|
+
- **Size gate.** `test/size.mjs` bundles every subpath with the esbuild JS API
|
|
47
|
+
and asserts `./shake` gz stays at or under the fixed 16,384 B charter budget.
|
|
48
|
+
Wired into `npm run verify`.
|
|
49
|
+
- **Dependency decision record (CP-17).** `decisions/0001-layout-and-deps.md`
|
|
50
|
+
documents the multi-file layout and the five first-party runtime deps, with
|
|
51
|
+
per-dep floor evidence. Repo-only; not shipped in the tarball.
|
|
52
|
+
- **TypeScript smoke.** `test/types-smoke/smoke.ts` exercises every subpath plus
|
|
53
|
+
the main entry under `strict` + `noImplicitAny` + node16 resolution;
|
|
54
|
+
`npm run typecheck` runs it and joins `prepublishOnly`.
|
|
55
|
+
|
|
9
56
|
## [1.0.1] -- 2026-08-25
|
|
10
57
|
|
|
11
58
|
Foundation release: make the suite run, gate it, and land the fixes that cost
|
package/README.md
CHANGED
|
@@ -20,6 +20,13 @@
|
|
|
20
20
|
npm install @zakkster/lite-camera-pro
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
Need only screen shake? Import the `./shake` subpath and pull just the engine +
|
|
24
|
+
presets (2.82 KB gz -- esm, unminified, gzip -9):
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import { createShakeState, addShake, updateShake, computeShake, getPreset } from '@zakkster/lite-camera-pro/shake';
|
|
28
|
+
```
|
|
29
|
+
|
|
23
30
|
---
|
|
24
31
|
|
|
25
32
|
## Why Pro?
|
package/llms.txt
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
> with presets, fluent timeline sequences, a 16-layer parallax manager, per-edge
|
|
7
7
|
> bounds, a debug HUD, and zero-alloc coordinate conversion.
|
|
8
8
|
|
|
9
|
-
Version: 1.0
|
|
9
|
+
Version: 1.1.0
|
|
10
10
|
|
|
11
11
|
ESM only. `import` from `@zakkster/lite-camera-pro`. Default export is the
|
|
12
12
|
CinematicCameraPro class. All hot-path APIs avoid allocation; setup-time calls
|
|
@@ -109,6 +109,19 @@ Multi: createMultiTargetState, updateMultiTarget
|
|
|
109
109
|
Sequence: createCameraSequence, panTo, dramaticZoom, bossReveal, timedShake
|
|
110
110
|
Enums: FollowMode, FOLLOW_STRATEGIES, BoundsType, WrapMode
|
|
111
111
|
|
|
112
|
+
## Subpath exports (import only what you use; gz, esm, unminified, gzip -9)
|
|
113
|
+
Beside the "." main entry, six subsystem subpaths + "./package.json". Same runtime
|
|
114
|
+
identities as the main entry (one engine, no fork). Per-subpath gz weight:
|
|
115
|
+
./shake 2.82 KB createShakeState, addShake, addTraumaSimple, updateShake, computeShake, clearShakes + presets/getPreset/registerPreset/listPresets
|
|
116
|
+
./parallax 0.89 KB createParallaxState, addParallaxLayer, removeParallaxLayer, updateParallax, getLayerScroll, applyParallaxLayer, WrapMode
|
|
117
|
+
./bounds 1.13 KB createBoundsState, setBoundsAll, setBoundsEdges, setBoundsRect, clearBoundsRect, applyBounds, BoundsType
|
|
118
|
+
./multi 0.89 KB createMultiTargetState, updateMultiTarget
|
|
119
|
+
./follow 0.71 KB FollowMode, FOLLOW_STRATEGIES
|
|
120
|
+
./sequence 5.94 KB createCameraSequence, panTo, dramaticZoom, bossReveal, timedShake (drags lite-timeline + lite-ease by design -- the only subpath that does)
|
|
121
|
+
. 21.70 KB full class + functional layer
|
|
122
|
+
Self-reference example (shake only):
|
|
123
|
+
import { createShakeState, addShake, updateShake, computeShake, getPreset } from '@zakkster/lite-camera-pro/shake';
|
|
124
|
+
|
|
112
125
|
## Dependencies (all @zakkster, first-party)
|
|
113
126
|
@zakkster/lite-camera (base CinematicCamera), lite-ease, lite-lerp, lite-noise, lite-timeline.
|
|
114
127
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zakkster/lite-camera-pro",
|
|
3
3
|
"author": "Zahary Shinikchiev <shinikchiev@yahoo.com>",
|
|
4
|
-
"version": "1.0
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"description": "Cinematic camera system for Canvas2D games. Zero-GC, multi-target framing, noise-based shake, and timeline sequences.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
@@ -13,7 +13,44 @@
|
|
|
13
13
|
"node": "./src/index.js",
|
|
14
14
|
"import": "./src/index.js",
|
|
15
15
|
"default": "./src/index.js"
|
|
16
|
-
}
|
|
16
|
+
},
|
|
17
|
+
"./shake": {
|
|
18
|
+
"types": "./src/Shake.d.ts",
|
|
19
|
+
"node": "./src/Shake.js",
|
|
20
|
+
"import": "./src/Shake.js",
|
|
21
|
+
"default": "./src/Shake.js"
|
|
22
|
+
},
|
|
23
|
+
"./parallax": {
|
|
24
|
+
"types": "./src/ParallaxManager.d.ts",
|
|
25
|
+
"node": "./src/ParallaxManager.js",
|
|
26
|
+
"import": "./src/ParallaxManager.js",
|
|
27
|
+
"default": "./src/ParallaxManager.js"
|
|
28
|
+
},
|
|
29
|
+
"./bounds": {
|
|
30
|
+
"types": "./src/BoundsSystem.d.ts",
|
|
31
|
+
"node": "./src/BoundsSystem.js",
|
|
32
|
+
"import": "./src/BoundsSystem.js",
|
|
33
|
+
"default": "./src/BoundsSystem.js"
|
|
34
|
+
},
|
|
35
|
+
"./multi": {
|
|
36
|
+
"types": "./src/MultiTarget.d.ts",
|
|
37
|
+
"node": "./src/MultiTarget.js",
|
|
38
|
+
"import": "./src/MultiTarget.js",
|
|
39
|
+
"default": "./src/MultiTarget.js"
|
|
40
|
+
},
|
|
41
|
+
"./follow": {
|
|
42
|
+
"types": "./src/FollowMode.d.ts",
|
|
43
|
+
"node": "./src/FollowMode.js",
|
|
44
|
+
"import": "./src/FollowMode.js",
|
|
45
|
+
"default": "./src/FollowMode.js"
|
|
46
|
+
},
|
|
47
|
+
"./sequence": {
|
|
48
|
+
"types": "./src/CameraSequence.d.ts",
|
|
49
|
+
"node": "./src/CameraSequence.js",
|
|
50
|
+
"import": "./src/CameraSequence.js",
|
|
51
|
+
"default": "./src/CameraSequence.js"
|
|
52
|
+
},
|
|
53
|
+
"./package.json": "./package.json"
|
|
17
54
|
},
|
|
18
55
|
"files": [
|
|
19
56
|
"src/",
|
|
@@ -50,15 +87,17 @@
|
|
|
50
87
|
"@zakkster/lite-gc-profiler": "^1.16.0",
|
|
51
88
|
"@zakkster/lite-leak": "^1.10.0",
|
|
52
89
|
"@zakkster/lite-signal": "^1.5.0",
|
|
53
|
-
"esbuild": "^0.25.0"
|
|
90
|
+
"esbuild": "^0.25.0",
|
|
91
|
+
"typescript": "7.0.2"
|
|
54
92
|
},
|
|
55
93
|
"scripts": {
|
|
56
94
|
"test": "node --test test/*.test.js",
|
|
57
95
|
"test:gc": "node --expose-gc --test test/*.test.js",
|
|
58
96
|
"torture": "node --expose-gc test/torture.mjs",
|
|
59
|
-
"verify": "npm run test:gc && npm run torture",
|
|
97
|
+
"verify": "npm run test:gc && npm run torture && node test/size.mjs",
|
|
98
|
+
"typecheck": "tsc -p test/types-smoke/tsconfig.json",
|
|
60
99
|
"bundle-check": "esbuild ./src/index.js --bundle --format=esm --outfile=test-bundle.js",
|
|
61
|
-
"prepublishOnly": "npm run verify && npm run bundle-check"
|
|
100
|
+
"prepublishOnly": "npm run verify && npm run typecheck && npm run bundle-check"
|
|
62
101
|
},
|
|
63
102
|
"keywords": [
|
|
64
103
|
"camera",
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zakkster/lite-camera-pro/bounds -- TypeScript declarations.
|
|
3
|
+
*
|
|
4
|
+
* Configurable per-edge boundary behavior. Pure math, no dependencies.
|
|
5
|
+
* Complete runtime surface, no `any`.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// -- Boundary types --
|
|
9
|
+
export declare const BoundsType: {
|
|
10
|
+
readonly HARD: 0;
|
|
11
|
+
readonly SOFT: 1;
|
|
12
|
+
readonly ELASTIC: 2;
|
|
13
|
+
readonly NONE: 3;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// -- Bounds system state (one per camera) --
|
|
17
|
+
export interface BoundsState {
|
|
18
|
+
left: number;
|
|
19
|
+
right: number;
|
|
20
|
+
top: number;
|
|
21
|
+
bottom: number;
|
|
22
|
+
softZone: number;
|
|
23
|
+
elasticMax: number;
|
|
24
|
+
elasticStrength: number;
|
|
25
|
+
boundsX: number;
|
|
26
|
+
boundsY: number;
|
|
27
|
+
boundsW: number;
|
|
28
|
+
boundsH: number;
|
|
29
|
+
customBounds: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// -- Per-edge config for setBoundsEdges --
|
|
33
|
+
export interface BoundsEdgesConfig {
|
|
34
|
+
left?: number;
|
|
35
|
+
right?: number;
|
|
36
|
+
top?: number;
|
|
37
|
+
bottom?: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export declare function createBoundsState(): BoundsState;
|
|
41
|
+
export declare function setBoundsAll(state: BoundsState, type: number): void;
|
|
42
|
+
export declare function setBoundsEdges(state: BoundsState, config: BoundsEdgesConfig): void;
|
|
43
|
+
export declare function setBoundsRect(state: BoundsState, x: number, y: number, w: number, h: number): void;
|
|
44
|
+
export declare function clearBoundsRect(state: BoundsState): void;
|
|
45
|
+
export declare function applyBounds(
|
|
46
|
+
state: BoundsState,
|
|
47
|
+
target: Float32Array,
|
|
48
|
+
pos: Float32Array,
|
|
49
|
+
maxX: number,
|
|
50
|
+
maxY: number,
|
|
51
|
+
visW: number,
|
|
52
|
+
visH: number,
|
|
53
|
+
dt: number,
|
|
54
|
+
): void;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zakkster/lite-camera-pro/sequence -- TypeScript declarations.
|
|
3
|
+
*
|
|
4
|
+
* Timeline-driven camera choreography. NOTE: this subpath drags
|
|
5
|
+
* @zakkster/lite-timeline and @zakkster/lite-ease by design -- it is the only
|
|
6
|
+
* subpath that does. Complete runtime surface, no `any`.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { CinematicCameraPro } from './index.js';
|
|
10
|
+
import type { ShakeProfile } from './Shake.js';
|
|
11
|
+
|
|
12
|
+
// -- Sequence construction options --
|
|
13
|
+
export interface CameraSequenceOptions {
|
|
14
|
+
loop?: boolean;
|
|
15
|
+
onComplete?: () => void;
|
|
16
|
+
blendOutTime?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// -- Per-step options --
|
|
20
|
+
export interface StepOptions {
|
|
21
|
+
ease?: (t: number) => number;
|
|
22
|
+
at?: string | number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// -- A fluent camera sequence handle --
|
|
26
|
+
export interface CameraSequence {
|
|
27
|
+
moveTo(x: number, y: number, duration: number, opts?: StepOptions): CameraSequence;
|
|
28
|
+
zoomTo(level: number, duration: number, opts?: StepOptions): CameraSequence;
|
|
29
|
+
moveAndZoom(x: number, y: number, level: number, duration: number, opts?: StepOptions): CameraSequence;
|
|
30
|
+
shake(profileOrName: string | ShakeProfile, intensity?: number, opts?: StepOptions): CameraSequence;
|
|
31
|
+
wait(duration: number, opts?: StepOptions): CameraSequence;
|
|
32
|
+
call(fn: () => void, opts?: StepOptions): CameraSequence;
|
|
33
|
+
play(): CameraSequence;
|
|
34
|
+
pause(): CameraSequence;
|
|
35
|
+
resume(): CameraSequence;
|
|
36
|
+
stop(): CameraSequence;
|
|
37
|
+
seek(timeMs: number): CameraSequence;
|
|
38
|
+
destroy(): void;
|
|
39
|
+
readonly duration: number;
|
|
40
|
+
readonly progress: number;
|
|
41
|
+
readonly playing: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export declare function createCameraSequence(cam: CinematicCameraPro, options?: CameraSequenceOptions): CameraSequence;
|
|
45
|
+
export declare function panTo(
|
|
46
|
+
cam: CinematicCameraPro,
|
|
47
|
+
x: number,
|
|
48
|
+
y: number,
|
|
49
|
+
duration: number,
|
|
50
|
+
opts?: CameraSequenceOptions & StepOptions,
|
|
51
|
+
): CameraSequence;
|
|
52
|
+
export declare function dramaticZoom(
|
|
53
|
+
cam: CinematicCameraPro,
|
|
54
|
+
x: number,
|
|
55
|
+
y: number,
|
|
56
|
+
zoom: number,
|
|
57
|
+
duration: number,
|
|
58
|
+
opts?: CameraSequenceOptions & StepOptions,
|
|
59
|
+
): CameraSequence;
|
|
60
|
+
export declare function bossReveal(
|
|
61
|
+
cam: CinematicCameraPro,
|
|
62
|
+
x: number,
|
|
63
|
+
y: number,
|
|
64
|
+
totalMs?: number,
|
|
65
|
+
opts?: CameraSequenceOptions,
|
|
66
|
+
): CameraSequence;
|
|
67
|
+
export declare function timedShake(
|
|
68
|
+
cam: CinematicCameraPro,
|
|
69
|
+
presetOrProfile: string | ShakeProfile,
|
|
70
|
+
holdMs?: number,
|
|
71
|
+
opts?: CameraSequenceOptions,
|
|
72
|
+
): CameraSequence;
|
|
73
|
+
|
|
74
|
+
declare const _default: typeof createCameraSequence;
|
|
75
|
+
export default _default;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zakkster/lite-camera-pro/follow -- TypeScript declarations.
|
|
3
|
+
*
|
|
4
|
+
* Follow-mode enum and the strategy dispatch table. Complete runtime surface,
|
|
5
|
+
* no `any`.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { CinematicCameraPro } from './index.js';
|
|
9
|
+
|
|
10
|
+
// -- Follow modes --
|
|
11
|
+
export declare const FollowMode: {
|
|
12
|
+
readonly SMOOTH: 0;
|
|
13
|
+
readonly LOCK: 1;
|
|
14
|
+
readonly PREDICTIVE: 2;
|
|
15
|
+
readonly CUT: 3;
|
|
16
|
+
readonly HYBRID: 4;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// -- Strategy dispatch table, indexed by FollowMode value --
|
|
20
|
+
export declare const FOLLOW_STRATEGIES: ReadonlyArray<
|
|
21
|
+
(cam: CinematicCameraPro, dt: number, px: number, py: number, pvx: number, pvy: number) => void
|
|
22
|
+
>;
|
|
23
|
+
|
|
24
|
+
declare const _default: typeof FollowMode;
|
|
25
|
+
export default _default;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zakkster/lite-camera-pro/multi -- TypeScript declarations.
|
|
3
|
+
*
|
|
4
|
+
* Multi-target framing: fit several targets in view. Pure math, no
|
|
5
|
+
* dependencies. Complete runtime surface, no `any`.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { CinematicCameraPro } from './index.js';
|
|
9
|
+
|
|
10
|
+
// -- A 2D point (target position) --
|
|
11
|
+
export interface Vec2 {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// -- Multi-target config/state (one per camera) --
|
|
17
|
+
export interface MultiTargetState {
|
|
18
|
+
active: boolean;
|
|
19
|
+
targets: Vec2[] | null;
|
|
20
|
+
count: number;
|
|
21
|
+
paddingX: number;
|
|
22
|
+
paddingY: number;
|
|
23
|
+
minZoom: number;
|
|
24
|
+
maxZoom: number;
|
|
25
|
+
zoomSpeed: number;
|
|
26
|
+
followSpeed: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// -- Options accepted by CinematicCameraPro.trackMultiple --
|
|
30
|
+
export interface MultiTargetOptions {
|
|
31
|
+
paddingX?: number;
|
|
32
|
+
paddingY?: number;
|
|
33
|
+
padding?: number;
|
|
34
|
+
minZoom?: number;
|
|
35
|
+
maxZoom?: number;
|
|
36
|
+
zoomSpeed?: number;
|
|
37
|
+
followSpeed?: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export declare function updateMultiTarget(
|
|
41
|
+
cam: CinematicCameraPro,
|
|
42
|
+
dt: number,
|
|
43
|
+
targets: Vec2[],
|
|
44
|
+
count: number,
|
|
45
|
+
): void;
|
|
46
|
+
export declare function createMultiTargetState(): MultiTargetState;
|
|
47
|
+
|
|
48
|
+
declare const _default: typeof updateMultiTarget;
|
|
49
|
+
export default _default;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zakkster/lite-camera-pro/parallax -- TypeScript declarations.
|
|
3
|
+
*
|
|
4
|
+
* Multi-layer scroll manager. Pure math, no dependencies. Complete runtime
|
|
5
|
+
* surface, no `any`.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// -- Wrap modes for layer tiling --
|
|
9
|
+
export declare const WrapMode: {
|
|
10
|
+
readonly NONE: 0;
|
|
11
|
+
readonly REPEAT_X: 1;
|
|
12
|
+
readonly REPEAT_Y: 2;
|
|
13
|
+
readonly REPEAT_BOTH: 3;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// -- A single pre-allocated parallax layer --
|
|
17
|
+
export interface ParallaxLayer {
|
|
18
|
+
active: boolean;
|
|
19
|
+
id: string;
|
|
20
|
+
speedX: number;
|
|
21
|
+
speedY: number;
|
|
22
|
+
offsetX: number;
|
|
23
|
+
offsetY: number;
|
|
24
|
+
wrap: number;
|
|
25
|
+
scrollX: number;
|
|
26
|
+
scrollY: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// -- Parallax manager state (one per camera) --
|
|
30
|
+
export interface ParallaxState {
|
|
31
|
+
layers: ParallaxLayer[];
|
|
32
|
+
layerCount: number;
|
|
33
|
+
activeCount: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// -- Options accepted by addParallaxLayer --
|
|
37
|
+
export interface ParallaxLayerOptions {
|
|
38
|
+
offsetX?: number;
|
|
39
|
+
offsetY?: number;
|
|
40
|
+
wrap?: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// -- Output shape for getLayerScroll --
|
|
44
|
+
export interface ScrollOut {
|
|
45
|
+
x: number;
|
|
46
|
+
y: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export declare function createParallaxState(): ParallaxState;
|
|
50
|
+
export declare function addParallaxLayer(
|
|
51
|
+
state: ParallaxState,
|
|
52
|
+
id: string,
|
|
53
|
+
speedX: number,
|
|
54
|
+
speedY?: number,
|
|
55
|
+
opts?: ParallaxLayerOptions,
|
|
56
|
+
): ParallaxLayer | null;
|
|
57
|
+
export declare function removeParallaxLayer(state: ParallaxState, id: string): void;
|
|
58
|
+
export declare function updateParallax(state: ParallaxState, camX: number, camY: number, zoom: number): void;
|
|
59
|
+
export declare function getLayerScroll(state: ParallaxState, id: string, out: ScrollOut): ScrollOut | null;
|
|
60
|
+
export declare function applyParallaxLayer(state: ParallaxState, id: string, ctx: CanvasRenderingContext2D): boolean;
|
package/src/Shake.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zakkster/lite-camera-pro/shake -- TypeScript declarations.
|
|
3
|
+
*
|
|
4
|
+
* The ./shake subpath barrel: the noise-based shake engine (ShakeEngine.js)
|
|
5
|
+
* plus the built-in presets and registry (ShakePresets.js). Complete runtime
|
|
6
|
+
* surface, no `any`.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// -- Shake profile (input) --
|
|
10
|
+
export interface ShakeProfile {
|
|
11
|
+
/** Initial trauma [0, 1]. Undefined defaults to 0.5 in addShake. */
|
|
12
|
+
trauma?: number;
|
|
13
|
+
/** Noise sample frequency (higher = more jittery). Default 15. */
|
|
14
|
+
freq?: number;
|
|
15
|
+
/** Trauma units lost per second. Default 1. */
|
|
16
|
+
decay?: number;
|
|
17
|
+
/** Maximum pixel offset at trauma=1. Default 15. */
|
|
18
|
+
maxOffset?: number;
|
|
19
|
+
/** Maximum rotation (radians) at trauma=1. Default 0.05. */
|
|
20
|
+
maxAngle?: number;
|
|
21
|
+
/** Directional X component; (0,0) = omnidirectional. Default 0. */
|
|
22
|
+
dirX?: number;
|
|
23
|
+
/** Directional Y component. Default 0. */
|
|
24
|
+
dirY?: number;
|
|
25
|
+
/** Per-profile intensity multiplier used by addShake. Default 1. */
|
|
26
|
+
intensity?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// -- A single pre-allocated shake slot --
|
|
30
|
+
export interface ShakeSlot {
|
|
31
|
+
active: boolean;
|
|
32
|
+
isDefault: boolean;
|
|
33
|
+
trauma: number;
|
|
34
|
+
decay: number;
|
|
35
|
+
freq: number;
|
|
36
|
+
time: number;
|
|
37
|
+
maxOffset: number;
|
|
38
|
+
maxAngle: number;
|
|
39
|
+
dirX: number;
|
|
40
|
+
dirY: number;
|
|
41
|
+
isDirectional: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// -- Shake engine state (one per camera) --
|
|
45
|
+
export interface ShakeState {
|
|
46
|
+
slots: ShakeSlot[];
|
|
47
|
+
slotCount: number;
|
|
48
|
+
seedOffset: number;
|
|
49
|
+
/** Computed X offset in pixels (read by apply()). */
|
|
50
|
+
offsetX: number;
|
|
51
|
+
/** Computed Y offset in pixels. */
|
|
52
|
+
offsetY: number;
|
|
53
|
+
/** Computed rotation in radians. */
|
|
54
|
+
angle: number;
|
|
55
|
+
/** Global shake scale (0 = no shake, 1 = normal). */
|
|
56
|
+
globalScale: number;
|
|
57
|
+
/** True when any slot is active. */
|
|
58
|
+
active: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// -- Shake engine functions (ShakeEngine.js) --
|
|
62
|
+
export declare function createShakeState(seedOffset?: number): ShakeState;
|
|
63
|
+
export declare function addShake(state: ShakeState, profile: ShakeProfile, intensity?: number): void;
|
|
64
|
+
export declare function addTraumaSimple(state: ShakeState, amount: number): void;
|
|
65
|
+
export declare function updateShake(state: ShakeState, dt: number): void;
|
|
66
|
+
export declare function computeShake(state: ShakeState): void;
|
|
67
|
+
export declare function clearShakes(state: ShakeState): void;
|
|
68
|
+
|
|
69
|
+
// -- Built-in presets (ShakePresets.js) --
|
|
70
|
+
export declare const EXPLOSION: Readonly<ShakeProfile>;
|
|
71
|
+
export declare const EARTHQUAKE: Readonly<ShakeProfile>;
|
|
72
|
+
export declare const RECOIL: Readonly<ShakeProfile>;
|
|
73
|
+
export declare const IMPACT: Readonly<ShakeProfile>;
|
|
74
|
+
export declare const LANDING: Readonly<ShakeProfile>;
|
|
75
|
+
export declare const DAMAGE: Readonly<ShakeProfile>;
|
|
76
|
+
export declare const RUMBLE: Readonly<ShakeProfile>;
|
|
77
|
+
export declare const HEAVY_IMPACT: Readonly<ShakeProfile>;
|
|
78
|
+
|
|
79
|
+
// -- Preset registry (ShakePresets.js) --
|
|
80
|
+
export declare function getPreset(name: string): Readonly<ShakeProfile> | null;
|
|
81
|
+
export declare function registerPreset(name: string, profile: ShakeProfile): void;
|
|
82
|
+
export declare function listPresets(): string[];
|
package/src/Shake.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// @zakkster/lite-camera-pro -- the ./shake subpath barrel.
|
|
2
|
+
// Re-export only; never a copy. The camera class and this subpath import the
|
|
3
|
+
// SAME module files, so createShakeState et al. have one runtime identity.
|
|
4
|
+
// ShakePresets is folded in so a shake-only consumer gets presets + getPreset
|
|
5
|
+
// from a single import.
|
|
6
|
+
export * from './ShakeEngine.js';
|
|
7
|
+
export * from './ShakePresets.js';
|
package/src/index.d.ts
CHANGED
|
@@ -1,68 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @zakkster/lite-camera-pro
|
|
2
|
+
* @zakkster/lite-camera-pro -- TypeScript declarations (main entry).
|
|
3
|
+
*
|
|
4
|
+
* The full functional layer is re-exported from the per-subsystem sibling
|
|
5
|
+
* declarations (one declaration per type -- no duplicates). This file adds the
|
|
6
|
+
* CinematicCameraPro class, the debug-HUD facade, and the VERSION const.
|
|
3
7
|
*/
|
|
4
8
|
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
readonly REPEAT_X: 1;
|
|
22
|
-
readonly REPEAT_Y: 2;
|
|
23
|
-
readonly REPEAT_BOTH: 3;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
// ── Bounds Types ──
|
|
27
|
-
export declare const BoundsType: {
|
|
28
|
-
readonly HARD: 0;
|
|
29
|
-
readonly SOFT: 1;
|
|
30
|
-
readonly ELASTIC: 2;
|
|
31
|
-
readonly NONE: 3;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// ── Shake Profile ──
|
|
35
|
-
export interface ShakeProfile {
|
|
36
|
-
trauma?: number;
|
|
37
|
-
freq?: number;
|
|
38
|
-
decay?: number;
|
|
39
|
-
maxOffset?: number;
|
|
40
|
-
maxAngle?: number;
|
|
41
|
-
dirX?: number;
|
|
42
|
-
dirY?: number;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// ── Shake Presets ──
|
|
46
|
-
export declare const EXPLOSION: Readonly<ShakeProfile>;
|
|
47
|
-
export declare const EARTHQUAKE: Readonly<ShakeProfile>;
|
|
48
|
-
export declare const RECOIL: Readonly<ShakeProfile>;
|
|
49
|
-
export declare const IMPACT: Readonly<ShakeProfile>;
|
|
50
|
-
export declare const LANDING: Readonly<ShakeProfile>;
|
|
51
|
-
export declare const DAMAGE: Readonly<ShakeProfile>;
|
|
52
|
-
export declare const RUMBLE: Readonly<ShakeProfile>;
|
|
53
|
-
export declare const HEAVY_IMPACT: Readonly<ShakeProfile>;
|
|
54
|
-
|
|
55
|
-
export declare function getPreset(name: string): ShakeProfile | null;
|
|
56
|
-
export declare function registerPreset(name: string, profile: ShakeProfile): void;
|
|
57
|
-
export declare function listPresets(): string[];
|
|
58
|
-
|
|
59
|
-
// ── Vec2 ──
|
|
60
|
-
export interface Vec2 {
|
|
61
|
-
x: number;
|
|
62
|
-
y: number;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// ── Debug HUD Config ──
|
|
9
|
+
// -- Functional layer (mirrors the ./shake, ./parallax, ./bounds, ./multi,
|
|
10
|
+
// ./follow, ./sequence subpaths; same runtime identities) --
|
|
11
|
+
export * from './Shake.js';
|
|
12
|
+
export * from './ParallaxManager.js';
|
|
13
|
+
export * from './BoundsSystem.js';
|
|
14
|
+
export * from './MultiTarget.js';
|
|
15
|
+
export * from './FollowMode.js';
|
|
16
|
+
export * from './CameraSequence.js';
|
|
17
|
+
|
|
18
|
+
// -- Types needed locally by the class declaration --
|
|
19
|
+
import type { ShakeProfile } from './Shake.js';
|
|
20
|
+
import type { Vec2, MultiTargetOptions } from './MultiTarget.js';
|
|
21
|
+
import type { BoundsEdgesConfig } from './BoundsSystem.js';
|
|
22
|
+
import type { CameraSequence, CameraSequenceOptions } from './CameraSequence.js';
|
|
23
|
+
|
|
24
|
+
// -- Debug HUD (DebugHUD.js) -- facade only, no dedicated subpath --
|
|
66
25
|
export interface DebugHUDConfig {
|
|
67
26
|
show: {
|
|
68
27
|
position: boolean;
|
|
@@ -83,66 +42,14 @@ export declare function createDebugHUDConfig(): DebugHUDConfig;
|
|
|
83
42
|
export declare function drawDebugHUD(cam: CinematicCameraPro, ctx: CanvasRenderingContext2D, config?: DebugHUDConfig): void;
|
|
84
43
|
export declare function drawDebugWorld(cam: CinematicCameraPro, ctx: CanvasRenderingContext2D, config?: DebugHUDConfig): void;
|
|
85
44
|
|
|
86
|
-
//
|
|
87
|
-
export
|
|
88
|
-
loop?: boolean;
|
|
89
|
-
onComplete?: () => void;
|
|
90
|
-
blendOutTime?: number;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export interface StepOptions {
|
|
94
|
-
ease?: (t: number) => number;
|
|
95
|
-
at?: string | number;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export interface CameraSequence {
|
|
99
|
-
moveTo(x: number, y: number, duration: number, opts?: StepOptions): CameraSequence;
|
|
100
|
-
zoomTo(level: number, duration: number, opts?: StepOptions): CameraSequence;
|
|
101
|
-
moveAndZoom(x: number, y: number, level: number, duration: number, opts?: StepOptions): CameraSequence;
|
|
102
|
-
shake(profileOrName: string | ShakeProfile, intensity?: number, opts?: StepOptions): CameraSequence;
|
|
103
|
-
wait(duration: number, opts?: StepOptions): CameraSequence;
|
|
104
|
-
call(fn: () => void, opts?: StepOptions): CameraSequence;
|
|
105
|
-
play(): CameraSequence;
|
|
106
|
-
pause(): CameraSequence;
|
|
107
|
-
resume(): CameraSequence;
|
|
108
|
-
stop(): CameraSequence;
|
|
109
|
-
seek(timeMs: number): CameraSequence;
|
|
110
|
-
destroy(): void;
|
|
111
|
-
readonly duration: number;
|
|
112
|
-
readonly progress: number;
|
|
113
|
-
readonly playing: boolean;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export declare function createCameraSequence(cam: CinematicCameraPro, options?: CameraSequenceOptions): CameraSequence;
|
|
117
|
-
export declare function panTo(cam: CinematicCameraPro, x: number, y: number, duration: number, opts?: CameraSequenceOptions & StepOptions): CameraSequence;
|
|
118
|
-
export declare function dramaticZoom(cam: CinematicCameraPro, x: number, y: number, zoom: number, duration: number, opts?: CameraSequenceOptions & StepOptions): CameraSequence;
|
|
119
|
-
export declare function bossReveal(cam: CinematicCameraPro, x: number, y: number, totalMs?: number, opts?: CameraSequenceOptions): CameraSequence;
|
|
120
|
-
export declare function timedShake(cam: CinematicCameraPro, presetOrProfile: string | ShakeProfile, holdMs?: number, opts?: CameraSequenceOptions): CameraSequence;
|
|
121
|
-
|
|
122
|
-
// ── Multi-Target Options ──
|
|
123
|
-
export interface MultiTargetOptions {
|
|
124
|
-
paddingX?: number;
|
|
125
|
-
paddingY?: number;
|
|
126
|
-
padding?: number;
|
|
127
|
-
minZoom?: number;
|
|
128
|
-
maxZoom?: number;
|
|
129
|
-
zoomSpeed?: number;
|
|
130
|
-
followSpeed?: number;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// ── Bounds Config ──
|
|
134
|
-
export interface BoundsEdgesConfig {
|
|
135
|
-
left?: number;
|
|
136
|
-
right?: number;
|
|
137
|
-
top?: number;
|
|
138
|
-
bottom?: number;
|
|
139
|
-
}
|
|
45
|
+
// -- Package version (bumped in lockstep with package.json + llms.txt) --
|
|
46
|
+
export declare const VERSION: string;
|
|
140
47
|
|
|
141
|
-
//
|
|
48
|
+
// -- Main camera class --
|
|
142
49
|
export declare class CinematicCameraPro {
|
|
143
50
|
constructor(viewW: number, viewH: number, worldW: number, worldH: number, seed?: number);
|
|
144
51
|
|
|
145
|
-
//
|
|
52
|
+
// Public state
|
|
146
53
|
readonly pos: Float32Array;
|
|
147
54
|
readonly target: Float32Array;
|
|
148
55
|
readonly look: Float32Array;
|
|
@@ -170,58 +77,58 @@ export declare class CinematicCameraPro {
|
|
|
170
77
|
|
|
171
78
|
debugConfig: DebugHUDConfig;
|
|
172
79
|
|
|
173
|
-
//
|
|
80
|
+
// Follow mode
|
|
174
81
|
setMode(mode: number): this;
|
|
175
82
|
|
|
176
|
-
//
|
|
83
|
+
// Multi-target
|
|
177
84
|
trackMultiple(targets: Vec2[], options?: MultiTargetOptions): this;
|
|
178
85
|
trackSingle(): this;
|
|
179
86
|
setTargetCount(count: number): this;
|
|
180
87
|
|
|
181
|
-
//
|
|
88
|
+
// Shake
|
|
182
89
|
addTrauma(amount: number): this;
|
|
183
90
|
shake(profile: ShakeProfile, intensity?: number): this;
|
|
184
91
|
shakePreset(name: string, intensity?: number): this;
|
|
185
92
|
clearShakes(): this;
|
|
186
93
|
|
|
187
|
-
//
|
|
94
|
+
// Sequences
|
|
188
95
|
createSequence(options?: CameraSequenceOptions): CameraSequence;
|
|
189
96
|
playSequence(seq: CameraSequence): this;
|
|
190
97
|
stopSequence(): this;
|
|
191
98
|
readonly sequencePlaying: boolean;
|
|
192
99
|
|
|
193
|
-
//
|
|
100
|
+
// Zoom
|
|
194
101
|
setZoom(level: number, duration?: number, ease?: (t: number) => number): this;
|
|
195
102
|
zoomAt(targetOrX: number | Vec2, yOrLevel: number, levelOrDur?: number, duration?: number, ease?: (t: number) => number): this;
|
|
196
103
|
|
|
197
|
-
//
|
|
104
|
+
// Coordinate conversion
|
|
198
105
|
screenToWorld(sx: number, sy: number, out: Vec2): Vec2;
|
|
199
106
|
worldToScreen(wx: number, wy: number, out: Vec2): Vec2;
|
|
200
107
|
|
|
201
|
-
//
|
|
108
|
+
// Parallax
|
|
202
109
|
addParallaxLayer(id: string, speedX: number, speedY?: number, opts?: { offsetX?: number; offsetY?: number; wrap?: number }): this;
|
|
203
110
|
removeParallaxLayer(id: string): this;
|
|
204
111
|
applyParallax(id: string, ctx: CanvasRenderingContext2D): boolean;
|
|
205
112
|
|
|
206
|
-
//
|
|
113
|
+
// Bounds
|
|
207
114
|
setBoundsType(type: number): this;
|
|
208
115
|
setBoundsEdges(config: BoundsEdgesConfig): this;
|
|
209
116
|
setBoundsRect(x: number, y: number, w: number, h: number): this;
|
|
210
117
|
clearBoundsRect(): this;
|
|
211
118
|
|
|
212
|
-
//
|
|
119
|
+
// Core
|
|
213
120
|
update(dt: number, px: number, py: number, pvx?: number, pvy?: number): void;
|
|
214
121
|
apply(ctx: CanvasRenderingContext2D): void;
|
|
215
122
|
|
|
216
|
-
//
|
|
123
|
+
// Debug
|
|
217
124
|
debug(ctx: CanvasRenderingContext2D): void;
|
|
218
125
|
debugHUD(ctx: CanvasRenderingContext2D): void;
|
|
219
126
|
|
|
220
|
-
//
|
|
127
|
+
// Save / load
|
|
221
128
|
getState(): { posX: number; posY: number; targetX: number; targetY: number; zoom: number; mode: number };
|
|
222
129
|
setState(snapshot: { posX?: number; posY?: number; targetX?: number; targetY?: number; zoom?: number; mode?: number }): this;
|
|
223
130
|
|
|
224
|
-
//
|
|
131
|
+
// Lifecycle
|
|
225
132
|
destroy(): void;
|
|
226
133
|
}
|
|
227
134
|
|