@zylem/behaviors 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 +26 -0
- package/dist/behavior-system-DYbx-x_-.d.ts +307 -0
- package/dist/chunk-2C3Z5GE7.js +176 -0
- package/dist/chunk-2C3Z5GE7.js.map +1 -0
- package/dist/chunk-2CLT36VB.js +241 -0
- package/dist/chunk-2CLT36VB.js.map +1 -0
- package/dist/chunk-3PYGRHAL.js +35 -0
- package/dist/chunk-3PYGRHAL.js.map +1 -0
- package/dist/chunk-4I6E6DGV.js +212 -0
- package/dist/chunk-4I6E6DGV.js.map +1 -0
- package/dist/chunk-4URF65BR.js +44 -0
- package/dist/chunk-4URF65BR.js.map +1 -0
- package/dist/chunk-6C6NXNEW.js +38 -0
- package/dist/chunk-6C6NXNEW.js.map +1 -0
- package/dist/chunk-ARJWUNRE.js +431 -0
- package/dist/chunk-ARJWUNRE.js.map +1 -0
- package/dist/chunk-BXP4K7RF.js +1205 -0
- package/dist/chunk-BXP4K7RF.js.map +1 -0
- package/dist/chunk-DYLH6K7B.js +44 -0
- package/dist/chunk-DYLH6K7B.js.map +1 -0
- package/dist/chunk-EIWQM6U3.js +27 -0
- package/dist/chunk-EIWQM6U3.js.map +1 -0
- package/dist/chunk-EZNCCO4L.js +14 -0
- package/dist/chunk-EZNCCO4L.js.map +1 -0
- package/dist/chunk-F3KRX2V4.js +457 -0
- package/dist/chunk-F3KRX2V4.js.map +1 -0
- package/dist/chunk-FPTWVCPN.js +53 -0
- package/dist/chunk-FPTWVCPN.js.map +1 -0
- package/dist/chunk-GCNRXAKH.js +37 -0
- package/dist/chunk-GCNRXAKH.js.map +1 -0
- package/dist/chunk-GYURWCIQ.js +1985 -0
- package/dist/chunk-GYURWCIQ.js.map +1 -0
- package/dist/chunk-HZMY3TT4.js +244 -0
- package/dist/chunk-HZMY3TT4.js.map +1 -0
- package/dist/chunk-ID5QJYF5.js +50 -0
- package/dist/chunk-ID5QJYF5.js.map +1 -0
- package/dist/chunk-JAN34G6S.js +552 -0
- package/dist/chunk-JAN34G6S.js.map +1 -0
- package/dist/chunk-K3UNLQ7W.js +118 -0
- package/dist/chunk-K3UNLQ7W.js.map +1 -0
- package/dist/chunk-KDY5N6J4.js +82 -0
- package/dist/chunk-KDY5N6J4.js.map +1 -0
- package/dist/chunk-KOZUNIIE.js +413 -0
- package/dist/chunk-KOZUNIIE.js.map +1 -0
- package/dist/chunk-KS72RZHX.js +30 -0
- package/dist/chunk-KS72RZHX.js.map +1 -0
- package/dist/chunk-LD5SMIB3.js +32 -0
- package/dist/chunk-LD5SMIB3.js.map +1 -0
- package/dist/chunk-OHCPV2NT.js +86 -0
- package/dist/chunk-OHCPV2NT.js.map +1 -0
- package/dist/chunk-OYWFPIHF.js +115 -0
- package/dist/chunk-OYWFPIHF.js.map +1 -0
- package/dist/chunk-POZER3MQ.js +407 -0
- package/dist/chunk-POZER3MQ.js.map +1 -0
- package/dist/chunk-RTRVBEIB.js +56 -0
- package/dist/chunk-RTRVBEIB.js.map +1 -0
- package/dist/chunk-RTVRUNYR.js +29 -0
- package/dist/chunk-RTVRUNYR.js.map +1 -0
- package/dist/chunk-SS7ELMJ7.js +406 -0
- package/dist/chunk-SS7ELMJ7.js.map +1 -0
- package/dist/chunk-STCCNLPC.js +160 -0
- package/dist/chunk-STCCNLPC.js.map +1 -0
- package/dist/chunk-SVLNF434.js +261 -0
- package/dist/chunk-SVLNF434.js.map +1 -0
- package/dist/chunk-UYFOLI2X.js +24 -0
- package/dist/chunk-UYFOLI2X.js.map +1 -0
- package/dist/chunk-VAN4WW3F.js +67 -0
- package/dist/chunk-VAN4WW3F.js.map +1 -0
- package/dist/chunk-WOMHL23C.js +369 -0
- package/dist/chunk-WOMHL23C.js.map +1 -0
- package/dist/chunk-WWVD5DR5.js +120 -0
- package/dist/chunk-WWVD5DR5.js.map +1 -0
- package/dist/chunk-XG2YMCJW.js +201 -0
- package/dist/chunk-XG2YMCJW.js.map +1 -0
- package/dist/chunk-XIJNE67Y.js +210 -0
- package/dist/chunk-XIJNE67Y.js.map +1 -0
- package/dist/chunk-Y6UJOUE5.js +44 -0
- package/dist/chunk-Y6UJOUE5.js.map +1 -0
- package/dist/chunk-YUO6SKJD.js +348 -0
- package/dist/chunk-YUO6SKJD.js.map +1 -0
- package/dist/components--hjBMTnz.d.ts +120 -0
- package/dist/components-B29WHGQN.d.ts +39 -0
- package/dist/components-BWG1GkZA.d.ts +20 -0
- package/dist/components-XCpL6IYt.d.ts +18 -0
- package/dist/components-qWwOsvwh.d.ts +43 -0
- package/dist/cooldown.d.ts +116 -0
- package/dist/cooldown.js +20 -0
- package/dist/cooldown.js.map +1 -0
- package/dist/coordinators/boundary-ricochet-3d.d.ts +19 -0
- package/dist/coordinators/boundary-ricochet-3d.js +8 -0
- package/dist/coordinators/boundary-ricochet-3d.js.map +1 -0
- package/dist/coordinators/boundary-ricochet.d.ts +34 -0
- package/dist/coordinators/boundary-ricochet.js +8 -0
- package/dist/coordinators/boundary-ricochet.js.map +1 -0
- package/dist/coordinators/first-person-shooter.d.ts +35 -0
- package/dist/coordinators/first-person-shooter.js +9 -0
- package/dist/coordinators/first-person-shooter.js.map +1 -0
- package/dist/coordinators/multidirectional-space-shooter.d.ts +27 -0
- package/dist/coordinators/multidirectional-space-shooter.js +10 -0
- package/dist/coordinators/multidirectional-space-shooter.js.map +1 -0
- package/dist/coordinators/top-down-shooter.d.ts +27 -0
- package/dist/coordinators/top-down-shooter.js +10 -0
- package/dist/coordinators/top-down-shooter.js.map +1 -0
- package/dist/core.d.ts +25 -0
- package/dist/core.js +327 -0
- package/dist/core.js.map +1 -0
- package/dist/destructible-3d.d.ts +42 -0
- package/dist/destructible-3d.js +13 -0
- package/dist/destructible-3d.js.map +1 -0
- package/dist/destructible-prebake.d.ts +28 -0
- package/dist/destructible-prebake.js +23 -0
- package/dist/destructible-prebake.js.map +1 -0
- package/dist/entity-types-CmtQ-IBp.d.ts +15 -0
- package/dist/first-person-perspective-C9Mptl0-.d.ts +23 -0
- package/dist/first-person.d.ts +204 -0
- package/dist/first-person.js +27 -0
- package/dist/first-person.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +263 -0
- package/dist/index.js.map +1 -0
- package/dist/jumper-2d.d.ts +113 -0
- package/dist/jumper-2d.js +27 -0
- package/dist/jumper-2d.js.map +1 -0
- package/dist/jumper-3d.d.ts +164 -0
- package/dist/jumper-3d.js +29 -0
- package/dist/jumper-3d.js.map +1 -0
- package/dist/moveable-BCRpjAQb.d.ts +176 -0
- package/dist/particle-emitter/presets.d.ts +46 -0
- package/dist/particle-emitter/presets.js +15 -0
- package/dist/particle-emitter/presets.js.map +1 -0
- package/dist/particle-emitter.d.ts +78 -0
- package/dist/particle-emitter.js +15 -0
- package/dist/particle-emitter.js.map +1 -0
- package/dist/payload-BQzu-oY_.d.ts +89 -0
- package/dist/platformer-3d.d.ts +347 -0
- package/dist/platformer-3d.js +23 -0
- package/dist/platformer-3d.js.map +1 -0
- package/dist/ricochet-2d.d.ts +274 -0
- package/dist/ricochet-2d.js +16 -0
- package/dist/ricochet-2d.js.map +1 -0
- package/dist/ricochet-3d.d.ts +116 -0
- package/dist/ricochet-3d.js +16 -0
- package/dist/ricochet-3d.js.map +1 -0
- package/dist/runtime-2d.d.ts +2 -0
- package/dist/runtime-2d.js +32 -0
- package/dist/runtime-2d.js.map +1 -0
- package/dist/runtime-pong.d.ts +92 -0
- package/dist/runtime-pong.js +38 -0
- package/dist/runtime-pong.js.map +1 -0
- package/dist/screen-visibility.d.ts +74 -0
- package/dist/screen-visibility.js +10 -0
- package/dist/screen-visibility.js.map +1 -0
- package/dist/screen-wrap.d.ts +86 -0
- package/dist/screen-wrap.js +16 -0
- package/dist/screen-wrap.js.map +1 -0
- package/dist/shooter-2d.d.ts +77 -0
- package/dist/shooter-2d.js +12 -0
- package/dist/shooter-2d.js.map +1 -0
- package/dist/spark-DDlIg1nM.d.ts +148 -0
- package/dist/sync-state-machine-CZyspBpj.d.ts +16 -0
- package/dist/thruster.d.ts +132 -0
- package/dist/thruster.js +26 -0
- package/dist/thruster.js.map +1 -0
- package/dist/top-down-movement.d.ts +40 -0
- package/dist/top-down-movement.js +20 -0
- package/dist/top-down-movement.js.map +1 -0
- package/dist/use-behavior-D_82jAL3.d.ts +13 -0
- package/dist/vector-Bm65-FOG.d.ts +45 -0
- package/dist/world-boundary-2d.d.ts +141 -0
- package/dist/world-boundary-2d.js +21 -0
- package/dist/world-boundary-2d.js.map +1 -0
- package/dist/world-boundary-3d.d.ts +75 -0
- package/dist/world-boundary-3d.js +21 -0
- package/dist/world-boundary-3d.js.map +1 -0
- package/package.json +161 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import { S as SyncStateMachine } from './sync-state-machine-CZyspBpj.js';
|
|
2
|
+
import { a as BehaviorDescriptor } from './behavior-system-DYbx-x_-.js';
|
|
3
|
+
import 'typescript-fsm';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Platformer 3D ECS Components
|
|
7
|
+
*
|
|
8
|
+
* Components for 3D platformer movement system including walking, running,
|
|
9
|
+
* jumping with multi-jump support, and falling/landing states.
|
|
10
|
+
*/
|
|
11
|
+
interface Platformer3DMovementComponent {
|
|
12
|
+
/** Base walking speed */
|
|
13
|
+
walkSpeed: number;
|
|
14
|
+
/** Sprint/run speed */
|
|
15
|
+
runSpeed: number;
|
|
16
|
+
/** Initial jump force/velocity */
|
|
17
|
+
jumpForce: number;
|
|
18
|
+
/** Maximum number of jumps (1 = single jump, 2 = double jump, etc.) */
|
|
19
|
+
maxJumps: number;
|
|
20
|
+
/** Gravity force (optional override) */
|
|
21
|
+
gravity: number;
|
|
22
|
+
/** Ray length for ground detection */
|
|
23
|
+
groundRayLength: number;
|
|
24
|
+
/** Coyote time in seconds (grace period after leaving ground) */
|
|
25
|
+
coyoteTime: number;
|
|
26
|
+
/** Jump buffer time in seconds (queue jump input before landing) */
|
|
27
|
+
jumpBufferTime: number;
|
|
28
|
+
/** Velocity multiplier when releasing jump button early (0-1) */
|
|
29
|
+
jumpCutMultiplier: number;
|
|
30
|
+
/** Time in seconds before multi-jump becomes available (0 = after button release) */
|
|
31
|
+
multiJumpWindowTime: number;
|
|
32
|
+
/** Enable ground-ray debug visualization */
|
|
33
|
+
debugGroundProbe: boolean;
|
|
34
|
+
}
|
|
35
|
+
declare function createPlatformer3DMovementComponent(options?: Partial<Platformer3DMovementComponent>): Platformer3DMovementComponent;
|
|
36
|
+
interface Platformer3DInputComponent {
|
|
37
|
+
/** Horizontal movement input (-1 to 1) */
|
|
38
|
+
moveX: number;
|
|
39
|
+
/** Forward/backward movement input (-1 to 1) */
|
|
40
|
+
moveZ: number;
|
|
41
|
+
/** Jump button pressed */
|
|
42
|
+
jump: boolean;
|
|
43
|
+
/** Run/sprint button held */
|
|
44
|
+
run: boolean;
|
|
45
|
+
}
|
|
46
|
+
declare function createPlatformer3DInputComponent(): Platformer3DInputComponent;
|
|
47
|
+
interface Platformer3DStateComponent {
|
|
48
|
+
/** Is the entity on the ground */
|
|
49
|
+
grounded: boolean;
|
|
50
|
+
/** Is currently in a jump arc */
|
|
51
|
+
jumping: boolean;
|
|
52
|
+
/** Is falling (not jumping) */
|
|
53
|
+
falling: boolean;
|
|
54
|
+
/** Current jump count (for multi-jump) */
|
|
55
|
+
jumpCount: number;
|
|
56
|
+
/** Y position when jump started */
|
|
57
|
+
jumpStartHeight: number;
|
|
58
|
+
/** Current movement speed being applied */
|
|
59
|
+
currentSpeed: number;
|
|
60
|
+
/** Last known ground Y position */
|
|
61
|
+
lastGroundedY: number;
|
|
62
|
+
/** Was jump button pressed last frame (for edge detection) */
|
|
63
|
+
jumpPressedLastFrame: boolean;
|
|
64
|
+
/** Is currently colliding with ground (from physics collision callback) */
|
|
65
|
+
collisionGrounded: boolean;
|
|
66
|
+
/** Timestamp of last ground collision */
|
|
67
|
+
groundedCollisionTime: number;
|
|
68
|
+
/** Time in seconds since last grounded */
|
|
69
|
+
timeSinceGrounded: number;
|
|
70
|
+
/** Is a jump allowed due to buffer? */
|
|
71
|
+
jumpBuffered: boolean;
|
|
72
|
+
/** Time remaining in jump buffer */
|
|
73
|
+
jumpBufferTimer: number;
|
|
74
|
+
/** Is jump button currently held */
|
|
75
|
+
jumpHeld: boolean;
|
|
76
|
+
/** Has the jump cut been applied for this jump? */
|
|
77
|
+
jumpCutApplied: boolean;
|
|
78
|
+
/** Has jump button been released since last jump (required for multi-jump) */
|
|
79
|
+
jumpReleasedSinceLastJump: boolean;
|
|
80
|
+
/** Time since current jump started (for multi-jump window) */
|
|
81
|
+
timeSinceJump: number;
|
|
82
|
+
/** True for the single frame on which a jump impulse was applied; prevents gravity from clobbering jump velocity. */
|
|
83
|
+
jumpedThisFrame: boolean;
|
|
84
|
+
/** Remaining seconds of jump-cut velocity ramp; while > 0, velocity.y lerps toward velocity.y * jumpCutMultiplier. */
|
|
85
|
+
jumpCutRampTimer: number;
|
|
86
|
+
/** Remaining seconds of grounded-hysteresis grace (keeps `grounded` true briefly after ground probe misses, to absorb edge/ray flicker). */
|
|
87
|
+
groundedGraceTimer: number;
|
|
88
|
+
}
|
|
89
|
+
declare function createPlatformer3DStateComponent(): Platformer3DStateComponent;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Platformer 3D Finite State Machine
|
|
93
|
+
*
|
|
94
|
+
* Manages state transitions for 3D platformer movement:
|
|
95
|
+
* - Idle: Standing still on ground
|
|
96
|
+
* - Walking: Moving on ground (slow)
|
|
97
|
+
* - Running: Moving on ground (fast)
|
|
98
|
+
* - Jumping: Ascending from jump
|
|
99
|
+
* - Falling: Descending (gravity)
|
|
100
|
+
* - Landing: Just touched ground
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Simplified Collision Context interface
|
|
105
|
+
*/
|
|
106
|
+
interface PlatformerCollisionContext {
|
|
107
|
+
contact: {
|
|
108
|
+
normal: {
|
|
109
|
+
x: number;
|
|
110
|
+
y: number;
|
|
111
|
+
z?: number;
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Platformer states
|
|
117
|
+
*/
|
|
118
|
+
declare enum Platformer3DState {
|
|
119
|
+
Idle = "idle",
|
|
120
|
+
Walking = "walking",
|
|
121
|
+
Running = "running",
|
|
122
|
+
Jumping = "jumping",
|
|
123
|
+
Falling = "falling",
|
|
124
|
+
Landing = "landing"
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Events that trigger state transitions
|
|
128
|
+
*/
|
|
129
|
+
declare enum Platformer3DEvent {
|
|
130
|
+
Walk = "walk",
|
|
131
|
+
Run = "run",
|
|
132
|
+
Jump = "jump",
|
|
133
|
+
Fall = "fall",
|
|
134
|
+
Land = "land",
|
|
135
|
+
Stop = "stop"
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Context for the FSM
|
|
139
|
+
*/
|
|
140
|
+
interface Platformer3DContext {
|
|
141
|
+
input: Platformer3DInputComponent;
|
|
142
|
+
state: Platformer3DStateComponent;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Platformer 3D FSM
|
|
146
|
+
*/
|
|
147
|
+
declare class Platformer3DFSM {
|
|
148
|
+
private ctx;
|
|
149
|
+
machine: SyncStateMachine<Platformer3DState, Platformer3DEvent, never>;
|
|
150
|
+
constructor(ctx: Platformer3DContext);
|
|
151
|
+
/**
|
|
152
|
+
* Get the current state
|
|
153
|
+
*/
|
|
154
|
+
getState(): Platformer3DState;
|
|
155
|
+
/**
|
|
156
|
+
* Dispatch an event to the FSM
|
|
157
|
+
*/
|
|
158
|
+
dispatch(event: Platformer3DEvent): void;
|
|
159
|
+
/**
|
|
160
|
+
* Check if grounded
|
|
161
|
+
*/
|
|
162
|
+
isGrounded(): boolean;
|
|
163
|
+
/**
|
|
164
|
+
* Get current jump count from context
|
|
165
|
+
*/
|
|
166
|
+
getJumpCount(): number;
|
|
167
|
+
/**
|
|
168
|
+
* Handle collision event to update ground state
|
|
169
|
+
*/
|
|
170
|
+
handleCollision(ctx: PlatformerCollisionContext): void;
|
|
171
|
+
/**
|
|
172
|
+
* Update FSM based on current state
|
|
173
|
+
*/
|
|
174
|
+
update(input: Platformer3DInputComponent, state: Platformer3DStateComponent): void;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Platformer 3D Behavior System
|
|
179
|
+
*
|
|
180
|
+
* Handles 3D platformer physics including:
|
|
181
|
+
* - Contact-based ground detection (uses the actual capsule collider — no
|
|
182
|
+
* raycast/shapecast probe). The bottom of the body's collider is the
|
|
183
|
+
* single source of truth for "is grounded".
|
|
184
|
+
* - Horizontal movement (walk/run)
|
|
185
|
+
* - Jumping with multi-jump support
|
|
186
|
+
* - Gravity application (Rapier's internal gravity is disabled per-body so
|
|
187
|
+
* `movement.gravity` is the only fall acceleration — previously the two
|
|
188
|
+
* stacked, doubling the airborne fall rate).
|
|
189
|
+
* - State synchronization with FSM
|
|
190
|
+
*/
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Entity with platformer components
|
|
194
|
+
*/
|
|
195
|
+
interface Platformer3DEntity {
|
|
196
|
+
uuid: string;
|
|
197
|
+
body: any;
|
|
198
|
+
platformer: Platformer3DMovementComponent;
|
|
199
|
+
$platformer: Platformer3DInputComponent;
|
|
200
|
+
platformerState: Platformer3DStateComponent;
|
|
201
|
+
transformStore?: any;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Platformer 3D Movement Behavior
|
|
205
|
+
*
|
|
206
|
+
* Core physics system for 3D platformer movement.
|
|
207
|
+
*
|
|
208
|
+
* Ground detection uses Rapier's narrow-phase contacts on the entity's
|
|
209
|
+
* collider (`world.contactsWith` + `contactPair`). This eliminates the old
|
|
210
|
+
* shape/ray probe and aligns "grounded" with the same surface the body
|
|
211
|
+
* physically rests on, which removes the jitter that happened on heightmap
|
|
212
|
+
* terrain (the probe and the contact resolver could disagree by a frame).
|
|
213
|
+
*/
|
|
214
|
+
declare class Platformer3DBehavior$1 {
|
|
215
|
+
private world;
|
|
216
|
+
private scene;
|
|
217
|
+
/**
|
|
218
|
+
* Tracks entities whose Rapier `gravityScale` has been zeroed so that
|
|
219
|
+
* `applyGravity` is the sole writer of vertical velocity. We do this
|
|
220
|
+
* lazily on the first update because the body isn't always available at
|
|
221
|
+
* construction time.
|
|
222
|
+
*/
|
|
223
|
+
private gravityConfiguredUUIDs;
|
|
224
|
+
constructor(world: any, scene: any);
|
|
225
|
+
/**
|
|
226
|
+
* Detect "grounded" using the actual capsule collider's contact pairs.
|
|
227
|
+
*
|
|
228
|
+
* A contact is treated as ground when its solver point lies below the
|
|
229
|
+
* body center (i.e., it sits on the bottom hemisphere/cylinder). We
|
|
230
|
+
* deliberately don't filter by normal direction: the contact point's
|
|
231
|
+
* position alone is robust against the various normal-flip conventions
|
|
232
|
+
* Rapier uses for `flipped` manifolds and against rolling-bottom edges
|
|
233
|
+
* on heightmap terrain.
|
|
234
|
+
*/
|
|
235
|
+
private detectGroundedFromContacts;
|
|
236
|
+
/**
|
|
237
|
+
* One-time per-entity physics setup: take over gravity from Rapier's
|
|
238
|
+
* world so that `applyGravity` controls the entire airborne fall curve.
|
|
239
|
+
* Without this, gravity was effectively doubled (Rapier's world gravity
|
|
240
|
+
* + this behavior's explicit gravity were both pulling the body down).
|
|
241
|
+
*/
|
|
242
|
+
private ensurePhysicsConfigured;
|
|
243
|
+
/**
|
|
244
|
+
* Apply horizontal movement based on input.
|
|
245
|
+
*
|
|
246
|
+
* Only writes X/Z axes — Y is left untouched so Rapier's contact resolution
|
|
247
|
+
* can damp vertical motion correctly while grounded. Jump and gravity are
|
|
248
|
+
* the sole writers of Y velocity (see handleJump / applyGravity).
|
|
249
|
+
*/
|
|
250
|
+
private applyMovement;
|
|
251
|
+
/**
|
|
252
|
+
* Handle jump logic with multi-jump, coyote time, buffering, and jump-cut ramp.
|
|
253
|
+
*/
|
|
254
|
+
private handleJump;
|
|
255
|
+
/**
|
|
256
|
+
* Apply gravity when not grounded.
|
|
257
|
+
*
|
|
258
|
+
* Skipped on the single frame immediately after a jump impulse is applied
|
|
259
|
+
* (tracked via `state.jumpedThisFrame`) so gravity never overwrites a
|
|
260
|
+
* just-applied jump velocity. The flag is cleared here regardless, so it
|
|
261
|
+
* only suppresses exactly one gravity step — independent of frame rate.
|
|
262
|
+
*/
|
|
263
|
+
private applyGravity;
|
|
264
|
+
/**
|
|
265
|
+
* Update entity state based on physics.
|
|
266
|
+
*
|
|
267
|
+
* Grounded is determined purely by Rapier's contact pairs on the entity's
|
|
268
|
+
* collider. This removes a whole class of slope/heightmap jitter caused
|
|
269
|
+
* by the previous shape probe disagreeing with the contact resolver — the
|
|
270
|
+
* probe could report grounded while a contact impulse had just nudged the
|
|
271
|
+
* body off the ground, producing visible micro-bouncing.
|
|
272
|
+
*
|
|
273
|
+
* While grounded, vertical velocity is held at 0 each frame. This stops
|
|
274
|
+
* residual upward kicks from slope-contact resolution from accumulating
|
|
275
|
+
* across frames (which previously caused the character to "ride up"
|
|
276
|
+
* slopes and lose contact briefly, then fall back, then re-contact, in a
|
|
277
|
+
* tight oscillation).
|
|
278
|
+
*/
|
|
279
|
+
private updateState;
|
|
280
|
+
/**
|
|
281
|
+
* Update one platformer entity. Invoked per linked entity by the
|
|
282
|
+
* Platformer3DBehaviorSystem adapter.
|
|
283
|
+
*/
|
|
284
|
+
updateEntity(entity: any, delta: number): void;
|
|
285
|
+
destroy(): void;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Platformer behavior options (typed for entity.use() autocomplete)
|
|
290
|
+
*/
|
|
291
|
+
interface Platformer3DBehaviorOptions {
|
|
292
|
+
/** Base walking speed (default: 12) */
|
|
293
|
+
walkSpeed?: number;
|
|
294
|
+
/** Sprint/run speed (default: 24) */
|
|
295
|
+
runSpeed?: number;
|
|
296
|
+
/** Initial jump force (default: 12) */
|
|
297
|
+
jumpForce?: number;
|
|
298
|
+
/** Maximum number of jumps (default: 1) */
|
|
299
|
+
maxJumps?: number;
|
|
300
|
+
/** Gravity force (default: 9.82) */
|
|
301
|
+
gravity?: number;
|
|
302
|
+
/** Ray length for ground detection (default: 1.0) */
|
|
303
|
+
groundRayLength?: number;
|
|
304
|
+
/** Enable debug visualization for ground probe rays (default: false) */
|
|
305
|
+
debugGroundProbe?: boolean;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Platformer3DBehavior - typed descriptor for 3D platformer movement
|
|
309
|
+
*
|
|
310
|
+
* Provides complete 3D platformer physics including:
|
|
311
|
+
* - Walking and running
|
|
312
|
+
* - Jumping with multi-jump support
|
|
313
|
+
* - Gravity and falling
|
|
314
|
+
* - Ground detection
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```typescript
|
|
318
|
+
* import { Platformer3DBehavior } from "@zylem/game-lib/behavior";
|
|
319
|
+
*
|
|
320
|
+
* const player = await playgroundActor('player');
|
|
321
|
+
* const platformer = player.use(Platformer3DBehavior, {
|
|
322
|
+
* walkSpeed: 12,
|
|
323
|
+
* runSpeed: 24,
|
|
324
|
+
* jumpForce: 12,
|
|
325
|
+
* maxJumps: 2, // Double jump!
|
|
326
|
+
* });
|
|
327
|
+
*
|
|
328
|
+
* // In update loop
|
|
329
|
+
* player.onUpdate(({ inputs }) => {
|
|
330
|
+
* player.$platformer.moveX = inputs.p1.axes.Horizontal.value;
|
|
331
|
+
* player.$platformer.moveZ = inputs.p1.axes.Vertical.value;
|
|
332
|
+
* player.$platformer.jump = inputs.p1.buttons.A.held > 0;
|
|
333
|
+
* player.$platformer.run = inputs.p1.shoulders.LTrigger.held > 0;
|
|
334
|
+
*
|
|
335
|
+
* const state = platformer.getState();
|
|
336
|
+
* const grounded = platformer.isGrounded();
|
|
337
|
+
* });
|
|
338
|
+
* ```
|
|
339
|
+
*/
|
|
340
|
+
declare const Platformer3DBehavior: BehaviorDescriptor<Platformer3DBehaviorOptions, {
|
|
341
|
+
getState: () => Platformer3DState;
|
|
342
|
+
isGrounded: () => boolean;
|
|
343
|
+
getJumpCount: () => number;
|
|
344
|
+
onPlatformCollision: (ctx: PlatformerCollisionContext) => void;
|
|
345
|
+
}, Platformer3DEntity>;
|
|
346
|
+
|
|
347
|
+
export { Platformer3DBehavior, type Platformer3DBehaviorOptions, type Platformer3DContext, type Platformer3DEntity, Platformer3DEvent, Platformer3DFSM, type Platformer3DInputComponent, Platformer3DBehavior$1 as Platformer3DMovementBehavior, type Platformer3DMovementComponent, Platformer3DState, type Platformer3DStateComponent, type PlatformerCollisionContext, createPlatformer3DInputComponent, createPlatformer3DMovementComponent, createPlatformer3DStateComponent };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Platformer3DBehavior,
|
|
3
|
+
Platformer3DBehavior2,
|
|
4
|
+
Platformer3DEvent,
|
|
5
|
+
Platformer3DFSM,
|
|
6
|
+
Platformer3DState,
|
|
7
|
+
createPlatformer3DInputComponent,
|
|
8
|
+
createPlatformer3DMovementComponent,
|
|
9
|
+
createPlatformer3DStateComponent
|
|
10
|
+
} from "./chunk-JAN34G6S.js";
|
|
11
|
+
import "./chunk-4URF65BR.js";
|
|
12
|
+
import "./chunk-EZNCCO4L.js";
|
|
13
|
+
export {
|
|
14
|
+
Platformer3DBehavior2 as Platformer3DBehavior,
|
|
15
|
+
Platformer3DEvent,
|
|
16
|
+
Platformer3DFSM,
|
|
17
|
+
Platformer3DBehavior as Platformer3DMovementBehavior,
|
|
18
|
+
Platformer3DState,
|
|
19
|
+
createPlatformer3DInputComponent,
|
|
20
|
+
createPlatformer3DMovementComponent,
|
|
21
|
+
createPlatformer3DStateComponent
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=platformer-3d.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { B as BaseEntityInterface } from './entity-types-CmtQ-IBp.js';
|
|
2
|
+
import { S as SyncStateMachine } from './sync-state-machine-CZyspBpj.js';
|
|
3
|
+
import { a as BehaviorDescriptor } from './behavior-system-DYbx-x_-.js';
|
|
4
|
+
import 'three';
|
|
5
|
+
import '@dimforge/rapier3d-compat';
|
|
6
|
+
import 'typescript-fsm';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Ricochet2DFSM
|
|
10
|
+
*
|
|
11
|
+
* FSM + extended state to track ricochet events and results.
|
|
12
|
+
* The FSM state tracks whether a ricochet is currently occurring.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
interface Ricochet2DResult {
|
|
16
|
+
/** The reflected velocity vector */
|
|
17
|
+
velocity: {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
z?: number;
|
|
21
|
+
};
|
|
22
|
+
/** The resulting speed after reflection */
|
|
23
|
+
speed: number;
|
|
24
|
+
/** The collision normal used for reflection */
|
|
25
|
+
normal: {
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
z?: number;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
interface Ricochet2DCollisionContext {
|
|
32
|
+
entity?: BaseEntityInterface;
|
|
33
|
+
otherEntity?: BaseEntityInterface;
|
|
34
|
+
/** Current velocity of the entity (optional if entity is provided) */
|
|
35
|
+
selfVelocity?: {
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
z?: number;
|
|
39
|
+
};
|
|
40
|
+
/** Contact information from the collision */
|
|
41
|
+
contact: {
|
|
42
|
+
/** The collision normal */
|
|
43
|
+
normal?: {
|
|
44
|
+
x: number;
|
|
45
|
+
y: number;
|
|
46
|
+
z?: number;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Optional position where the collision occurred.
|
|
50
|
+
* If provided, used for precise offset calculation.
|
|
51
|
+
*/
|
|
52
|
+
position?: {
|
|
53
|
+
x: number;
|
|
54
|
+
y: number;
|
|
55
|
+
z?: number;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Optional position of the entity that owns this behavior.
|
|
60
|
+
* Used with contact.position for offset calculations.
|
|
61
|
+
*/
|
|
62
|
+
selfPosition?: {
|
|
63
|
+
x: number;
|
|
64
|
+
y: number;
|
|
65
|
+
z?: number;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Optional position of the other entity in the collision.
|
|
69
|
+
* Used for paddle-style deflection: offset = (contactY - otherY) / halfHeight.
|
|
70
|
+
*/
|
|
71
|
+
otherPosition?: {
|
|
72
|
+
x: number;
|
|
73
|
+
y: number;
|
|
74
|
+
z?: number;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Optional size of the other entity (e.g., paddle size).
|
|
78
|
+
* If provided, used to normalize the offset based on the collision face.
|
|
79
|
+
*/
|
|
80
|
+
otherSize?: {
|
|
81
|
+
x: number;
|
|
82
|
+
y: number;
|
|
83
|
+
z?: number;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
declare enum Ricochet2DState {
|
|
87
|
+
Idle = "idle",
|
|
88
|
+
Ricocheting = "ricocheting"
|
|
89
|
+
}
|
|
90
|
+
declare enum Ricochet2DEvent {
|
|
91
|
+
StartRicochet = "start-ricochet",
|
|
92
|
+
EndRicochet = "end-ricochet"
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Callback type for ricochet event listeners.
|
|
96
|
+
*/
|
|
97
|
+
type RicochetCallback = (result: Ricochet2DResult) => void;
|
|
98
|
+
/**
|
|
99
|
+
* FSM wrapper with extended state (lastResult).
|
|
100
|
+
* Systems or consumers call `computeRicochet(...)` when a collision occurs.
|
|
101
|
+
*/
|
|
102
|
+
declare class Ricochet2DFSM {
|
|
103
|
+
readonly machine: SyncStateMachine<Ricochet2DState, Ricochet2DEvent, never>;
|
|
104
|
+
private lastResult;
|
|
105
|
+
private lastUpdatedAtMs;
|
|
106
|
+
private currentTimeMs;
|
|
107
|
+
private listeners;
|
|
108
|
+
constructor();
|
|
109
|
+
/**
|
|
110
|
+
* Add a listener for ricochet events.
|
|
111
|
+
* @returns Unsubscribe function
|
|
112
|
+
*/
|
|
113
|
+
addListener(callback: RicochetCallback): () => void;
|
|
114
|
+
/**
|
|
115
|
+
* Emit result to all listeners.
|
|
116
|
+
*/
|
|
117
|
+
private emitToListeners;
|
|
118
|
+
getState(): Ricochet2DState;
|
|
119
|
+
/**
|
|
120
|
+
* Returns the last computed ricochet result, or null if none.
|
|
121
|
+
*/
|
|
122
|
+
getLastResult(): Ricochet2DResult | null;
|
|
123
|
+
/**
|
|
124
|
+
* Best-effort timestamp (ms) of the last computation.
|
|
125
|
+
*/
|
|
126
|
+
getLastUpdatedAtMs(): number | null;
|
|
127
|
+
/**
|
|
128
|
+
* Set current game time (called by system each frame).
|
|
129
|
+
* Used for cooldown calculations.
|
|
130
|
+
*/
|
|
131
|
+
setCurrentTimeMs(timeMs: number): void;
|
|
132
|
+
/**
|
|
133
|
+
* Check if ricochet is on cooldown (to prevent rapid duplicate applications).
|
|
134
|
+
* @param cooldownMs Cooldown duration in milliseconds (default: 50ms)
|
|
135
|
+
*/
|
|
136
|
+
isOnCooldown(cooldownMs?: number): boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Reset cooldown state (e.g., on entity respawn).
|
|
139
|
+
*/
|
|
140
|
+
resetCooldown(): void;
|
|
141
|
+
/**
|
|
142
|
+
* Compute a ricochet result from collision context.
|
|
143
|
+
* Returns the result for the consumer to apply, or null if invalid input.
|
|
144
|
+
*/
|
|
145
|
+
computeRicochet(ctx: Ricochet2DCollisionContext, options?: {
|
|
146
|
+
minSpeed?: number;
|
|
147
|
+
maxSpeed?: number;
|
|
148
|
+
speedMultiplier?: number;
|
|
149
|
+
reflectionMode?: 'simple' | 'angled';
|
|
150
|
+
maxAngleDeg?: number;
|
|
151
|
+
}): Ricochet2DResult | null;
|
|
152
|
+
/**
|
|
153
|
+
* Extract velocity, position, and size data from entities or context.
|
|
154
|
+
*/
|
|
155
|
+
private extractDataFromEntities;
|
|
156
|
+
/**
|
|
157
|
+
* Compute collision normal from entity positions using AABB heuristic.
|
|
158
|
+
*/
|
|
159
|
+
private computeNormalFromPositions;
|
|
160
|
+
/**
|
|
161
|
+
* Compute basic reflection using the formula: v' = v - 2(v·n)n
|
|
162
|
+
*/
|
|
163
|
+
private computeBasicReflection;
|
|
164
|
+
/**
|
|
165
|
+
* Compute angled deflection for paddle-style reflections.
|
|
166
|
+
*/
|
|
167
|
+
private computeAngledDeflection;
|
|
168
|
+
/**
|
|
169
|
+
* Compute hit offset for angled deflection (-1 to 1).
|
|
170
|
+
*/
|
|
171
|
+
private computeHitOffset;
|
|
172
|
+
/**
|
|
173
|
+
* Apply speed constraints to the reflected velocity.
|
|
174
|
+
*/
|
|
175
|
+
private applySpeedClamp;
|
|
176
|
+
/**
|
|
177
|
+
* Clear the ricochet state (call after consumer has applied the result).
|
|
178
|
+
*/
|
|
179
|
+
clearRicochet(): void;
|
|
180
|
+
private dispatch;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
interface Ricochet2DOptions {
|
|
184
|
+
/**
|
|
185
|
+
* Minimum speed after reflection.
|
|
186
|
+
* Default: 2
|
|
187
|
+
*/
|
|
188
|
+
minSpeed: number;
|
|
189
|
+
/**
|
|
190
|
+
* Maximum speed after reflection.
|
|
191
|
+
* Default: 20
|
|
192
|
+
*/
|
|
193
|
+
maxSpeed: number;
|
|
194
|
+
/**
|
|
195
|
+
* Speed multiplier applied during angled reflection.
|
|
196
|
+
* Default: 1.05
|
|
197
|
+
*/
|
|
198
|
+
speedMultiplier: number;
|
|
199
|
+
/**
|
|
200
|
+
* Reflection mode:
|
|
201
|
+
* - 'simple': Basic axis inversion
|
|
202
|
+
* - 'angled': Paddle-style deflection based on contact point
|
|
203
|
+
* Default: 'angled'
|
|
204
|
+
*/
|
|
205
|
+
reflectionMode: 'simple' | 'angled';
|
|
206
|
+
/**
|
|
207
|
+
* Maximum deflection angle in degrees for angled mode.
|
|
208
|
+
* Default: 60
|
|
209
|
+
*/
|
|
210
|
+
maxAngleDeg: number;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Handle methods provided by Ricochet2DBehavior
|
|
214
|
+
*/
|
|
215
|
+
interface Ricochet2DHandle {
|
|
216
|
+
/**
|
|
217
|
+
* Compute a ricochet/reflection result from collision context.
|
|
218
|
+
* Returns the result for the consumer to apply, or null if invalid input.
|
|
219
|
+
*
|
|
220
|
+
* @param ctx - Collision context with selfVelocity and contact normal
|
|
221
|
+
* @returns Ricochet result with velocity, speed, and normal, or null
|
|
222
|
+
*/
|
|
223
|
+
getRicochet(ctx: Ricochet2DCollisionContext): Ricochet2DResult | null;
|
|
224
|
+
/**
|
|
225
|
+
* Compute ricochet and apply velocity directly via transformStore.
|
|
226
|
+
* Emits to onRicochet listeners if successful.
|
|
227
|
+
*
|
|
228
|
+
* @param ctx - Collision context with entity and contact normal
|
|
229
|
+
* @returns true if ricochet was computed and applied, false otherwise
|
|
230
|
+
*/
|
|
231
|
+
applyRicochet(ctx: Ricochet2DCollisionContext): boolean;
|
|
232
|
+
/**
|
|
233
|
+
* Get the last computed ricochet result, or null if none.
|
|
234
|
+
*/
|
|
235
|
+
getLastResult(): Ricochet2DResult | null;
|
|
236
|
+
/**
|
|
237
|
+
* Register a listener for ricochet events.
|
|
238
|
+
* Called whenever a ricochet is computed (from getRicochet or applyRicochet).
|
|
239
|
+
*
|
|
240
|
+
* @param callback - Function to call with ricochet result
|
|
241
|
+
* @returns Unsubscribe function
|
|
242
|
+
*/
|
|
243
|
+
onRicochet(callback: RicochetCallback): () => void;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Ricochet2DBehavior
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```ts
|
|
250
|
+
* import { Ricochet2DBehavior } from "@zylem/game-lib/behavior";
|
|
251
|
+
*
|
|
252
|
+
* const ball = createSphere({ ... });
|
|
253
|
+
* const ricochet = ball.use(Ricochet2DBehavior, {
|
|
254
|
+
* minSpeed: 3,
|
|
255
|
+
* maxSpeed: 15,
|
|
256
|
+
* reflectionMode: 'angled',
|
|
257
|
+
* });
|
|
258
|
+
*
|
|
259
|
+
* ball.onCollision(({ entity, other }) => {
|
|
260
|
+
* const velocity = entity.body.linvel();
|
|
261
|
+
* const result = ricochet.getRicochet({
|
|
262
|
+
* selfVelocity: velocity,
|
|
263
|
+
* contact: { normal: { x: 1, y: 0 } }, // from collision data
|
|
264
|
+
* });
|
|
265
|
+
*
|
|
266
|
+
* if (result) {
|
|
267
|
+
* entity.body.setLinvel(result.velocity, true);
|
|
268
|
+
* }
|
|
269
|
+
* });
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
declare const Ricochet2DBehavior: BehaviorDescriptor<Ricochet2DOptions, Ricochet2DHandle, unknown>;
|
|
273
|
+
|
|
274
|
+
export { Ricochet2DBehavior, type Ricochet2DCollisionContext, Ricochet2DEvent, Ricochet2DFSM, type Ricochet2DHandle, type Ricochet2DOptions, type Ricochet2DResult, Ricochet2DState, type RicochetCallback };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Ricochet2DBehavior,
|
|
3
|
+
Ricochet2DEvent,
|
|
4
|
+
Ricochet2DFSM,
|
|
5
|
+
Ricochet2DState
|
|
6
|
+
} from "./chunk-KOZUNIIE.js";
|
|
7
|
+
import "./chunk-Y6UJOUE5.js";
|
|
8
|
+
import "./chunk-4URF65BR.js";
|
|
9
|
+
import "./chunk-EZNCCO4L.js";
|
|
10
|
+
export {
|
|
11
|
+
Ricochet2DBehavior,
|
|
12
|
+
Ricochet2DEvent,
|
|
13
|
+
Ricochet2DFSM,
|
|
14
|
+
Ricochet2DState
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=ricochet-2d.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|