@zylem/behaviors 0.3.1 → 0.4.1
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/dist/behavior-system-y8SGrGWy.d.ts +580 -0
- package/dist/{chunk-ARJWUNRE.js → chunk-27UPCP5B.js} +10 -10
- package/dist/{chunk-ARJWUNRE.js.map → chunk-27UPCP5B.js.map} +1 -1
- package/dist/{chunk-YUO6SKJD.js → chunk-4L36OPY2.js} +33 -23
- package/dist/chunk-4L36OPY2.js.map +1 -0
- package/dist/{chunk-DYLH6K7B.js → chunk-4WH2ZN7P.js} +1 -1
- package/dist/{chunk-DYLH6K7B.js.map → chunk-4WH2ZN7P.js.map} +1 -1
- package/dist/{chunk-ZPSAXX73.js → chunk-5SM5SH5O.js} +26 -26
- package/dist/chunk-5SM5SH5O.js.map +1 -0
- package/dist/{chunk-STCCNLPC.js → chunk-5XZWTFGF.js} +5 -3
- package/dist/chunk-5XZWTFGF.js.map +1 -0
- package/dist/{chunk-JAN34G6S.js → chunk-67XLJ26X.js} +152 -168
- package/dist/chunk-67XLJ26X.js.map +1 -0
- package/dist/{chunk-2CLT36VB.js → chunk-75FJIUIG.js} +22 -23
- package/dist/chunk-75FJIUIG.js.map +1 -0
- package/dist/{chunk-OYWFPIHF.js → chunk-A4CA35DQ.js} +20 -17
- package/dist/chunk-A4CA35DQ.js.map +1 -0
- package/dist/{chunk-SS7ELMJ7.js → chunk-F72WX4MH.js} +49 -33
- package/dist/chunk-F72WX4MH.js.map +1 -0
- package/dist/{chunk-RTRVBEIB.js → chunk-FTDZAKZW.js} +5 -18
- package/dist/chunk-FTDZAKZW.js.map +1 -0
- package/dist/{chunk-XIJNE67Y.js → chunk-GFARAJV2.js} +3 -5
- package/dist/{chunk-XIJNE67Y.js.map → chunk-GFARAJV2.js.map} +1 -1
- package/dist/{chunk-VAN4WW3F.js → chunk-H4TJ7X4O.js} +4 -7
- package/dist/chunk-H4TJ7X4O.js.map +1 -0
- package/dist/{chunk-KS72RZHX.js → chunk-IZJFUAXB.js} +1 -1
- package/dist/{chunk-KS72RZHX.js.map → chunk-IZJFUAXB.js.map} +1 -1
- package/dist/{chunk-SVLNF434.js → chunk-JXMF4NUI.js} +51 -3
- package/dist/chunk-JXMF4NUI.js.map +1 -0
- package/dist/chunk-KFFETUAL.js +40 -0
- package/dist/chunk-KFFETUAL.js.map +1 -0
- package/dist/chunk-LL4FLHIY.js +12 -0
- package/dist/chunk-LL4FLHIY.js.map +1 -0
- package/dist/{chunk-RTVRUNYR.js → chunk-OTLSUYQQ.js} +2 -2
- package/dist/chunk-OTLSUYQQ.js.map +1 -0
- package/dist/{chunk-Y6UJOUE5.js → chunk-Q75LKHDF.js} +14 -2
- package/dist/chunk-Q75LKHDF.js.map +1 -0
- package/dist/{chunk-KOZUNIIE.js → chunk-QDCJLJUV.js} +10 -10
- package/dist/{chunk-KOZUNIIE.js.map → chunk-QDCJLJUV.js.map} +1 -1
- package/dist/{chunk-LD5SMIB3.js → chunk-QVCMJ4Q2.js} +1 -1
- package/dist/{chunk-LD5SMIB3.js.map → chunk-QVCMJ4Q2.js.map} +1 -1
- package/dist/{chunk-F3KRX2V4.js → chunk-RDHSHEZM.js} +46 -24
- package/dist/chunk-RDHSHEZM.js.map +1 -0
- package/dist/chunk-UIG7MWS2.js +518 -0
- package/dist/chunk-UIG7MWS2.js.map +1 -0
- package/dist/{chunk-6C6NXNEW.js → chunk-UL6Q5HDP.js} +25 -3
- package/dist/chunk-UL6Q5HDP.js.map +1 -0
- package/dist/{chunk-XG2YMCJW.js → chunk-VMQHNJJI.js} +6 -8
- package/dist/{chunk-XG2YMCJW.js.map → chunk-VMQHNJJI.js.map} +1 -1
- package/dist/{chunk-GCNRXAKH.js → chunk-XP3ASVGJ.js} +13 -10
- package/dist/chunk-XP3ASVGJ.js.map +1 -0
- package/dist/{chunk-ID5QJYF5.js → chunk-Y7YIAWPW.js} +11 -1
- package/dist/chunk-Y7YIAWPW.js.map +1 -0
- package/dist/{chunk-4I6E6DGV.js → chunk-Z72F2ENM.js} +6 -8
- package/dist/{chunk-4I6E6DGV.js.map → chunk-Z72F2ENM.js.map} +1 -1
- package/dist/{chunk-FPTWVCPN.js → chunk-ZA43LPRM.js} +4 -24
- package/dist/chunk-ZA43LPRM.js.map +1 -0
- package/dist/{chunk-K3UNLQ7W.js → chunk-ZRQWSURL.js} +2 -2
- package/dist/chunk-ZRQWSURL.js.map +1 -0
- package/dist/cooldown.d.ts +2 -1
- package/dist/cooldown.js +1 -1
- package/dist/coordinators/boundary-ricochet-3d.d.ts +12 -5
- package/dist/coordinators/boundary-ricochet-3d.js +2 -1
- package/dist/coordinators/boundary-ricochet.d.ts +9 -7
- package/dist/coordinators/boundary-ricochet.js +2 -1
- package/dist/coordinators/first-person-shooter.d.ts +9 -8
- package/dist/coordinators/first-person-shooter.js +3 -3
- package/dist/coordinators/multidirectional-space-shooter.d.ts +12 -9
- package/dist/coordinators/multidirectional-space-shooter.js +4 -4
- package/dist/coordinators/top-down-shooter.d.ts +9 -8
- package/dist/coordinators/top-down-shooter.js +3 -3
- package/dist/core.d.ts +4 -4
- package/dist/core.js +17 -39
- package/dist/core.js.map +1 -1
- package/dist/destructible-3d.d.ts +2 -1
- package/dist/first-person.d.ts +12 -12
- package/dist/first-person.js +9 -8
- package/dist/index.d.ts +37 -14
- package/dist/index.js +73 -44
- package/dist/jumper-2d.d.ts +7 -6
- package/dist/jumper-2d.js +6 -5
- package/dist/jumper-3d.d.ts +12 -11
- package/dist/jumper-3d.js +7 -6
- package/dist/{moveable-BCRpjAQb.d.ts → moveable-Cl9h-_w7.d.ts} +2 -78
- package/dist/particle-emitter.d.ts +1 -1
- package/dist/particle-emitter.js +1 -1
- package/dist/platformer-2d.d.ts +306 -0
- package/dist/platformer-2d.js +24 -0
- package/dist/platformer-3d.d.ts +74 -87
- package/dist/platformer-3d.js +5 -4
- package/dist/ricochet-2d.d.ts +1 -1
- package/dist/ricochet-2d.js +2 -2
- package/dist/ricochet-3d.d.ts +1 -1
- package/dist/ricochet-3d.js +2 -2
- package/dist/runtime-2d.d.ts +93 -2
- package/dist/runtime-2d.js +145 -22
- package/dist/runtime-2d.js.map +1 -1
- package/dist/screen-visibility.d.ts +2 -1
- package/dist/screen-wrap.d.ts +2 -1
- package/dist/screen-wrap.js +1 -1
- package/dist/shooter-2d.d.ts +5 -3
- package/dist/shooter-2d.js +2 -2
- package/dist/shooter-fire-DGripl0z.d.ts +55 -0
- package/dist/thruster.d.ts +8 -18
- package/dist/thruster.js +6 -6
- package/dist/top-down-movement.d.ts +7 -4
- package/dist/top-down-movement.js +5 -5
- package/dist/{use-behavior-D_82jAL3.d.ts → use-behavior-B85d5u7-.d.ts} +1 -1
- package/dist/world-boundary-2d.d.ts +2 -1
- package/dist/world-boundary-2d.js +2 -2
- package/dist/world-boundary-3d.d.ts +2 -1
- package/dist/world-boundary-3d.js +2 -2
- package/package.json +7 -5
- package/dist/behavior-system-DYbx-x_-.d.ts +0 -307
- package/dist/chunk-2C3Z5GE7.js +0 -176
- package/dist/chunk-2C3Z5GE7.js.map +0 -1
- package/dist/chunk-2CLT36VB.js.map +0 -1
- package/dist/chunk-3PYGRHAL.js +0 -35
- package/dist/chunk-3PYGRHAL.js.map +0 -1
- package/dist/chunk-6C6NXNEW.js.map +0 -1
- package/dist/chunk-F3KRX2V4.js.map +0 -1
- package/dist/chunk-FPTWVCPN.js.map +0 -1
- package/dist/chunk-GCNRXAKH.js.map +0 -1
- package/dist/chunk-ID5QJYF5.js.map +0 -1
- package/dist/chunk-JAN34G6S.js.map +0 -1
- package/dist/chunk-K3UNLQ7W.js.map +0 -1
- package/dist/chunk-OYWFPIHF.js.map +0 -1
- package/dist/chunk-RTRVBEIB.js.map +0 -1
- package/dist/chunk-RTVRUNYR.js.map +0 -1
- package/dist/chunk-SS7ELMJ7.js.map +0 -1
- package/dist/chunk-STCCNLPC.js.map +0 -1
- package/dist/chunk-SVLNF434.js.map +0 -1
- package/dist/chunk-VAN4WW3F.js.map +0 -1
- package/dist/chunk-Y6UJOUE5.js.map +0 -1
- package/dist/chunk-YUO6SKJD.js.map +0 -1
- package/dist/chunk-ZPSAXX73.js.map +0 -1
- package/dist/runtime-pong.d.ts +0 -92
- package/dist/runtime-pong.js +0 -38
- /package/dist/{runtime-pong.js.map → platformer-2d.js.map} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zylem/behaviors",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Tree-shakable Zylem behavior descriptors, systems, coordinators, and runtime-agnostic behavior helpers.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,6 +57,10 @@
|
|
|
57
57
|
"types": "./dist/particle-emitter/presets.d.ts",
|
|
58
58
|
"import": "./dist/particle-emitter/presets.js"
|
|
59
59
|
},
|
|
60
|
+
"./platformer-2d": {
|
|
61
|
+
"types": "./dist/platformer-2d.d.ts",
|
|
62
|
+
"import": "./dist/platformer-2d.js"
|
|
63
|
+
},
|
|
60
64
|
"./platformer-3d": {
|
|
61
65
|
"types": "./dist/platformer-3d.d.ts",
|
|
62
66
|
"import": "./dist/platformer-3d.js"
|
|
@@ -73,10 +77,6 @@
|
|
|
73
77
|
"types": "./dist/runtime-2d.d.ts",
|
|
74
78
|
"import": "./dist/runtime-2d.js"
|
|
75
79
|
},
|
|
76
|
-
"./runtime-pong": {
|
|
77
|
-
"types": "./dist/runtime-pong.d.ts",
|
|
78
|
-
"import": "./dist/runtime-pong.js"
|
|
79
|
-
},
|
|
80
80
|
"./screen-visibility": {
|
|
81
81
|
"types": "./dist/screen-visibility.d.ts",
|
|
82
82
|
"import": "./dist/screen-visibility.js"
|
|
@@ -128,6 +128,7 @@
|
|
|
128
128
|
"./package.json": "./package.json"
|
|
129
129
|
},
|
|
130
130
|
"scripts": {
|
|
131
|
+
"zylem": "node --experimental-strip-types ./scripts/zylem-runner.ts",
|
|
131
132
|
"build": "tsup",
|
|
132
133
|
"dev": "tsup --watch",
|
|
133
134
|
"typecheck": "tsc --noEmit",
|
|
@@ -145,6 +146,7 @@
|
|
|
145
146
|
"three": "^0.180.0"
|
|
146
147
|
},
|
|
147
148
|
"devDependencies": {
|
|
149
|
+
"@clack/prompts": "^1.6.0",
|
|
148
150
|
"@dimforge/rapier3d-compat": "^0.11.2",
|
|
149
151
|
"@types/node": "^20.19.13",
|
|
150
152
|
"@types/three": "0.171.0",
|
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BehaviorDescriptor
|
|
3
|
-
*
|
|
4
|
-
* Type-safe behavior descriptors that provide options inference.
|
|
5
|
-
* Used with entity.use() to declaratively attach behaviors to entities.
|
|
6
|
-
*
|
|
7
|
-
* Each behavior can define its own handle type via `createHandle`,
|
|
8
|
-
* providing behavior-specific methods with full type safety.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Base handle returned by entity.use() for lazy access to behavior runtime.
|
|
13
|
-
* FSM is null until entity is spawned and components are initialized.
|
|
14
|
-
*/
|
|
15
|
-
interface BaseBehaviorHandle<O extends Record<string, any> = Record<string, any>> {
|
|
16
|
-
/** Get the FSM instance (null until entity is spawned) */
|
|
17
|
-
getFSM(): any | null;
|
|
18
|
-
/** Get the current options */
|
|
19
|
-
getOptions(): O;
|
|
20
|
-
/** Access the underlying behavior ref */
|
|
21
|
-
readonly ref: BehaviorRef<O>;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Reference to a behavior stored on an entity
|
|
25
|
-
*/
|
|
26
|
-
interface BehaviorRef<O extends Record<string, any> = Record<string, any>> {
|
|
27
|
-
/** The behavior descriptor */
|
|
28
|
-
descriptor: BehaviorDescriptor<O, any>;
|
|
29
|
-
/** Merged options (defaults + overrides) */
|
|
30
|
-
options: O;
|
|
31
|
-
/** Optional FSM instance - set lazily when entity is spawned */
|
|
32
|
-
fsm?: any;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* A typed behavior descriptor that associates a symbol key with:
|
|
36
|
-
* - Default options (providing type inference)
|
|
37
|
-
* - A system factory to create the behavior system
|
|
38
|
-
* - An optional handle factory for behavior-specific methods
|
|
39
|
-
*/
|
|
40
|
-
interface BehaviorDescriptor<O extends Record<string, any> = Record<string, any>, H extends Record<string, any> = Record<string, never>, I = unknown> {
|
|
41
|
-
/** Unique symbol identifying this behavior */
|
|
42
|
-
readonly key: symbol;
|
|
43
|
-
/** Default options (used for type inference) */
|
|
44
|
-
readonly defaultOptions: O;
|
|
45
|
-
/** Factory to create the behavior system */
|
|
46
|
-
readonly systemFactory: any;
|
|
47
|
-
/**
|
|
48
|
-
* Optional factory to create behavior-specific handle methods.
|
|
49
|
-
* These methods are merged into the handle returned by entity.use().
|
|
50
|
-
*/
|
|
51
|
-
readonly createHandle?: (ref: any) => H;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* The full handle type returned by entity.use().
|
|
55
|
-
* Combines base handle with behavior-specific methods.
|
|
56
|
-
*/
|
|
57
|
-
type BehaviorHandle<O extends Record<string, any> = Record<string, any>, H extends Record<string, any> = Record<string, never>> = BaseBehaviorHandle<O> & H;
|
|
58
|
-
/**
|
|
59
|
-
* Configuration for defining a new behavior
|
|
60
|
-
*/
|
|
61
|
-
interface DefineBehaviorConfig<O extends Record<string, any>, H extends Record<string, any> = Record<string, never>, I = unknown> {
|
|
62
|
-
/** Human-readable name for debugging */
|
|
63
|
-
name: string;
|
|
64
|
-
/** Default options - these define the type */
|
|
65
|
-
defaultOptions: O;
|
|
66
|
-
/** Factory function to create the system */
|
|
67
|
-
systemFactory: BehaviorSystemFactory;
|
|
68
|
-
/**
|
|
69
|
-
* Optional factory to create behavior-specific handle methods.
|
|
70
|
-
* The returned object is merged into the handle returned by entity.use().
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* ```typescript
|
|
74
|
-
* createHandle: (ref) => ({
|
|
75
|
-
* getLastHits: () => ref.fsm?.getLastHits() ?? null,
|
|
76
|
-
* getMovement: (moveX, moveY) => ref.fsm?.getMovement(moveX, moveY) ?? { moveX, moveY },
|
|
77
|
-
* }),
|
|
78
|
-
* ```
|
|
79
|
-
*/
|
|
80
|
-
createHandle?: (ref: BehaviorRef<O>) => H;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Define a typed behavior descriptor.
|
|
84
|
-
*
|
|
85
|
-
* @example
|
|
86
|
-
* ```typescript
|
|
87
|
-
* export const WorldBoundary2DBehavior = defineBehavior({
|
|
88
|
-
* name: 'world-boundary-2d',
|
|
89
|
-
* defaultOptions: { boundaries: { top: 0, bottom: 0, left: 0, right: 0 } },
|
|
90
|
-
* systemFactory: (ctx) => new WorldBoundary2DSystem(ctx.world),
|
|
91
|
-
* createHandle: (ref) => ({
|
|
92
|
-
* getLastHits: () => ref.fsm?.getLastHits() ?? null,
|
|
93
|
-
* getMovement: (moveX: number, moveY: number) =>
|
|
94
|
-
* ref.fsm?.getMovement(moveX, moveY) ?? { moveX, moveY },
|
|
95
|
-
* }),
|
|
96
|
-
* });
|
|
97
|
-
*
|
|
98
|
-
* // Usage - handle has getLastHits and getMovement with full types
|
|
99
|
-
* const boundary = ship.use(WorldBoundary2DBehavior, { ... });
|
|
100
|
-
* const hits = boundary.getLastHits(); // Fully typed!
|
|
101
|
-
* ```
|
|
102
|
-
*/
|
|
103
|
-
declare function defineBehavior<O extends Record<string, any>, H extends Record<string, any> = Record<string, never>, I = unknown>(config: DefineBehaviorConfig<O, H, I>): BehaviorDescriptor<O, H, I>;
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Minimal, runtime-agnostic entity options contract.
|
|
107
|
-
*
|
|
108
|
-
* The full engine entity (in `@zylem/game-lib`) provides a richer options type,
|
|
109
|
-
* but behaviors only rely on this loose shape.
|
|
110
|
-
*/
|
|
111
|
-
interface GameEntityOptions {
|
|
112
|
-
[key: string]: any;
|
|
113
|
-
name?: string;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Structural stand-in for the engine `GameEntity`.
|
|
117
|
-
*
|
|
118
|
-
* Behaviors annotate against this loose contract so that `@zylem/behaviors`
|
|
119
|
-
* (and its `@zylem/behaviors/core` surface) never has to depend on the concrete
|
|
120
|
-
* `@zylem/game-lib` entity implementation. The real engine entity is
|
|
121
|
-
* structurally assignable to this type.
|
|
122
|
-
*/
|
|
123
|
-
declare class GameEntity<TOptions = unknown> {
|
|
124
|
-
[key: string]: any;
|
|
125
|
-
uuid: string;
|
|
126
|
-
name: string;
|
|
127
|
-
type: string;
|
|
128
|
-
options?: TOptions & Record<string, unknown>;
|
|
129
|
-
group: any;
|
|
130
|
-
mesh?: any;
|
|
131
|
-
materials?: any[];
|
|
132
|
-
body: any;
|
|
133
|
-
collider: any;
|
|
134
|
-
colliderDesc?: any;
|
|
135
|
-
colliderDescs: any[];
|
|
136
|
-
bodyDesc?: any;
|
|
137
|
-
physicsAttached: boolean;
|
|
138
|
-
runtimeHandle?: number;
|
|
139
|
-
transformStore?: any;
|
|
140
|
-
nodeDestroy?: any;
|
|
141
|
-
isInstanced?: boolean;
|
|
142
|
-
private __behaviorRefs;
|
|
143
|
-
create(): this;
|
|
144
|
-
onCleanup(callback: () => void): this;
|
|
145
|
-
setPosition(_x: number, _y: number, _z: number): void;
|
|
146
|
-
setRotation(_x: number, _y: number, _z: number): void;
|
|
147
|
-
setRotationZ(_z: number): void;
|
|
148
|
-
setScale(_x: number, _y: number, _z: number): void;
|
|
149
|
-
/**
|
|
150
|
-
* Attach a behavior to this entity. The real engine entity does substantially
|
|
151
|
-
* more, but this functional stub stores the merged ref and builds the handle
|
|
152
|
-
* so descriptor/handle logic (and tests that drive behaviors directly) work
|
|
153
|
-
* without the full engine.
|
|
154
|
-
*/
|
|
155
|
-
use<O extends Record<string, any>, H extends Record<string, any> = Record<string, never>>(descriptor: BehaviorDescriptor<O, H>, options?: Partial<O>): BehaviorHandle<O, H>;
|
|
156
|
-
/** Live behavior refs attached via {@link use}. */
|
|
157
|
-
getBehaviorRefs(): BehaviorRef<any>[];
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Factory contract injected into behavior systems via
|
|
161
|
-
* {@link BehaviorSystemContext.createEntity}. The host engine supplies the real
|
|
162
|
-
* entity factory at stage-construction time.
|
|
163
|
-
*/
|
|
164
|
-
type CreateEntityFn = (options?: Partial<GameEntityOptions>) => GameEntity<GameEntityOptions>;
|
|
165
|
-
|
|
166
|
-
declare const StageBodyKind: {
|
|
167
|
-
readonly Dynamic: 0;
|
|
168
|
-
readonly Static: 1;
|
|
169
|
-
readonly KinematicPosition: 2;
|
|
170
|
-
readonly KinematicVelocity: 3;
|
|
171
|
-
};
|
|
172
|
-
declare const StageBoundaryDim: {
|
|
173
|
-
readonly Two: 2;
|
|
174
|
-
readonly Three: 3;
|
|
175
|
-
};
|
|
176
|
-
declare const StageRicochetDim: {
|
|
177
|
-
readonly Two: 2;
|
|
178
|
-
readonly Three: 3;
|
|
179
|
-
};
|
|
180
|
-
declare const StageRicochetReflection: {
|
|
181
|
-
readonly Mirror: 0;
|
|
182
|
-
readonly Angled: 1;
|
|
183
|
-
};
|
|
184
|
-
declare const StageTopDownPlane: {
|
|
185
|
-
readonly Xy: 0;
|
|
186
|
-
readonly Xz: 1;
|
|
187
|
-
};
|
|
188
|
-
declare const StageEventType: {
|
|
189
|
-
readonly CollisionStarted: 1;
|
|
190
|
-
readonly CollisionStopped: 2;
|
|
191
|
-
readonly BoundaryHit: 3;
|
|
192
|
-
readonly Ricochet: 4;
|
|
193
|
-
readonly RegionEntered: 5;
|
|
194
|
-
readonly JumpStarted: 6;
|
|
195
|
-
readonly Landed: 7;
|
|
196
|
-
readonly Wrapped: 8;
|
|
197
|
-
readonly CooldownFired: 9;
|
|
198
|
-
};
|
|
199
|
-
interface WasmStageRuntime {
|
|
200
|
-
getPose(handle: number): any;
|
|
201
|
-
attachThruster(handle: number, opts: any): boolean;
|
|
202
|
-
setThrusterInput(handle: number, thrust: number, rotate: number): void;
|
|
203
|
-
attachTopDown(handle: number, opts: {
|
|
204
|
-
plane: number;
|
|
205
|
-
speed: number;
|
|
206
|
-
faceMovement?: boolean;
|
|
207
|
-
}): boolean;
|
|
208
|
-
setTopDownInput(handle: number, moveX: number, moveY: number): void;
|
|
209
|
-
attachShooter2D(handle: number, opts: any): boolean;
|
|
210
|
-
attachScreenWrap(handle: number, opts: any): boolean;
|
|
211
|
-
queryScreenWrap(handle: number): any;
|
|
212
|
-
attachWorldBoundary(handle: number, dim: number, opts: any): boolean;
|
|
213
|
-
queryWorldBoundary(handle: number): any;
|
|
214
|
-
attachRicochet(handle: number, dim: number, opts: any): boolean;
|
|
215
|
-
attachPlatformer3D(handle: number, opts: any): boolean;
|
|
216
|
-
setPlatformer3DInputAxes(handle: number, moveX: number, moveZ: number): void;
|
|
217
|
-
setPlatformer3DInputButtons(handle: number, jump: boolean, run: boolean): void;
|
|
218
|
-
attachFirstPerson(handle: number, opts: any): boolean;
|
|
219
|
-
setFirstPersonInput(handle: number, input: any): void;
|
|
220
|
-
attachJumper2D(handle: number, opts: any): boolean;
|
|
221
|
-
setJumper2DInput(handle: number, jumpPressed: boolean): void;
|
|
222
|
-
attachJumper3D(handle: number, opts: any): boolean;
|
|
223
|
-
setJumper3DInput(handle: number, jumpPressed: boolean): void;
|
|
224
|
-
}
|
|
225
|
-
/** Default options used when constructing a wasm-backed Stage runtime. */
|
|
226
|
-
interface WasmStageRuntimeOptions {
|
|
227
|
-
initialCapacity?: number;
|
|
228
|
-
gravity?: readonly [number, number, number];
|
|
229
|
-
imports?: WebAssembly.Imports;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* BehaviorSystem Interface
|
|
234
|
-
*
|
|
235
|
-
* Legacy behavior systems reserved the first `update` argument for an ECS world
|
|
236
|
-
* handle; it is always `undefined` now.
|
|
237
|
-
*/
|
|
238
|
-
/** @deprecated Retained only for the first argument slot of `BehaviorSystem.update`. */
|
|
239
|
-
type BehaviorEcsHandle = unknown;
|
|
240
|
-
/**
|
|
241
|
-
* A behavior system that processes entities with specific components.
|
|
242
|
-
*
|
|
243
|
-
* @example
|
|
244
|
-
* ```typescript
|
|
245
|
-
* class ThrusterMovementSystem implements BehaviorSystem {
|
|
246
|
-
* update(_ecs: BehaviorEcsHandle | undefined, delta: number): void {
|
|
247
|
-
* // Iterate behavior links, push intent into wasm runtime, etc.
|
|
248
|
-
* }
|
|
249
|
-
* }
|
|
250
|
-
* ```
|
|
251
|
-
*/
|
|
252
|
-
interface BehaviorSystem {
|
|
253
|
-
/** Optional eager initialization when a behavior link is registered on a live entity */
|
|
254
|
-
attach?(link: BehaviorEntityLink): void;
|
|
255
|
-
/** Called once per frame. The first argument is always `undefined` (reserved legacy slot). */
|
|
256
|
-
update(ecs: BehaviorEcsHandle | undefined, delta: number): void;
|
|
257
|
-
/** Optional cleanup when a behavior link is detached from a live entity */
|
|
258
|
-
detach?(link: BehaviorEntityLink): void;
|
|
259
|
-
/** Optional cleanup when stage is destroyed */
|
|
260
|
-
destroy?(ecs?: BehaviorEcsHandle): void;
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Runtime link between a spawned entity and one of its behavior refs.
|
|
264
|
-
* Systems can iterate these links to avoid scanning all world entities.
|
|
265
|
-
*/
|
|
266
|
-
interface BehaviorEntityLink {
|
|
267
|
-
entity: any;
|
|
268
|
-
ref: any;
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Context provided to behavior-system factories.
|
|
272
|
-
*
|
|
273
|
-
* After the runtime-only stage migration, `wasmStage` is the source of
|
|
274
|
-
* truth — descriptors should call `wasmStage.attach<X>(handle, opts)` /
|
|
275
|
-
* `wasmStage.query<X>(handle)` from inside the system instead of touching
|
|
276
|
-
* `entity.body` directly. The legacy `world` / `scene` fields remain for
|
|
277
|
-
* unmigrated descriptors.
|
|
278
|
-
*/
|
|
279
|
-
interface BehaviorSystemContext {
|
|
280
|
-
world: any;
|
|
281
|
-
scene: any;
|
|
282
|
-
/** Wasm-driven Stage runtime; omitted when the stage has no wasm module. */
|
|
283
|
-
wasmStage?: WasmStageRuntime | null;
|
|
284
|
-
/**
|
|
285
|
-
* Returns live behavior links for a descriptor key.
|
|
286
|
-
* O(1) lookup into a pre-built stage index.
|
|
287
|
-
*/
|
|
288
|
-
getBehaviorLinks?: (key: symbol) => Iterable<BehaviorEntityLink>;
|
|
289
|
-
/**
|
|
290
|
-
* Host-injected entity factory. Behaviors that spawn entities at runtime
|
|
291
|
-
* (e.g. destructible-3d fragments) use this instead of importing the engine
|
|
292
|
-
* entity factory directly, keeping the behavior layer decoupled.
|
|
293
|
-
*/
|
|
294
|
-
createEntity?: CreateEntityFn;
|
|
295
|
-
/**
|
|
296
|
-
* Host-injected accessor for the global game-state bag, passed to entity
|
|
297
|
-
* lifecycle hooks (e.g. `nodeDestroy`).
|
|
298
|
-
*/
|
|
299
|
-
getGlobals?: () => any;
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* Factory function that creates a BehaviorSystem.
|
|
303
|
-
* Receives the stage for access to world, scene, etc.
|
|
304
|
-
*/
|
|
305
|
-
type BehaviorSystemFactory<T extends BehaviorSystem = BehaviorSystem> = (stage: BehaviorSystemContext) => T;
|
|
306
|
-
|
|
307
|
-
export { type BaseBehaviorHandle as B, type CreateEntityFn as C, type DefineBehaviorConfig as D, GameEntity as G, StageBodyKind as S, type WasmStageRuntime as W, type BehaviorDescriptor as a, type BehaviorEcsHandle as b, type BehaviorEntityLink as c, type BehaviorHandle as d, type BehaviorRef as e, type BehaviorSystem as f, type BehaviorSystemContext as g, type BehaviorSystemFactory as h, type GameEntityOptions as i, StageBoundaryDim as j, StageEventType as k, StageRicochetDim as l, StageRicochetReflection as m, StageTopDownPlane as n, type WasmStageRuntimeOptions as o, defineBehavior as p };
|
package/dist/chunk-2C3Z5GE7.js
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
defineBehavior
|
|
3
|
-
} from "./chunk-EZNCCO4L.js";
|
|
4
|
-
|
|
5
|
-
// src/lib/behaviors/runtime-pong/runtime-pong.descriptors.ts
|
|
6
|
-
var runtimeNoopSystemFactory = () => ({
|
|
7
|
-
update(_ecs, _delta) {
|
|
8
|
-
}
|
|
9
|
-
});
|
|
10
|
-
var RUNTIME_PONG_BALL_BEHAVIOR_KEY = /* @__PURE__ */ Symbol.for("zylem:behavior:runtime-pong-ball");
|
|
11
|
-
var RUNTIME_PADDLE_INPUT_2D_BEHAVIOR_KEY = /* @__PURE__ */ Symbol.for("zylem:behavior:runtime-paddle-input-2d");
|
|
12
|
-
var RUNTIME_WORLD_BOUNDARY_2D_BEHAVIOR_KEY = /* @__PURE__ */ Symbol.for("zylem:behavior:runtime-world-boundary-2d");
|
|
13
|
-
var RUNTIME_RICOCHET_2D_BEHAVIOR_KEY = /* @__PURE__ */ Symbol.for("zylem:behavior:runtime-ricochet-2d");
|
|
14
|
-
var RUNTIME_TRIGGER_REGION_2D_BEHAVIOR_KEY = /* @__PURE__ */ Symbol.for("zylem:behavior:runtime-trigger-region-2d");
|
|
15
|
-
var RUNTIME_GOAL_ZONE_2D_BEHAVIOR_KEY = /* @__PURE__ */ Symbol.for("zylem:behavior:runtime-goal-zone-2d");
|
|
16
|
-
var RICOCHET_LISTENERS = /* @__PURE__ */ Symbol("runtime-ricochet-listeners");
|
|
17
|
-
var TRIGGER_REGION_LISTENERS = /* @__PURE__ */ Symbol("runtime-trigger-region-listeners");
|
|
18
|
-
var GOAL_LISTENERS = /* @__PURE__ */ Symbol("runtime-goal-listeners");
|
|
19
|
-
var RUNTIME_BALL_SET_POSITION = /* @__PURE__ */ Symbol("runtime-ball-set-position");
|
|
20
|
-
var RUNTIME_BALL_SET_VELOCITY = /* @__PURE__ */ Symbol("runtime-ball-set-velocity");
|
|
21
|
-
var RUNTIME_BALL_GET_POSITION = /* @__PURE__ */ Symbol("runtime-ball-get-position");
|
|
22
|
-
var RuntimePongBallBehavior = defineBehavior({
|
|
23
|
-
name: "runtime-pong-ball",
|
|
24
|
-
defaultOptions: {
|
|
25
|
-
initialVelocity: [0, 0]
|
|
26
|
-
},
|
|
27
|
-
systemFactory: runtimeNoopSystemFactory,
|
|
28
|
-
createHandle: (ref) => ({
|
|
29
|
-
setRuntimePosition(x, y, z = 0) {
|
|
30
|
-
const callback = ref[RUNTIME_BALL_SET_POSITION];
|
|
31
|
-
callback?.(x, y, z);
|
|
32
|
-
},
|
|
33
|
-
setRuntimeVelocity(x, y) {
|
|
34
|
-
const callback = ref[RUNTIME_BALL_SET_VELOCITY];
|
|
35
|
-
callback?.(x, y);
|
|
36
|
-
},
|
|
37
|
-
getRuntimePosition() {
|
|
38
|
-
const callback = ref[RUNTIME_BALL_GET_POSITION];
|
|
39
|
-
return callback?.() ?? null;
|
|
40
|
-
}
|
|
41
|
-
})
|
|
42
|
-
});
|
|
43
|
-
var RuntimePaddleInput2DBehavior = defineBehavior({
|
|
44
|
-
name: "runtime-paddle-input-2d",
|
|
45
|
-
defaultOptions: {
|
|
46
|
-
player: "p1",
|
|
47
|
-
speed: 5
|
|
48
|
-
},
|
|
49
|
-
systemFactory: runtimeNoopSystemFactory
|
|
50
|
-
});
|
|
51
|
-
var RuntimeWorldBoundary2DBehavior = defineBehavior({
|
|
52
|
-
name: "runtime-world-boundary-2d",
|
|
53
|
-
defaultOptions: {
|
|
54
|
-
boundaries: {
|
|
55
|
-
left: 0,
|
|
56
|
-
right: 0,
|
|
57
|
-
bottom: 0,
|
|
58
|
-
top: 0
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
systemFactory: runtimeNoopSystemFactory
|
|
62
|
-
});
|
|
63
|
-
var RuntimeRicochet2DBehavior = defineBehavior({
|
|
64
|
-
name: "runtime-ricochet-2d",
|
|
65
|
-
defaultOptions: {
|
|
66
|
-
minSpeed: 2,
|
|
67
|
-
maxSpeed: 20,
|
|
68
|
-
speedMultiplier: 1.05,
|
|
69
|
-
reflectionMode: "angled",
|
|
70
|
-
maxAngleDeg: 60
|
|
71
|
-
},
|
|
72
|
-
systemFactory: runtimeNoopSystemFactory,
|
|
73
|
-
createHandle: (ref) => ({
|
|
74
|
-
onRicochet(callback) {
|
|
75
|
-
const listeners = ref[RICOCHET_LISTENERS] ?? [];
|
|
76
|
-
if (!ref[RICOCHET_LISTENERS]) {
|
|
77
|
-
ref[RICOCHET_LISTENERS] = listeners;
|
|
78
|
-
}
|
|
79
|
-
listeners.push(callback);
|
|
80
|
-
return () => {
|
|
81
|
-
const index = listeners.indexOf(callback);
|
|
82
|
-
if (index >= 0) {
|
|
83
|
-
listeners.splice(index, 1);
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
})
|
|
88
|
-
});
|
|
89
|
-
var RuntimeTriggerRegion2DBehavior = defineBehavior({
|
|
90
|
-
name: "runtime-trigger-region-2d",
|
|
91
|
-
defaultOptions: {
|
|
92
|
-
triggerId: 0,
|
|
93
|
-
halfExtents: [0.5, 2.5]
|
|
94
|
-
},
|
|
95
|
-
systemFactory: runtimeNoopSystemFactory,
|
|
96
|
-
createHandle: (ref) => ({
|
|
97
|
-
onRegionEnter(callback) {
|
|
98
|
-
const listeners = ref[TRIGGER_REGION_LISTENERS] ?? [];
|
|
99
|
-
if (!ref[TRIGGER_REGION_LISTENERS]) {
|
|
100
|
-
ref[TRIGGER_REGION_LISTENERS] = listeners;
|
|
101
|
-
}
|
|
102
|
-
listeners.push(callback);
|
|
103
|
-
return () => {
|
|
104
|
-
const index = listeners.indexOf(callback);
|
|
105
|
-
if (index >= 0) {
|
|
106
|
-
listeners.splice(index, 1);
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
})
|
|
111
|
-
});
|
|
112
|
-
var RuntimeGoalZone2DBehavior = defineBehavior({
|
|
113
|
-
name: "runtime-goal-zone-2d",
|
|
114
|
-
defaultOptions: {
|
|
115
|
-
scorer: "p1"
|
|
116
|
-
},
|
|
117
|
-
systemFactory: runtimeNoopSystemFactory,
|
|
118
|
-
createHandle: (ref) => ({
|
|
119
|
-
onGoal(callback) {
|
|
120
|
-
const listeners = ref[GOAL_LISTENERS] ?? [];
|
|
121
|
-
if (!ref[GOAL_LISTENERS]) {
|
|
122
|
-
ref[GOAL_LISTENERS] = listeners;
|
|
123
|
-
}
|
|
124
|
-
listeners.push(callback);
|
|
125
|
-
return () => {
|
|
126
|
-
const index = listeners.indexOf(callback);
|
|
127
|
-
if (index >= 0) {
|
|
128
|
-
listeners.splice(index, 1);
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
})
|
|
133
|
-
});
|
|
134
|
-
function emitRuntimeRicochet(ref, event) {
|
|
135
|
-
const listeners = ref[RICOCHET_LISTENERS];
|
|
136
|
-
for (const listener of listeners ?? []) {
|
|
137
|
-
listener(event);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
function emitRuntimeTriggerRegionEnter(ref, event) {
|
|
141
|
-
const listeners = ref[TRIGGER_REGION_LISTENERS];
|
|
142
|
-
for (const listener of listeners ?? []) {
|
|
143
|
-
listener(event);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
function emitRuntimeGoal(ref, event) {
|
|
147
|
-
const listeners = ref[GOAL_LISTENERS];
|
|
148
|
-
for (const listener of listeners ?? []) {
|
|
149
|
-
listener(event);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
function bindRuntimePongBallHandle(ref, controls) {
|
|
153
|
-
ref[RUNTIME_BALL_SET_POSITION] = controls.setPosition;
|
|
154
|
-
ref[RUNTIME_BALL_SET_VELOCITY] = controls.setVelocity;
|
|
155
|
-
ref[RUNTIME_BALL_GET_POSITION] = controls.getPosition;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export {
|
|
159
|
-
RUNTIME_PONG_BALL_BEHAVIOR_KEY,
|
|
160
|
-
RUNTIME_PADDLE_INPUT_2D_BEHAVIOR_KEY,
|
|
161
|
-
RUNTIME_WORLD_BOUNDARY_2D_BEHAVIOR_KEY,
|
|
162
|
-
RUNTIME_RICOCHET_2D_BEHAVIOR_KEY,
|
|
163
|
-
RUNTIME_TRIGGER_REGION_2D_BEHAVIOR_KEY,
|
|
164
|
-
RUNTIME_GOAL_ZONE_2D_BEHAVIOR_KEY,
|
|
165
|
-
RuntimePongBallBehavior,
|
|
166
|
-
RuntimePaddleInput2DBehavior,
|
|
167
|
-
RuntimeWorldBoundary2DBehavior,
|
|
168
|
-
RuntimeRicochet2DBehavior,
|
|
169
|
-
RuntimeTriggerRegion2DBehavior,
|
|
170
|
-
RuntimeGoalZone2DBehavior,
|
|
171
|
-
emitRuntimeRicochet,
|
|
172
|
-
emitRuntimeTriggerRegionEnter,
|
|
173
|
-
emitRuntimeGoal,
|
|
174
|
-
bindRuntimePongBallHandle
|
|
175
|
-
};
|
|
176
|
-
//# sourceMappingURL=chunk-2C3Z5GE7.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/behaviors/runtime-pong/runtime-pong.descriptors.ts"],"sourcesContent":["import {\n\tdefineBehavior,\n\ttype BehaviorRef,\n} from '../behavior-descriptor';\nimport type { BehaviorSystem } from '../behavior-system';\n\nexport interface RuntimePongBallOptions {\n\tinitialVelocity: readonly [number, number];\n}\n\nexport interface RuntimePongBallHandle {\n\tsetRuntimePosition(x: number, y: number, z?: number): void;\n\tsetRuntimeVelocity(x: number, y: number): void;\n\tgetRuntimePosition(): { x: number; y: number; z: number } | null;\n}\n\nexport interface RuntimePaddleInput2DOptions {\n\tplayer: 'p1' | 'p2';\n\tspeed: number;\n}\n\nexport interface RuntimeWorldBoundary2DOptions {\n\tboundaries: {\n\t\tleft: number;\n\t\tright: number;\n\t\tbottom: number;\n\t\ttop: number;\n\t};\n}\n\nexport interface RuntimeRicochet2DOptions {\n\tminSpeed: number;\n\tmaxSpeed: number;\n\tspeedMultiplier: number;\n\treflectionMode: 'simple' | 'angled';\n\tmaxAngleDeg: number;\n}\n\nexport interface RuntimeRicochet2DEvent {\n\tkind: 'wall' | 'paddle';\n}\n\nexport interface RuntimeRicochet2DHandle {\n\tonRicochet(callback: (event: RuntimeRicochet2DEvent) => void): () => void;\n}\n\n/** Registers a gameplay2d trigger AABB (sensor); wasm reports overlap via {@link emitRuntimeTriggerRegionEnter}. */\nexport interface RuntimeTriggerRegion2DOptions {\n\ttriggerId: number;\n\thalfExtents: readonly [number, number];\n}\n\nexport interface RuntimeTriggerRegion2DEvent {\n\ttriggerId: number;\n}\n\nexport interface RuntimeTriggerRegion2DHandle {\n\tonRegionEnter(callback: (event: RuntimeTriggerRegion2DEvent) => void): () => void;\n}\n\nexport interface RuntimeGoalZone2DOptions {\n\tscorer: 'p1' | 'p2';\n}\n\nexport interface RuntimeGoalZone2DEvent {\n\tscorer: 'p1' | 'p2';\n}\n\nexport interface RuntimeGoalZone2DHandle {\n\tonGoal(callback: (event: RuntimeGoalZone2DEvent) => void): () => void;\n}\n\nconst runtimeNoopSystemFactory = (): BehaviorSystem => ({\n\tupdate(_ecs: unknown, _delta: number) {},\n});\n\nexport const RUNTIME_PONG_BALL_BEHAVIOR_KEY = Symbol.for('zylem:behavior:runtime-pong-ball');\nexport const RUNTIME_PADDLE_INPUT_2D_BEHAVIOR_KEY = Symbol.for('zylem:behavior:runtime-paddle-input-2d');\nexport const RUNTIME_WORLD_BOUNDARY_2D_BEHAVIOR_KEY = Symbol.for('zylem:behavior:runtime-world-boundary-2d');\nexport const RUNTIME_RICOCHET_2D_BEHAVIOR_KEY = Symbol.for('zylem:behavior:runtime-ricochet-2d');\nexport const RUNTIME_TRIGGER_REGION_2D_BEHAVIOR_KEY = Symbol.for('zylem:behavior:runtime-trigger-region-2d');\nexport const RUNTIME_GOAL_ZONE_2D_BEHAVIOR_KEY = Symbol.for('zylem:behavior:runtime-goal-zone-2d');\n\nconst RICOCHET_LISTENERS = Symbol('runtime-ricochet-listeners');\nconst TRIGGER_REGION_LISTENERS = Symbol('runtime-trigger-region-listeners');\nconst GOAL_LISTENERS = Symbol('runtime-goal-listeners');\nconst RUNTIME_BALL_SET_POSITION = Symbol('runtime-ball-set-position');\nconst RUNTIME_BALL_SET_VELOCITY = Symbol('runtime-ball-set-velocity');\nconst RUNTIME_BALL_GET_POSITION = Symbol('runtime-ball-get-position');\n\nexport const RuntimePongBallBehavior = defineBehavior<\n\tRuntimePongBallOptions,\n\tRuntimePongBallHandle\n>({\n\tname: 'runtime-pong-ball',\n\tdefaultOptions: {\n\t\tinitialVelocity: [0, 0] as [number, number],\n\t},\n\tsystemFactory: runtimeNoopSystemFactory,\n\tcreateHandle: (ref: BehaviorRef<RuntimePongBallOptions>) => ({\n\t\tsetRuntimePosition(x: number, y: number, z: number = 0): void {\n\t\t\tconst callback = (ref as any)[RUNTIME_BALL_SET_POSITION] as\n\t\t\t\t| ((x: number, y: number, z: number) => void)\n\t\t\t\t| undefined;\n\t\t\tcallback?.(x, y, z);\n\t\t},\n\t\tsetRuntimeVelocity(x: number, y: number): void {\n\t\t\tconst callback = (ref as any)[RUNTIME_BALL_SET_VELOCITY] as\n\t\t\t\t| ((x: number, y: number) => void)\n\t\t\t\t| undefined;\n\t\t\tcallback?.(x, y);\n\t\t},\n\t\tgetRuntimePosition(): { x: number; y: number; z: number } | null {\n\t\t\tconst callback = (ref as any)[RUNTIME_BALL_GET_POSITION] as\n\t\t\t\t| (() => { x: number; y: number; z: number } | null)\n\t\t\t\t| undefined;\n\t\t\treturn callback?.() ?? null;\n\t\t},\n\t}),\n});\n\nexport const RuntimePaddleInput2DBehavior = defineBehavior<RuntimePaddleInput2DOptions>({\n\tname: 'runtime-paddle-input-2d',\n\tdefaultOptions: {\n\t\tplayer: 'p1',\n\t\tspeed: 5,\n\t} as RuntimePaddleInput2DOptions,\n\tsystemFactory: runtimeNoopSystemFactory,\n});\n\nexport const RuntimeWorldBoundary2DBehavior = defineBehavior({\n\tname: 'runtime-world-boundary-2d',\n\tdefaultOptions: {\n\t\tboundaries: {\n\t\t\tleft: 0,\n\t\t\tright: 0,\n\t\t\tbottom: 0,\n\t\t\ttop: 0,\n\t\t},\n\t},\n\tsystemFactory: runtimeNoopSystemFactory,\n});\n\nexport const RuntimeRicochet2DBehavior = defineBehavior<\n\tRuntimeRicochet2DOptions,\n\tRuntimeRicochet2DHandle\n>({\n\tname: 'runtime-ricochet-2d',\n\tdefaultOptions: {\n\t\tminSpeed: 2,\n\t\tmaxSpeed: 20,\n\t\tspeedMultiplier: 1.05,\n\t\treflectionMode: 'angled' as const,\n\t\tmaxAngleDeg: 60,\n\t},\n\tsystemFactory: runtimeNoopSystemFactory,\n\tcreateHandle: (ref: BehaviorRef<RuntimeRicochet2DOptions>) => ({\n\t\tonRicochet(callback: (event: RuntimeRicochet2DEvent) => void): () => void {\n\t\t\tconst listeners =\n\t\t\t\t((ref as any)[RICOCHET_LISTENERS] as Array<(event: RuntimeRicochet2DEvent) => void> | undefined)\n\t\t\t\t?? [];\n\t\t\tif (!(ref as any)[RICOCHET_LISTENERS]) {\n\t\t\t\t(ref as any)[RICOCHET_LISTENERS] = listeners;\n\t\t\t}\n\t\t\tlisteners.push(callback);\n\t\t\treturn () => {\n\t\t\t\tconst index = listeners.indexOf(callback);\n\t\t\t\tif (index >= 0) {\n\t\t\t\t\tlisteners.splice(index, 1);\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t}),\n});\n\nexport const RuntimeTriggerRegion2DBehavior = defineBehavior<\n\tRuntimeTriggerRegion2DOptions,\n\tRuntimeTriggerRegion2DHandle\n>({\n\tname: 'runtime-trigger-region-2d',\n\tdefaultOptions: {\n\t\ttriggerId: 0,\n\t\thalfExtents: [0.5, 2.5] as [number, number],\n\t},\n\tsystemFactory: runtimeNoopSystemFactory,\n\tcreateHandle: (ref: BehaviorRef<RuntimeTriggerRegion2DOptions>) => ({\n\t\tonRegionEnter(callback: (event: RuntimeTriggerRegion2DEvent) => void): () => void {\n\t\t\tconst listeners =\n\t\t\t\t((ref as any)[TRIGGER_REGION_LISTENERS] as\n\t\t\t\t\t| Array<(event: RuntimeTriggerRegion2DEvent) => void>\n\t\t\t\t\t| undefined) ?? [];\n\t\t\tif (!(ref as any)[TRIGGER_REGION_LISTENERS]) {\n\t\t\t\t(ref as any)[TRIGGER_REGION_LISTENERS] = listeners;\n\t\t\t}\n\t\t\tlisteners.push(callback);\n\t\t\treturn () => {\n\t\t\t\tconst index = listeners.indexOf(callback);\n\t\t\t\tif (index >= 0) {\n\t\t\t\t\tlisteners.splice(index, 1);\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t}),\n});\n\nexport const RuntimeGoalZone2DBehavior = defineBehavior<\n\tRuntimeGoalZone2DOptions,\n\tRuntimeGoalZone2DHandle\n>({\n\tname: 'runtime-goal-zone-2d',\n\tdefaultOptions: {\n\t\tscorer: 'p1',\n\t} as RuntimeGoalZone2DOptions,\n\tsystemFactory: runtimeNoopSystemFactory,\n\tcreateHandle: (ref: BehaviorRef<RuntimeGoalZone2DOptions>) => ({\n\t\tonGoal(callback: (event: RuntimeGoalZone2DEvent) => void): () => void {\n\t\t\tconst listeners =\n\t\t\t\t((ref as any)[GOAL_LISTENERS] as Array<(event: RuntimeGoalZone2DEvent) => void> | undefined)\n\t\t\t\t?? [];\n\t\t\tif (!(ref as any)[GOAL_LISTENERS]) {\n\t\t\t\t(ref as any)[GOAL_LISTENERS] = listeners;\n\t\t\t}\n\t\t\tlisteners.push(callback);\n\t\t\treturn () => {\n\t\t\t\tconst index = listeners.indexOf(callback);\n\t\t\t\tif (index >= 0) {\n\t\t\t\t\tlisteners.splice(index, 1);\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t}),\n});\n\nexport function emitRuntimeRicochet(\n\tref: BehaviorRef<RuntimeRicochet2DOptions>,\n\tevent: RuntimeRicochet2DEvent,\n): void {\n\tconst listeners = (ref as any)[RICOCHET_LISTENERS] as\n\t\t| Array<(event: RuntimeRicochet2DEvent) => void>\n\t\t| undefined;\n\tfor (const listener of listeners ?? []) {\n\t\tlistener(event);\n\t}\n}\n\nexport function emitRuntimeTriggerRegionEnter(\n\tref: BehaviorRef<RuntimeTriggerRegion2DOptions>,\n\tevent: RuntimeTriggerRegion2DEvent,\n): void {\n\tconst listeners = (ref as any)[TRIGGER_REGION_LISTENERS] as\n\t\t| Array<(event: RuntimeTriggerRegion2DEvent) => void>\n\t\t| undefined;\n\tfor (const listener of listeners ?? []) {\n\t\tlistener(event);\n\t}\n}\n\nexport function emitRuntimeGoal(\n\tref: BehaviorRef<RuntimeGoalZone2DOptions>,\n\tevent: RuntimeGoalZone2DEvent,\n): void {\n\tconst listeners = (ref as any)[GOAL_LISTENERS] as\n\t\t| Array<(event: RuntimeGoalZone2DEvent) => void>\n\t\t| undefined;\n\tfor (const listener of listeners ?? []) {\n\t\tlistener(event);\n\t}\n}\n\nexport function bindRuntimePongBallHandle(\n\tref: BehaviorRef<RuntimePongBallOptions>,\n\tcontrols: {\n\t\tsetPosition: (x: number, y: number, z: number) => void;\n\t\tsetVelocity: (x: number, y: number) => void;\n\t\tgetPosition: () => { x: number; y: number; z: number } | null;\n\t},\n): void {\n\t(ref as any)[RUNTIME_BALL_SET_POSITION] = controls.setPosition;\n\t(ref as any)[RUNTIME_BALL_SET_VELOCITY] = controls.setVelocity;\n\t(ref as any)[RUNTIME_BALL_GET_POSITION] = controls.getPosition;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/behaviors/thruster/thruster-fsm.ts","../src/lib/behaviors/thruster/thruster-movement.behavior.ts","../src/lib/behaviors/thruster/thruster.descriptor.ts"],"sourcesContent":["/**\n * ThrusterFSM\n * \n * State machine controller for thruster behavior.\n * FSM does NOT touch physics or ThrusterMovementBehavior - it only writes ThrusterInputComponent.\n */\n\nimport { SyncStateMachine, t } from '../../core/utility/sync-state-machine';\nimport type { ThrusterInputComponent } from './components';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FSM State Model\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport enum ThrusterState {\n\tIdle = 'idle',\n\tActive = 'active',\n\tBoosting = 'boosting',\n\tDisabled = 'disabled',\n\tDocked = 'docked',\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FSM Events\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport enum ThrusterEvent {\n\tActivate = 'activate',\n\tDeactivate = 'deactivate',\n\tBoost = 'boost',\n\tEndBoost = 'endBoost',\n\tDisable = 'disable',\n\tEnable = 'enable',\n\tDock = 'dock',\n\tUndock = 'undock',\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FSM Context Object\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface ThrusterFSMContext {\n\tinput: ThrusterInputComponent;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Player Input (raw input from controller/keyboard)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface PlayerInput {\n\tthrust: number;\n\trotate: number;\n\tthrustX?: number;\n\tthrustY?: number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// ThrusterFSM Controller\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport class ThrusterFSM {\n\tmachine: SyncStateMachine<ThrusterState, ThrusterEvent, never>;\n\n\tconstructor(private ctx: ThrusterFSMContext) {\n\t\tthis.machine = new SyncStateMachine<ThrusterState, ThrusterEvent, never>(\n\t\t\tThrusterState.Idle,\n\t\t\t[\n\t\t\t\t// Core transitions\n\t\t\t\tt(ThrusterState.Idle, ThrusterEvent.Activate, ThrusterState.Active),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Deactivate, ThrusterState.Idle),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Boost, ThrusterState.Boosting),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Disable, ThrusterState.Disabled),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Dock, ThrusterState.Docked),\n\t\t\t\tt(ThrusterState.Boosting, ThrusterEvent.EndBoost, ThrusterState.Active),\n\t\t\t\tt(ThrusterState.Boosting, ThrusterEvent.Disable, ThrusterState.Disabled),\n\t\t\t\tt(ThrusterState.Disabled, ThrusterEvent.Enable, ThrusterState.Idle),\n\t\t\t\tt(ThrusterState.Docked, ThrusterEvent.Undock, ThrusterState.Idle),\n\t\t\t\t// Self-transitions (no-ops for redundant events)\n\t\t\t\tt(ThrusterState.Idle, ThrusterEvent.Deactivate, ThrusterState.Idle),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Activate, ThrusterState.Active),\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Get current state\n\t */\n\tgetState(): ThrusterState {\n\t\treturn this.machine.getState();\n\t}\n\n\t/**\n\t * Dispatch an event to transition state\n\t */\n\tdispatch(event: ThrusterEvent): void {\n\t\tif (this.machine.can(event)) {\n\t\t\tthis.machine.syncDispatch(event);\n\t\t}\n\t}\n\n\t/**\n\t * Update FSM state based on player input.\n\t * Auto-transitions between Idle/Active to report current state.\n\t * Does NOT modify input - just observes and reports.\n\t */\n\tupdate(playerInput: PlayerInput): void {\n\t\tconst state = this.machine.getState();\n\t\tconst hasInput =\n\t\t\tMath.abs(playerInput.thrust) > 0.01\n\t\t\t|| Math.abs(playerInput.rotate) > 0.01\n\t\t\t|| Math.abs(playerInput.thrustX ?? 0) > 0.01\n\t\t\t|| Math.abs(playerInput.thrustY ?? 0) > 0.01;\n\n\t\t// Auto-transition to report state based on input\n\t\tif (hasInput && state === ThrusterState.Idle) {\n\t\t\tthis.dispatch(ThrusterEvent.Activate);\n\t\t} else if (!hasInput && state === ThrusterState.Active) {\n\t\t\tthis.dispatch(ThrusterEvent.Deactivate);\n\t\t}\n\t}\n}\n","/**\n * ThrusterMovementBehavior\n * \n * This is the heart of the thruster movement system - a pure, stateless force generator.\n * Works identically for player, AI, and replay.\n */\n\nimport type { ZylemWorld } from '../../collision/world';\nimport type { PhysicsBodyComponent } from '../components';\nimport type { ThrusterMovementComponent, ThrusterInputComponent } from './components';\nimport {\n\tgetRotationAngle2D,\n\tnormalizeDirection2D,\n} from '../shared/direction-2d';\n\n/**\n * Zylem-style Behavior interface\n */\nexport interface Behavior {\n\tupdate(dt: number): void;\n}\n\n/**\n * Entity with thruster components\n */\nexport interface ThrusterEntity {\n\tphysics: PhysicsBodyComponent;\n\tthruster: ThrusterMovementComponent;\n\t$thruster: ThrusterInputComponent;\n}\n\n/**\n * ThrusterMovementBehavior - Force generator for thruster-equipped entities\n * \n * Responsibilities:\n * - Query entities with PhysicsBody, ThrusterMovement, and ThrusterInput components\n * - Apply velocities based on thrust input (2D mode)\n * - Apply angular velocity based on rotation input\n */\nexport class ThrusterMovementBehavior implements Behavior {\n\tconstructor(private world: ZylemWorld) {}\n\n\t/**\n\t * Update a single thruster-enabled entity.\n\t */\n\tupdateEntity(gameEntity: any, _dt: number): void {\n\t\tif (!gameEntity.physics?.body || !gameEntity.thruster || !gameEntity.$thruster) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst e: ThrusterEntity = {\n\t\t\tphysics: gameEntity.physics,\n\t\t\tthruster: gameEntity.thruster,\n\t\t\t$thruster: gameEntity.$thruster,\n\t\t};\n\n\t\tconst body = e.physics.body;\n\t\tconst thruster = e.thruster;\n\t\tconst input = e.$thruster;\n\n\t\tif (thruster.linearDamping != null && typeof body.setLinearDamping === 'function') {\n\t\t\tbody.setLinearDamping(thruster.linearDamping);\n\t\t}\n\n\t\t// Get Z rotation from quaternion (for 2D sprites)\n\t\tconst rotationZ = getRotationAngle2D(body.rotation());\n\t\tconst currentVel = body.linvel();\n\t\tconst vectorThrust = normalizeDirection2D(input.thrustX, input.thrustY);\n\n\t\t// --- Linear thrust ---\n\t\tif (vectorThrust) {\n\t\t\tconst thrustScale = Math.min(1, Math.hypot(input.thrustX, input.thrustY));\n\t\t\tconst thrustAmount = thruster.linearThrust * thrustScale * 0.1;\n\t\t\tbody.setLinvel({\n\t\t\t\tx: currentVel.x + vectorThrust.x * thrustAmount,\n\t\t\t\ty: currentVel.y + vectorThrust.y * thrustAmount,\n\t\t\t\tz: currentVel.z,\n\t\t\t}, true);\n\t\t} else if (input.thrust !== 0) {\n\t\t\tconst forwardX = Math.sin(-rotationZ);\n\t\t\tconst forwardY = Math.cos(-rotationZ);\n\t\t\tconst thrustAmount = thruster.linearThrust * input.thrust * 0.1;\n\t\t\tbody.setLinvel({\n\t\t\t\tx: currentVel.x + forwardX * thrustAmount,\n\t\t\t\ty: currentVel.y + forwardY * thrustAmount,\n\t\t\t\tz: currentVel.z\n\t\t\t}, true);\n\t\t}\n\n\t\t// --- Angular thrust (Z-axis for 2D) ---\n\t\tif (input.rotate !== 0) {\n\t\t\tbody.setAngvel({ x: 0, y: 0, z: -thruster.angularThrust * input.rotate }, true);\n\t\t} else {\n\t\t\t// Stop rotation when no input\n\t\t\tconst angVel = body.angvel();\n\t\t\tbody.setAngvel({ x: angVel.x, y: angVel.y, z: 0 }, true);\n\t\t}\n\t}\n\n\tupdate(dt: number): void {\n\t\tif (!this.world?.collisionMap) return;\n\t\tfor (const [, entity] of this.world.collisionMap) {\n\t\t\tthis.updateEntity(entity, dt);\n\t\t}\n\t}\n}\n","/**\n * Thruster Behavior Descriptor\n * \n * Type-safe descriptor for the thruster behavior system using the new entity.use() API.\n * This wraps the existing ThrusterMovementBehavior and components.\n */\n\nimport { defineBehavior } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport { ThrusterMovementBehavior, ThrusterEntity } from './thruster-movement.behavior';\nimport { ThrusterFSM } from './thruster-fsm';\nimport {\n\tcreateThrusterInputComponent,\n\tcreateThrusterMovementComponent,\n\ttype ThrusterMovementComponent,\n\ttype ThrusterInputComponent,\n} from './components';\nimport type { WasmStageRuntime } from '../../runtime/wasm-stage-runtime';\n\n/**\n * Thruster behavior options (typed for entity.use() autocomplete)\n */\nexport interface ThrusterBehaviorOptions {\n\t/** Forward thrust force (default: 10) */\n\tlinearThrust: number;\n\t/** Rotation torque (default: 5) */\n\tangularThrust: number;\n\t/** Optional linear damping override */\n\tlinearDamping?: number;\n}\n\nconst defaultOptions: ThrusterBehaviorOptions = {\n\tlinearThrust: 10,\n\tangularThrust: 5,\n\tlinearDamping: undefined,\n};\n\nconst THRUSTER_BEHAVIOR_KEY = Symbol.for('zylem:behavior:thruster');\n\n/**\n * Adapter that wraps ThrusterMovementBehavior as a BehaviorSystem.\n * \n * This bridges the entity.use() pattern with the ECS component-based approach:\n * - Reads options from entity behaviorRefs\n * - Initializes ThrusterMovementComponent and ThrusterInputComponent on entities\n * - Creates FSM lazily and attaches to BehaviorRef for access via handle.getFSM()\n * - Delegates physics to ThrusterMovementBehavior\n * \n * NOTE: Input is controlled by the user via entity.onUpdate() - set entity.input.thrust/rotate\n */\nclass ThrusterBehaviorSystem implements BehaviorSystem {\n\tprivate movementBehavior: ThrusterMovementBehavior;\n\tprivate attachedRuntimeSlots = new Set<number>();\n\n\tconstructor(\n\t\tprivate world: any,\n\t\tprivate wasmStage: WasmStageRuntime | null,\n\t\tprivate getBehaviorLinks?: (key: symbol) => Iterable<BehaviorEntityLink>,\n\t) {\n\t\tthis.movementBehavior = new ThrusterMovementBehavior(world);\n\t}\n\n\tupdate(_ecs: unknown, delta: number): void {\n\t\tconst links = this.getBehaviorLinks?.(THRUSTER_BEHAVIOR_KEY);\n\t\tif (!links) return;\n\n\t\tfor (const link of links) {\n\t\t\tconst gameEntity = link.entity as any;\n\t\t\tconst thrusterRef = link.ref as any;\n\n\t\t\tconst options = thrusterRef.options as ThrusterBehaviorOptions;\n\n\t\t\tif (!gameEntity.thruster) {\n\t\t\t\tgameEntity.thruster = createThrusterMovementComponent(\n\t\t\t\t\toptions.linearThrust,\n\t\t\t\t\toptions.angularThrust,\n\t\t\t\t\t{ linearDamping: options.linearDamping },\n\t\t\t\t) as ThrusterMovementComponent;\n\t\t\t}\n\n\t\t\tif (!gameEntity.$thruster) {\n\t\t\t\tgameEntity.$thruster = createThrusterInputComponent() as ThrusterInputComponent;\n\t\t\t}\n\n\t\t\tif (!thrusterRef.fsm && gameEntity.$thruster) {\n\t\t\t\tthrusterRef.fsm = new ThrusterFSM({ input: gameEntity.$thruster });\n\t\t\t}\n\n\t\t\tif (thrusterRef.fsm && gameEntity.$thruster) {\n\t\t\t\tthrusterRef.fsm.update({\n\t\t\t\t\tthrust: gameEntity.$thruster.thrust,\n\t\t\t\t\trotate: gameEntity.$thruster.rotate,\n\t\t\t\t\tthrustX: gameEntity.$thruster.thrustX,\n\t\t\t\t\tthrustY: gameEntity.$thruster.thrustY,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst handle = (gameEntity.runtimeHandle ?? -1) as number;\n\t\t\tif (this.wasmStage && handle >= 0) {\n\t\t\t\tthis.ensureWasmAttached(handle, options);\n\t\t\t\tconst input = gameEntity.$thruster as ThrusterInputComponent | undefined;\n\t\t\t\tif (input) {\n\t\t\t\t\tthis.wasmStage.setThrusterInput(handle, input.thrust, input.rotate);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!gameEntity.body) continue;\n\t\t\tif (!gameEntity.physics) {\n\t\t\t\tgameEntity.physics = { body: gameEntity.body };\n\t\t\t}\n\t\t\tthis.movementBehavior.updateEntity(gameEntity, delta);\n\t\t}\n\t}\n\n\tprivate ensureWasmAttached(handle: number, options: ThrusterBehaviorOptions): void {\n\t\tif (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;\n\t\tthis.wasmStage.attachThruster(handle, {\n\t\t\tmaxSpeed: 50,\n\t\t\tacceleration: options.linearThrust,\n\t\t\tturnRateRadPerSec: options.angularThrust,\n\t\t\tlinearDamping: options.linearDamping ?? 0,\n\t\t});\n\t\tthis.attachedRuntimeSlots.add(handle);\n\t}\n\n\tdestroy(_ecs: unknown): void {\n\t\tthis.attachedRuntimeSlots.clear();\n\t}\n}\n\n/**\n * ThrusterBehavior - typed descriptor for thruster movement.\n * \n * Uses the existing ThrusterMovementBehavior under the hood.\n * \n * @example\n * ```typescript\n * import { ThrusterBehavior } from \"@zylem/game-lib/behavior\";\n * \n * const ship = createSprite({ ... });\n * ship.use(ThrusterBehavior, { linearThrust: 15, angularThrust: 8 });\n * ```\n */\nexport const ThrusterBehavior = defineBehavior<ThrusterBehaviorOptions, Record<string, never>, ThrusterEntity>({\n\tname: 'thruster',\n\tdefaultOptions,\n\tsystemFactory: (ctx) =>\n\t\tnew ThrusterBehaviorSystem(ctx.world, ctx.wasmStage ?? null, ctx.getBehaviorLinks),\n});\n"],"mappings":"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","names":["ThrusterState","ThrusterEvent"]}
|
package/dist/chunk-3PYGRHAL.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getBounds3DNormalFromHits
|
|
3
|
-
} from "./chunk-OHCPV2NT.js";
|
|
4
|
-
|
|
5
|
-
// src/lib/coordinators/boundary-ricochet-3d.coordinator.ts
|
|
6
|
-
var BoundaryRicochet3DCoordinator = class {
|
|
7
|
-
constructor(entity, boundary, ricochet) {
|
|
8
|
-
this.entity = entity;
|
|
9
|
-
this.boundary = boundary;
|
|
10
|
-
this.ricochet = ricochet;
|
|
11
|
-
}
|
|
12
|
-
entity;
|
|
13
|
-
boundary;
|
|
14
|
-
ricochet;
|
|
15
|
-
update() {
|
|
16
|
-
const hits = this.boundary.getLastHits();
|
|
17
|
-
if (!hits) return false;
|
|
18
|
-
const anyHit = hits.left || hits.right || hits.top || hits.bottom || hits.back || hits.front;
|
|
19
|
-
if (!anyHit) return false;
|
|
20
|
-
const clamped = this.boundary.getLastClampedPosition();
|
|
21
|
-
if (clamped && this.entity.body) {
|
|
22
|
-
this.entity.body.setTranslation(clamped, true);
|
|
23
|
-
}
|
|
24
|
-
const normal = getBounds3DNormalFromHits(hits);
|
|
25
|
-
return this.ricochet.applyRicochet({
|
|
26
|
-
entity: this.entity,
|
|
27
|
-
contact: { normal }
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export {
|
|
33
|
-
BoundaryRicochet3DCoordinator
|
|
34
|
-
};
|
|
35
|
-
//# sourceMappingURL=chunk-3PYGRHAL.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/coordinators/boundary-ricochet-3d.coordinator.ts"],"sourcesContent":["import { GameEntity } from '../entities/entity';\nimport type { MoveableEntity } from '../actions/capabilities/moveable';\nimport type { Ricochet3DHandle } from '../behaviors/ricochet-3d/ricochet-3d.descriptor';\nimport type { WorldBoundary3DHandle } from '../behaviors/world-boundary-3d/world-boundary-3d.descriptor';\nimport { getBounds3DNormalFromHits } from '../behaviors/shared/bounds-3d';\n\nexport class BoundaryRicochet3DCoordinator {\n\tconstructor(\n\t\tprivate entity: GameEntity<any> & MoveableEntity,\n\t\tprivate boundary: WorldBoundary3DHandle,\n\t\tprivate ricochet: Ricochet3DHandle,\n\t) {}\n\n\tpublic update(): boolean {\n\t\tconst hits = this.boundary.getLastHits();\n\t\tif (!hits) return false;\n\n\t\tconst anyHit =\n\t\t\thits.left || hits.right || hits.top || hits.bottom || hits.back || hits.front;\n\t\tif (!anyHit) return false;\n\n\t\tconst clamped = this.boundary.getLastClampedPosition();\n\t\tif (clamped && this.entity.body) {\n\t\t\tthis.entity.body.setTranslation(clamped, true);\n\t\t}\n\n\t\tconst normal = getBounds3DNormalFromHits(hits);\n\t\treturn this.ricochet.applyRicochet({\n\t\t\tentity: this.entity,\n\t\t\tcontact: { normal },\n\t\t});\n\t}\n}\n"],"mappings":";;;;;AAMO,IAAM,gCAAN,MAAoC;AAAA,EAC1C,YACS,QACA,UACA,UACP;AAHO;AACA;AACA;AAAA,EACN;AAAA,EAHM;AAAA,EACA;AAAA,EACA;AAAA,EAGF,SAAkB;AACxB,UAAM,OAAO,KAAK,SAAS,YAAY;AACvC,QAAI,CAAC,KAAM,QAAO;AAElB,UAAM,SACL,KAAK,QAAQ,KAAK,SAAS,KAAK,OAAO,KAAK,UAAU,KAAK,QAAQ,KAAK;AACzE,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,UAAU,KAAK,SAAS,uBAAuB;AACrD,QAAI,WAAW,KAAK,OAAO,MAAM;AAChC,WAAK,OAAO,KAAK,eAAe,SAAS,IAAI;AAAA,IAC9C;AAEA,UAAM,SAAS,0BAA0B,IAAI;AAC7C,WAAO,KAAK,SAAS,cAAc;AAAA,MAClC,QAAQ,KAAK;AAAA,MACb,SAAS,EAAE,OAAO;AAAA,IACnB,CAAC;AAAA,EACF;AACD;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/coordinators/shared/top-down-aim.ts"],"sourcesContent":["import {\n\tangleFromDirection2D,\n\tdirectionFromAngle2D,\n\tgetRotationAngle2D,\n\tnormalizeDirection2D,\n} from '../../behaviors/shared/direction-2d';\n\nexport interface ResolvedAim2D {\n\tangle: number;\n\tdirection: { x: number; y: number };\n\thasAimInput: boolean;\n}\n\nexport function getEntityFacingAngle2D(entity: any): number {\n\tif (entity.topDownMovementState) {\n\t\treturn entity.topDownMovementState.facingAngle;\n\t}\n\n\tif (entity.body?.rotation) {\n\t\treturn getRotationAngle2D(entity.body.rotation());\n\t}\n\n\treturn entity._rotation2DAngle ?? 0;\n}\n\nexport function resolveAim2D(\n\taimX: number,\n\taimY: number,\n\tfallbackAngle: number,\n): ResolvedAim2D {\n\tconst direction = normalizeDirection2D(aimX, aimY);\n\tif (direction) {\n\t\treturn {\n\t\t\tangle: angleFromDirection2D(direction),\n\t\t\tdirection,\n\t\t\thasAimInput: true,\n\t\t};\n\t}\n\n\treturn {\n\t\tangle: fallbackAngle,\n\t\tdirection: directionFromAngle2D(fallbackAngle),\n\t\thasAimInput: false,\n\t};\n}\n"],"mappings":";;;;;;;;AAaO,SAAS,uBAAuB,QAAqB;AAC3D,MAAI,OAAO,sBAAsB;AAChC,WAAO,OAAO,qBAAqB;AAAA,EACpC;AAEA,MAAI,OAAO,MAAM,UAAU;AAC1B,WAAO,mBAAmB,OAAO,KAAK,SAAS,CAAC;AAAA,EACjD;AAEA,SAAO,OAAO,oBAAoB;AACnC;AAEO,SAAS,aACf,MACA,MACA,eACgB;AAChB,QAAM,YAAY,qBAAqB,MAAM,IAAI;AACjD,MAAI,WAAW;AACd,WAAO;AAAA,MACN,OAAO,qBAAqB,SAAS;AAAA,MACrC;AAAA,MACA,aAAa;AAAA,IACd;AAAA,EACD;AAEA,SAAO;AAAA,IACN,OAAO;AAAA,IACP,WAAW,qBAAqB,aAAa;AAAA,IAC7C,aAAa;AAAA,EACd;AACD;","names":[]}
|