@zylem/behaviors 0.5.2 → 0.5.7
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-CldqNUgr.d.ts → behavior-system-HEt67el5.d.ts} +14 -1
- package/dist/{chunk-EIWQM6U3.js → chunk-2HKY6WF7.js} +0 -1
- package/dist/{chunk-IZJFUAXB.js → chunk-2HLZBWGD.js} +0 -1
- package/dist/{chunk-LL4FLHIY.js → chunk-2YF7J3H4.js} +0 -1
- package/dist/{chunk-SGHIGTVZ.js → chunk-3X3CL24Z.js} +0 -1
- package/dist/{chunk-HZMY3TT4.js → chunk-4DVDFCVY.js} +0 -1
- package/dist/{chunk-QVCMJ4Q2.js → chunk-4EWASZHB.js} +0 -1
- package/dist/{chunk-4LLK2FJI.js → chunk-55CFXXZH.js} +3 -4
- package/dist/{chunk-4MZ57HPD.js → chunk-57GLKGEX.js} +3 -4
- package/dist/{chunk-QS3VXWVO.js → chunk-7GGR26YA.js} +3 -4
- package/dist/{chunk-Y4PHT2HG.js → chunk-7LHXAEOZ.js} +4 -5
- package/dist/{chunk-PLIXVF7B.js → chunk-7TIIRJKF.js} +3 -4
- package/dist/{chunk-LZIHSJZR.js → chunk-CB3C7CRD.js} +4 -5
- package/dist/{chunk-G2KUXVU6.js → chunk-CTSYM56P.js} +30 -12
- package/dist/{chunk-2PAHQZZD.js → chunk-CVRN7YAI.js} +3 -4
- package/dist/{chunk-NW4SE5XW.js → chunk-DD4U42FG.js} +2 -3
- package/dist/{chunk-BAXJ7XHJ.js → chunk-E2MOFIDH.js} +3 -4
- package/dist/{chunk-WOMHL23C.js → chunk-ERS6SNA5.js} +1 -2
- package/dist/{chunk-4WH2ZN7P.js → chunk-F7E23E26.js} +0 -1
- package/dist/{chunk-DZ4LLQON.js → chunk-GZ3DQIIZ.js} +23 -2
- package/dist/{chunk-5WRI5ZAA.js → chunk-JSBRDJBE.js} +0 -1
- package/dist/{chunk-5A5AYP2C.js → chunk-K6CWKFHL.js} +0 -1
- package/dist/{chunk-52FJIDGL.js → chunk-LAN7U3AK.js} +1 -2
- package/dist/{chunk-WU6XXL3D.js → chunk-LLDLVVG4.js} +4 -5
- package/dist/{chunk-M3QDKKDF.js → chunk-LWM346FW.js} +0 -1
- package/dist/{chunk-7DGXUAPV.js → chunk-M25QJBDN.js} +4 -5
- package/dist/{chunk-7JLWZXPA.js → chunk-NDJO56BB.js} +3 -4
- package/dist/{chunk-AS3HR7AS.js → chunk-OBF6BIA2.js} +1 -2
- package/dist/{chunk-KIYUUSPK.js → chunk-OSPQFWQF.js} +2 -3
- package/dist/{chunk-4CEW64HO.js → chunk-OU2SW4U5.js} +3 -4
- package/dist/{chunk-H4TJ7X4O.js → chunk-QU6GQ657.js} +2 -3
- package/dist/{chunk-KFFETUAL.js → chunk-RR3XNDKG.js} +2 -3
- package/dist/{chunk-JVADRLWX.js → chunk-SHZZ2QRV.js} +2 -3
- package/dist/{chunk-7W3KY55G.js → chunk-TK3AXXXI.js} +3 -4
- package/dist/{chunk-OPZ2LVS2.js → chunk-TZQQYJYK.js} +0 -1
- package/dist/{chunk-7JJEIADR.js → chunk-UF7QPYUX.js} +299 -157
- package/dist/{chunk-NQPYMUDF.js → chunk-UKGBQTHL.js} +3 -4
- package/dist/{chunk-5XPPLTC7.js → chunk-UUMH3DC3.js} +1 -2
- package/dist/{chunk-TBUKJKY6.js → chunk-VJ3UA6OD.js} +1 -2
- package/dist/{chunk-OHCPV2NT.js → chunk-WHKPWIQO.js} +0 -1
- package/dist/{chunk-EZNCCO4L.js → chunk-YDLO5M7S.js} +0 -1
- package/dist/{components-BmievOxF.d.ts → components-JZQoO2sU.d.ts} +1 -1
- package/dist/cooldown.d.ts +1 -1
- package/dist/cooldown.js +3 -4
- package/dist/coordinators/boundary-ricochet-3d.d.ts +2 -2
- package/dist/coordinators/boundary-ricochet-3d.js +4 -5
- package/dist/coordinators/boundary-ricochet.d.ts +2 -2
- package/dist/coordinators/boundary-ricochet.js +4 -5
- package/dist/coordinators/first-person-shooter.js +4 -5
- package/dist/coordinators/multidirectional-space-shooter.d.ts +1 -1
- package/dist/coordinators/multidirectional-space-shooter.js +6 -7
- package/dist/coordinators/top-down-shooter.d.ts +1 -1
- package/dist/coordinators/top-down-shooter.js +6 -7
- package/dist/core.d.ts +21 -6
- package/dist/core.js +29 -7
- package/dist/destructible-3d.d.ts +1 -1
- package/dist/destructible-3d.js +4 -5
- package/dist/destructible-prebake.js +2 -3
- package/dist/{first-person-perspective-C9Mptl0-.d.ts → first-person-perspective-BxFHgFln.d.ts} +2 -0
- package/dist/first-person.d.ts +12 -3
- package/dist/first-person.js +7 -8
- package/dist/index.d.ts +5 -5
- package/dist/index.js +40 -41
- package/dist/jumper-2d.d.ts +1 -1
- package/dist/jumper-2d.js +5 -6
- package/dist/jumper-3d.d.ts +1 -1
- package/dist/jumper-3d.js +6 -7
- package/dist/{moveable-rdIvWiak.d.ts → moveable-BdFmI3s1.d.ts} +1 -1
- package/dist/particle-emitter/presets.d.ts +1 -1
- package/dist/particle-emitter/presets.js +2 -3
- package/dist/particle-emitter.d.ts +3 -3
- package/dist/particle-emitter.js +5 -6
- package/dist/platformer-2d.d.ts +1 -1
- package/dist/platformer-2d.js +5 -6
- package/dist/platformer-3d.d.ts +1 -1
- package/dist/platformer-3d.js +5 -6
- package/dist/ricochet-2d.d.ts +1 -1
- package/dist/ricochet-2d.js +5 -6
- package/dist/ricochet-3d.d.ts +1 -1
- package/dist/ricochet-3d.js +5 -6
- package/dist/runtime-2d.d.ts +1 -1
- package/dist/runtime-2d.js +2 -3
- package/dist/screen-visibility.d.ts +1 -1
- package/dist/screen-visibility.js +3 -4
- package/dist/screen-wrap.d.ts +1 -1
- package/dist/screen-wrap.js +5 -6
- package/dist/shooter-2d.d.ts +1 -1
- package/dist/shooter-2d.js +5 -6
- package/dist/{spark-Dx3cJbTW.d.ts → spark-C4Tp-52_.d.ts} +4 -2
- package/dist/thruster.d.ts +1 -1
- package/dist/thruster.js +5 -6
- package/dist/top-down-movement.d.ts +1 -1
- package/dist/top-down-movement.js +7 -8
- package/dist/world-boundary-2d.d.ts +1 -1
- package/dist/world-boundary-2d.js +6 -7
- package/dist/world-boundary-3d.d.ts +1 -1
- package/dist/world-boundary-3d.js +6 -7
- package/package.json +159 -161
- package/dist/chunk-2PAHQZZD.js.map +0 -1
- package/dist/chunk-4CEW64HO.js.map +0 -1
- package/dist/chunk-4LLK2FJI.js.map +0 -1
- package/dist/chunk-4MZ57HPD.js.map +0 -1
- package/dist/chunk-4WH2ZN7P.js.map +0 -1
- package/dist/chunk-52FJIDGL.js.map +0 -1
- package/dist/chunk-5A5AYP2C.js.map +0 -1
- package/dist/chunk-5WRI5ZAA.js.map +0 -1
- package/dist/chunk-5XPPLTC7.js.map +0 -1
- package/dist/chunk-7DGXUAPV.js.map +0 -1
- package/dist/chunk-7JJEIADR.js.map +0 -1
- package/dist/chunk-7JLWZXPA.js.map +0 -1
- package/dist/chunk-7W3KY55G.js.map +0 -1
- package/dist/chunk-AS3HR7AS.js.map +0 -1
- package/dist/chunk-BAXJ7XHJ.js.map +0 -1
- package/dist/chunk-DZ4LLQON.js.map +0 -1
- package/dist/chunk-EIWQM6U3.js.map +0 -1
- package/dist/chunk-EZNCCO4L.js.map +0 -1
- package/dist/chunk-G2KUXVU6.js.map +0 -1
- package/dist/chunk-H4TJ7X4O.js.map +0 -1
- package/dist/chunk-HZMY3TT4.js.map +0 -1
- package/dist/chunk-IZJFUAXB.js.map +0 -1
- package/dist/chunk-JVADRLWX.js.map +0 -1
- package/dist/chunk-KFFETUAL.js.map +0 -1
- package/dist/chunk-KIYUUSPK.js.map +0 -1
- package/dist/chunk-LL4FLHIY.js.map +0 -1
- package/dist/chunk-LZIHSJZR.js.map +0 -1
- package/dist/chunk-M3QDKKDF.js.map +0 -1
- package/dist/chunk-NQPYMUDF.js.map +0 -1
- package/dist/chunk-NW4SE5XW.js.map +0 -1
- package/dist/chunk-OHCPV2NT.js.map +0 -1
- package/dist/chunk-OPZ2LVS2.js.map +0 -1
- package/dist/chunk-PLIXVF7B.js.map +0 -1
- package/dist/chunk-QS3VXWVO.js.map +0 -1
- package/dist/chunk-QVCMJ4Q2.js.map +0 -1
- package/dist/chunk-SGHIGTVZ.js.map +0 -1
- package/dist/chunk-TBUKJKY6.js.map +0 -1
- package/dist/chunk-WOMHL23C.js.map +0 -1
- package/dist/chunk-WU6XXL3D.js.map +0 -1
- package/dist/chunk-Y4PHT2HG.js.map +0 -1
- package/dist/cooldown.js.map +0 -1
- package/dist/coordinators/boundary-ricochet-3d.js.map +0 -1
- package/dist/coordinators/boundary-ricochet.js.map +0 -1
- package/dist/coordinators/first-person-shooter.js.map +0 -1
- package/dist/coordinators/multidirectional-space-shooter.js.map +0 -1
- package/dist/coordinators/top-down-shooter.js.map +0 -1
- package/dist/core.js.map +0 -1
- package/dist/destructible-3d.js.map +0 -1
- package/dist/destructible-prebake.js.map +0 -1
- package/dist/first-person.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/jumper-2d.js.map +0 -1
- package/dist/jumper-3d.js.map +0 -1
- package/dist/particle-emitter/presets.js.map +0 -1
- package/dist/particle-emitter.js.map +0 -1
- package/dist/platformer-2d.js.map +0 -1
- package/dist/platformer-3d.js.map +0 -1
- package/dist/ricochet-2d.js.map +0 -1
- package/dist/ricochet-3d.js.map +0 -1
- package/dist/runtime-2d.js.map +0 -1
- package/dist/screen-visibility.js.map +0 -1
- package/dist/screen-wrap.js.map +0 -1
- package/dist/shooter-2d.js.map +0 -1
- package/dist/thruster.js.map +0 -1
- package/dist/top-down-movement.js.map +0 -1
- package/dist/world-boundary-2d.js.map +0 -1
- package/dist/world-boundary-3d.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/behaviors/platformer-2d/components.ts","../src/lib/behaviors/platformer-2d/platformer-2d-fsm.ts","../src/lib/behaviors/platformer-2d/platformer-2d.descriptor.ts"],"sourcesContent":["/**\n * Platformer 2D Components\n *\n * Components for 2D platformer movement on the X/Y plane: walking/running on\n * X, jumping with multi-jump support, and falling/landing states.\n */\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Platformer2DMovementComponent (capability / configuration)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface Platformer2DMovementComponent {\n\t/** Base walking speed */\n\twalkSpeed: number;\n\t/** Sprint/run speed */\n\trunSpeed: number;\n\t/** Initial jump force/velocity */\n\tjumpForce: number;\n\t/** Maximum number of jumps (1 = single jump, 2 = double jump, etc.) */\n\tmaxJumps: number;\n\t/** Gravity force */\n\tgravity: number;\n\t/** Coyote time in seconds (grace period after leaving ground) */\n\tcoyoteTime: number;\n\t/** Jump buffer time in seconds (queue jump input before landing) */\n\tjumpBufferTime: number;\n\t/** Velocity multiplier when releasing jump button early (0-1) */\n\tjumpCutMultiplier: number;\n\t/** Time in seconds before multi-jump becomes available (0 = after button release) */\n\tmultiJumpWindowTime: number;\n\t/** Maximum slope angle (degrees) the character can walk up */\n\tslopeClimbAngle: number;\n\t/** Slope angle (degrees) past which the character slides down */\n\tslopeSlideAngle: number;\n\t/** Autostep configuration for SNES-style step-ups, or false to disable */\n\tautostep: { maxHeight: number; minWidth: number } | false;\n\t/** Snap-to-ground distance (keeps the character glued going downhill) */\n\tsnapToGroundDistance: number;\n\t/** Character controller offset (small gap kept between collider and environment) */\n\tcharacterOffset: number;\n}\n\nexport function createPlatformer2DMovementComponent(\n\toptions: Partial<Platformer2DMovementComponent> = {},\n): Platformer2DMovementComponent {\n\treturn {\n\t\twalkSpeed: options.walkSpeed ?? 8,\n\t\trunSpeed: options.runSpeed ?? 14,\n\t\tjumpForce: options.jumpForce ?? 12,\n\t\tmaxJumps: options.maxJumps ?? 1,\n\t\tgravity: options.gravity ?? 20,\n\t\tcoyoteTime: options.coyoteTime ?? 0.1,\n\t\tjumpBufferTime: options.jumpBufferTime ?? 0.1,\n\t\tjumpCutMultiplier: options.jumpCutMultiplier ?? 0.5,\n\t\tmultiJumpWindowTime: options.multiJumpWindowTime ?? 0.15,\n\t\tslopeClimbAngle: options.slopeClimbAngle ?? 50,\n\t\tslopeSlideAngle: options.slopeSlideAngle ?? 40,\n\t\tautostep: options.autostep ?? { maxHeight: 0.25, minWidth: 0.05 },\n\t\tsnapToGroundDistance: options.snapToGroundDistance ?? 0.2,\n\t\tcharacterOffset: options.characterOffset ?? 0.05,\n\t};\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Platformer2DInputComponent (intent)\n// Written by: Player controller, AI controller\n// Read by: Platformer2DBehavior\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface Platformer2DInputComponent {\n\t/** Horizontal movement input (-1 to 1) */\n\tmoveX: number;\n\t/** Jump button pressed */\n\tjump: boolean;\n\t/** Run/sprint button held */\n\trun: boolean;\n}\n\nexport function createPlatformer2DInputComponent(): Platformer2DInputComponent {\n\treturn {\n\t\tmoveX: 0,\n\t\tjump: false,\n\t\trun: false,\n\t};\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Platformer2DStateComponent (runtime state)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface Platformer2DStateComponent {\n\t/** Is the entity on the ground */\n\tgrounded: boolean;\n\t/** Is currently in a jump arc */\n\tjumping: boolean;\n\t/** Is falling (not jumping) */\n\tfalling: boolean;\n\t/** Current jump count (for multi-jump) */\n\tjumpCount: number;\n\t/** Y position when jump started */\n\tjumpStartHeight: number;\n\t/** Current movement speed being applied */\n\tcurrentSpeed: number;\n\t/** Last known ground Y position */\n\tlastGroundedY: number;\n\t/** Was jump button pressed last frame (for edge detection) */\n\tjumpPressedLastFrame: boolean;\n\t/** Time in seconds since last grounded */\n\ttimeSinceGrounded: number;\n\t/** Is a jump allowed due to buffer? */\n\tjumpBuffered: boolean;\n\t/** Time remaining in jump buffer */\n\tjumpBufferTimer: number;\n\t/** Is jump button currently held */\n\tjumpHeld: boolean;\n\t/** Has the jump cut been applied for this jump? */\n\tjumpCutApplied: boolean;\n\t/** Has jump button been released since last jump (required for multi-jump) */\n\tjumpReleasedSinceLastJump: boolean;\n\t/** Time since current jump started (for multi-jump window) */\n\ttimeSinceJump: number;\n\t/** True for the single frame on which a jump impulse was applied; prevents gravity from clobbering jump velocity. */\n\tjumpedThisFrame: boolean;\n\t/** Remaining seconds of jump-cut velocity ramp; while > 0, verticalVelocity lerps toward verticalVelocity * jumpCutMultiplier. */\n\tjumpCutRampTimer: number;\n\t/**\n\t * Controller-owned vertical velocity (units/second).\n\t * The body is kinematic, so `linvel()` is meaningless — this field is the\n\t * single source of truth for jump/gravity motion on the Y axis.\n\t */\n\tverticalVelocity: number;\n}\n\nexport function createPlatformer2DStateComponent(): Platformer2DStateComponent {\n\treturn {\n\t\tgrounded: false,\n\t\tjumping: false,\n\t\tfalling: false,\n\t\tjumpCount: 0,\n\t\tjumpStartHeight: 0,\n\t\tcurrentSpeed: 0,\n\t\tlastGroundedY: 0,\n\t\tjumpPressedLastFrame: false,\n\t\ttimeSinceGrounded: 0,\n\t\tjumpBuffered: false,\n\t\tjumpBufferTimer: 0,\n\t\tjumpHeld: false,\n\t\tjumpCutApplied: false,\n\t\tjumpReleasedSinceLastJump: true,\n\t\ttimeSinceJump: 0,\n\t\tjumpedThisFrame: false,\n\t\tjumpCutRampTimer: 0,\n\t\tverticalVelocity: 0,\n\t};\n}\n","/**\n * Platformer 2D Finite State Machine\n *\n * Manages state transitions for 2D platformer movement:\n * - Idle: Standing still on ground\n * - Walking: Moving on ground (slow)\n * - Running: Moving on ground (fast)\n * - Jumping: Ascending from jump\n * - Falling: Descending (gravity)\n * - Landing: Just touched ground\n */\n\nimport { SyncStateMachine, t } from '../../core/utility/sync-state-machine';\nimport type { Platformer2DInputComponent, Platformer2DStateComponent } from './components';\n\n/**\n * Simplified collision context (normal in the X/Y plane).\n */\nexport interface Platformer2DCollisionContext {\n\tcontact: {\n\t\tnormal: { x: number; y: number };\n\t};\n}\n\nexport enum Platformer2DState {\n\tIdle = 'idle',\n\tWalking = 'walking',\n\tRunning = 'running',\n\tJumping = 'jumping',\n\tFalling = 'falling',\n\tLanding = 'landing',\n}\n\nexport enum Platformer2DEvent {\n\tWalk = 'walk',\n\tRun = 'run',\n\tJump = 'jump',\n\tFall = 'fall',\n\tLand = 'land',\n\tStop = 'stop',\n}\n\nexport interface Platformer2DContext {\n\tinput: Platformer2DInputComponent;\n\tstate: Platformer2DStateComponent;\n}\n\nexport class Platformer2DFSM {\n\tmachine: SyncStateMachine<Platformer2DState, Platformer2DEvent, never>;\n\n\tconstructor(private ctx: Platformer2DContext) {\n\t\tthis.machine = new SyncStateMachine<Platformer2DState, Platformer2DEvent, never>(\n\t\t\tPlatformer2DState.Idle,\n\t\t\t[\n\t\t\t\t// Idle transitions\n\t\t\t\tt(Platformer2DState.Idle, Platformer2DEvent.Walk, Platformer2DState.Walking),\n\t\t\t\tt(Platformer2DState.Idle, Platformer2DEvent.Run, Platformer2DState.Running),\n\t\t\t\tt(Platformer2DState.Idle, Platformer2DEvent.Jump, Platformer2DState.Jumping),\n\t\t\t\tt(Platformer2DState.Idle, Platformer2DEvent.Fall, Platformer2DState.Falling),\n\n\t\t\t\t// Walking transitions\n\t\t\t\tt(Platformer2DState.Walking, Platformer2DEvent.Run, Platformer2DState.Running),\n\t\t\t\tt(Platformer2DState.Walking, Platformer2DEvent.Jump, Platformer2DState.Jumping),\n\t\t\t\tt(Platformer2DState.Walking, Platformer2DEvent.Stop, Platformer2DState.Idle),\n\t\t\t\tt(Platformer2DState.Walking, Platformer2DEvent.Fall, Platformer2DState.Falling),\n\n\t\t\t\t// Running transitions\n\t\t\t\tt(Platformer2DState.Running, Platformer2DEvent.Walk, Platformer2DState.Walking),\n\t\t\t\tt(Platformer2DState.Running, Platformer2DEvent.Jump, Platformer2DState.Jumping),\n\t\t\t\tt(Platformer2DState.Running, Platformer2DEvent.Stop, Platformer2DState.Idle),\n\t\t\t\tt(Platformer2DState.Running, Platformer2DEvent.Fall, Platformer2DState.Falling),\n\n\t\t\t\t// Jumping transitions\n\t\t\t\tt(Platformer2DState.Jumping, Platformer2DEvent.Fall, Platformer2DState.Falling),\n\t\t\t\tt(Platformer2DState.Jumping, Platformer2DEvent.Land, Platformer2DState.Landing),\n\t\t\t\tt(Platformer2DState.Jumping, Platformer2DEvent.Jump, Platformer2DState.Jumping), // Multi-jump\n\n\t\t\t\t// Falling transitions\n\t\t\t\tt(Platformer2DState.Falling, Platformer2DEvent.Land, Platformer2DState.Landing),\n\t\t\t\tt(Platformer2DState.Falling, Platformer2DEvent.Jump, Platformer2DState.Jumping), // Air jump\n\n\t\t\t\t// Landing transitions\n\t\t\t\tt(Platformer2DState.Landing, Platformer2DEvent.Walk, Platformer2DState.Walking),\n\t\t\t\tt(Platformer2DState.Landing, Platformer2DEvent.Run, Platformer2DState.Running),\n\t\t\t\tt(Platformer2DState.Landing, Platformer2DEvent.Stop, Platformer2DState.Idle),\n\n\t\t\t\t// Self-transitions (no-ops)\n\t\t\t\tt(Platformer2DState.Idle, Platformer2DEvent.Stop, Platformer2DState.Idle),\n\t\t\t],\n\t\t);\n\t}\n\n\tgetState(): Platformer2DState {\n\t\treturn this.machine.getState();\n\t}\n\n\tdispatch(event: Platformer2DEvent): void {\n\t\tif (this.machine.can(event)) {\n\t\t\tthis.machine.syncDispatch(event);\n\t\t}\n\t}\n\n\tisGrounded(): boolean {\n\t\tconst state = this.getState();\n\t\treturn (\n\t\t\tstate === Platformer2DState.Idle ||\n\t\t\tstate === Platformer2DState.Walking ||\n\t\t\tstate === Platformer2DState.Running ||\n\t\t\tstate === Platformer2DState.Landing\n\t\t);\n\t}\n\n\tgetJumpCount(): number {\n\t\treturn this.ctx.state.jumpCount;\n\t}\n\n\t/**\n\t * Update FSM based on current component state.\n\t */\n\tupdate(input: Platformer2DInputComponent, state: Platformer2DStateComponent): void {\n\t\tthis.ctx.input = input;\n\t\tthis.ctx.state = state;\n\n\t\tconst currentState = this.getState();\n\t\tconst hasInput = Math.abs(input.moveX) > 0.1;\n\t\tconst isRunning = input.run;\n\n\t\t// Handle landing: if we're in falling state and now grounded, land\n\t\tif (currentState === Platformer2DState.Falling && state.grounded) {\n\t\t\tthis.dispatch(Platformer2DEvent.Land);\n\t\t\t// Don't return - allow immediate transition to movement state\n\t\t}\n\n\t\tif (state.grounded) {\n\t\t\tif (hasInput) {\n\t\t\t\tif (isRunning) {\n\t\t\t\t\tthis.dispatch(Platformer2DEvent.Run);\n\t\t\t\t} else {\n\t\t\t\t\tthis.dispatch(Platformer2DEvent.Walk);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.dispatch(Platformer2DEvent.Stop);\n\t\t\t}\n\t\t} else if (state.falling) {\n\t\t\tthis.dispatch(Platformer2DEvent.Fall);\n\t\t}\n\n\t\t// Handle jump input (edge detection handled in the system)\n\t\tif (input.jump && !state.jumpPressedLastFrame) {\n\t\t\tthis.dispatch(Platformer2DEvent.Jump);\n\t\t}\n\t}\n}\n","/**\n * Platformer 2D Behavior Descriptor\n *\n * Type-safe descriptor for the platformer 2D behavior system.\n * Provides entity.use() API for 2D platformer movement on the X/Y plane.\n */\n\nimport { defineBehavior } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport { Platformer2DState } from './platformer-2d-fsm';\nimport {\n\tcreatePlatformer2DMovementComponent,\n\tcreatePlatformer2DInputComponent,\n\tcreatePlatformer2DStateComponent,\n\ttype Platformer2DMovementComponent,\n\ttype Platformer2DInputComponent,\n\ttype Platformer2DStateComponent,\n} from './components';\nimport {\n\tSTAGE_INPUT_BUTTON_JUMP,\n\tSTAGE_INPUT_BUTTON_RUN,\n\treadBehaviorSnapshot,\n\tStagePlatformerShapeSource,\n\ttype BehaviorRuntime,\n\ttype StagePlatformer2DOptions,\n} from '../../runtime/wasm-stage-runtime';\n\n/** Rust FSM index → TS state (shared `platformer_3d/fsm.rs` ordering). */\nconst FSM_STATE_BY_INDEX: readonly Platformer2DState[] = [\n\tPlatformer2DState.Idle,\n\tPlatformer2DState.Walking,\n\tPlatformer2DState.Running,\n\tPlatformer2DState.Jumping,\n\tPlatformer2DState.Falling,\n\tPlatformer2DState.Landing,\n];\n\n/**\n * Platformer 2D behavior options (typed for entity.use() autocomplete)\n */\nexport interface Platformer2DBehaviorOptions {\n\t/** Base walking speed (default: 8) */\n\twalkSpeed?: number;\n\t/** Sprint/run speed (default: 14) */\n\trunSpeed?: number;\n\t/** Initial jump force (default: 12) */\n\tjumpForce?: number;\n\t/** Maximum number of jumps (default: 1) */\n\tmaxJumps?: number;\n\t/** Gravity force (default: 20) */\n\tgravity?: number;\n\t/** Coyote time in seconds (default: 0.1) */\n\tcoyoteTime?: number;\n\t/** Jump buffer time in seconds (default: 0.1) */\n\tjumpBufferTime?: number;\n\t/** Velocity multiplier when releasing jump early (default: 0.5) */\n\tjumpCutMultiplier?: number;\n\t/** Maximum slope angle in degrees the character can walk up (default: 50) */\n\tslopeClimbAngle?: number;\n\t/** Slope angle in degrees past which the character slides (default: 40) */\n\tslopeSlideAngle?: number;\n\t/** Autostep over small step-ups, or false to disable (default: { maxHeight: 0.25, minWidth: 0.05 }) */\n\tautostep?: { maxHeight: number; minWidth: number } | false;\n\t/** Snap-to-ground distance for downhill/step-down stability (default: 0.2) */\n\tsnapToGroundDistance?: number;\n\t/** Character controller collision offset (default: 0.05) */\n\tcharacterOffset?: number;\n\t/** Explicit KCC capsule override (requires `useAttachedCollider: false`). */\n\tshape?: {\n\t\thalfHeight: number;\n\t\tradius: number;\n\t\toffset?: [number, number, number];\n\t};\n\t/** When true (default), KCC reads shape + offset from the attached Rapier collider. */\n\tuseAttachedCollider?: boolean;\n}\n\nconst defaultOptions: Platformer2DBehaviorOptions = {\n\twalkSpeed: 8,\n\trunSpeed: 14,\n\tjumpForce: 12,\n\tmaxJumps: 1,\n\tgravity: 20,\n\tcoyoteTime: 0.1,\n\tjumpBufferTime: 0.1,\n\tjumpCutMultiplier: 0.5,\n\tslopeClimbAngle: 50,\n\tslopeSlideAngle: 40,\n\tautostep: { maxHeight: 0.25, minWidth: 0.05 },\n\tsnapToGroundDistance: 0.2,\n\tcharacterOffset: 0.05,\n};\n\nconst PLATFORMER_2D_BEHAVIOR_KEY = Symbol.for('zylem:behavior:platformer-2d');\n\nfunction resolvePlatformer2DAttachShape(\n\toptions: Platformer2DBehaviorOptions,\n\tgameEntity?: {\n\t\tcolliderDesc?: {\n\t\t\tshape?: { type?: string; halfHeight?: number; radius?: number };\n\t\t\toffset?: [number, number, number];\n\t\t};\n\t},\n): Pick<StagePlatformer2DOptions, 'halfHeight' | 'radius' | 'offsetX' | 'offsetY' | 'offsetZ' | 'shapeSource'> {\n\tconst fallback = {\n\t\thalfHeight: 0.9,\n\t\tradius: 0.4,\n\t\toffsetX: 0,\n\t\toffsetY: 0,\n\t\toffsetZ: 0,\n\t\tshapeSource: StagePlatformerShapeSource.Auto,\n\t};\n\n\tif (options.useAttachedCollider === false && options.shape) {\n\t\tconst offset = options.shape.offset ?? [0, 0, 0];\n\t\treturn {\n\t\t\thalfHeight: options.shape.halfHeight,\n\t\t\tradius: options.shape.radius,\n\t\t\toffsetX: offset[0],\n\t\t\toffsetY: offset[1],\n\t\t\toffsetZ: offset[2],\n\t\t\tshapeSource: StagePlatformerShapeSource.Override,\n\t\t};\n\t}\n\n\tconst collider = gameEntity?.colliderDesc;\n\tif (collider?.shape?.type === 'capsule') {\n\t\tconst offset = collider.offset ?? [0, 0, 0];\n\t\treturn {\n\t\t\thalfHeight: collider.shape.halfHeight ?? fallback.halfHeight,\n\t\t\tradius: collider.shape.radius ?? fallback.radius,\n\t\t\toffsetX: offset[0],\n\t\t\toffsetY: offset[1],\n\t\t\toffsetZ: offset[2],\n\t\t\tshapeSource: StagePlatformerShapeSource.Auto,\n\t\t};\n\t}\n\n\treturn fallback;\n}\n\n/**\n * Entity with 2D platformer components (input written by the game; the wasm\n * runtime owns the kinematic character controller and FSM).\n */\nexport interface Platformer2DEntity {\n\tuuid: string;\n\tplatformer2D: Platformer2DMovementComponent;\n\t$platformer2D: Platformer2DInputComponent;\n\tplatformer2DState: Platformer2DStateComponent;\n}\n\n/**\n * Forwards 2D platformer input into the wasm runtime. Entities with a\n * `runtimeHandle` are attached once to the Stage runtime and receive input\n * via the slot-indexed input buffer each frame; the Rust `platformer_2d` system\n * is the single simulation path.\n */\nclass Platformer2DBehaviorSystem implements BehaviorSystem {\n\tprivate attachedRuntimeSlots = new Set<number>();\n\n\tconstructor(\n\t\tprivate wasmStage: BehaviorRuntime | null,\n\t\tprivate getBehaviorLinks?: (key: symbol) => Iterable<BehaviorEntityLink>,\n\t) {}\n\n\tupdate(_ecs: unknown, _delta: number): void {\n\t\tconst links = this.getBehaviorLinks?.(PLATFORMER_2D_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 platformerRef = link.ref as any;\n\n\t\t\tconst options = platformerRef.options as Platformer2DBehaviorOptions;\n\n\t\t\tif (!gameEntity.platformer2D) {\n\t\t\t\tgameEntity.platformer2D = createPlatformer2DMovementComponent(options);\n\t\t\t}\n\t\t\tif (!gameEntity.$platformer2D) {\n\t\t\t\tgameEntity.$platformer2D = createPlatformer2DInputComponent();\n\t\t\t}\n\t\t\tif (!gameEntity.platformer2DState) {\n\t\t\t\tgameEntity.platformer2DState = createPlatformer2DStateComponent();\n\t\t\t}\n\n\t\t\tconst handle = (gameEntity.runtimeHandle ?? -1) as number;\n\t\t\tif (!this.wasmStage || handle < 0) continue;\n\n\t\t\tthis.ensureWasmAttached(handle, options, gameEntity);\n\t\t\tplatformerRef.__wasmStage = this.wasmStage;\n\t\t\tplatformerRef.__entity = gameEntity;\n\t\t\tconst input = gameEntity.$platformer2D;\n\t\t\tif (input) {\n\t\t\t\tthis.wasmStage.writeInputAxes(handle, input.moveX ?? 0, 0);\n\t\t\t\tthis.wasmStage.writeInputButton(handle, STAGE_INPUT_BUTTON_JUMP, !!input.jump);\n\t\t\t\tthis.wasmStage.writeInputButton(handle, STAGE_INPUT_BUTTON_RUN, !!input.run);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate ensureWasmAttached(\n\t\thandle: number,\n\t\toptions: Platformer2DBehaviorOptions,\n\t\tgameEntity?: { colliderDesc?: { shape?: { type?: string; halfHeight?: number; radius?: number }; offset?: [number, number, number] } },\n\t): void {\n\t\tif (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;\n\t\tconst autostep = options.autostep ?? defaultOptions.autostep!;\n\t\tconst shape = resolvePlatformer2DAttachShape(options, gameEntity);\n\t\tthis.wasmStage.attachPlatformer2D(handle, {\n\t\t\t...shape,\n\t\t\twalkSpeed: options.walkSpeed ?? defaultOptions.walkSpeed!,\n\t\t\trunSpeed: options.runSpeed ?? defaultOptions.runSpeed!,\n\t\t\tjumpForce: options.jumpForce ?? defaultOptions.jumpForce!,\n\t\t\tmaxJumps: options.maxJumps ?? defaultOptions.maxJumps!,\n\t\t\tgravity: options.gravity ?? defaultOptions.gravity!,\n\t\t\tcoyoteTime: options.coyoteTime ?? defaultOptions.coyoteTime!,\n\t\t\tjumpBufferTime: options.jumpBufferTime ?? defaultOptions.jumpBufferTime!,\n\t\t\tjumpCutMultiplier: options.jumpCutMultiplier ?? defaultOptions.jumpCutMultiplier!,\n\t\t\tslopeClimbAngle: options.slopeClimbAngle ?? defaultOptions.slopeClimbAngle!,\n\t\t\tslopeSlideAngle: options.slopeSlideAngle ?? defaultOptions.slopeSlideAngle!,\n\t\t\tautostepHeight: autostep ? autostep.maxHeight : 0,\n\t\t\tautostepMinWidth: autostep ? autostep.minWidth : 0.05,\n\t\t\tsnapToGroundDistance: options.snapToGroundDistance ?? defaultOptions.snapToGroundDistance!,\n\t\t\tcharacterOffset: options.characterOffset ?? defaultOptions.characterOffset!,\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 * Platformer2DBehavior - typed descriptor for 2D platformer movement\n *\n * Provides complete 2D platformer physics on the X/Y plane including:\n * - Walking and running on X\n * - Jumping with buffer, coyote time, multi-jump, and jump-cut\n * - Gravity ownership and falling\n * - Kinematic character controller (collide-and-slide, autostep, snap-to-ground)\n *\n * @example\n * ```typescript\n * import { Platformer2DBehavior } from \"@zylem/behaviors/platformer-2d\";\n *\n * const platformer = player.use(Platformer2DBehavior, {\n * walkSpeed: 8,\n * runSpeed: 14,\n * jumpForce: 12,\n * maxJumps: 2, // Double jump!\n * });\n *\n * // In update loop\n * player.onUpdate(({ inputs }) => {\n * player.$platformer2D.moveX = inputs.p1.axes.Horizontal.value;\n * player.$platformer2D.jump = inputs.p1.buttons.A.held > 0;\n * player.$platformer2D.run = inputs.p1.shoulders.LTrigger.held > 0;\n *\n * const state = platformer.getState();\n * const grounded = platformer.isGrounded();\n * });\n * ```\n */\nexport const Platformer2DBehavior = defineBehavior<\n\tPlatformer2DBehaviorOptions,\n\t{\n\t\tgetState: () => Platformer2DState;\n\t\tisGrounded: () => boolean;\n\t\tgetJumpCount: () => number;\n\t},\n\tPlatformer2DEntity\n>({\n\tname: 'platformer-2d',\n\tdefaultOptions,\n\tsystemFactory: (ctx) =>\n\t\tnew Platformer2DBehaviorSystem(\n\t\t\tctx.wasmStage ?? null,\n\t\t\tctx.getBehaviorLinks,\n\t\t),\n\t// Handles read the runtime snapshot buffer (values are from the end of\n\t// the previous step — one-frame lag). The Rust FSM is the single source\n\t// of truth.\n\tcreateHandle: (ref) => ({\n\t\tgetState: () => {\n\t\t\tconst snapshot = readBehaviorSnapshot(ref);\n\t\t\tif (snapshot) return FSM_STATE_BY_INDEX[snapshot.fsmState] ?? Platformer2DState.Idle;\n\t\t\treturn Platformer2DState.Idle;\n\t\t},\n\t\tisGrounded: () => readBehaviorSnapshot(ref)?.grounded ?? false,\n\t\tgetJumpCount: () => readBehaviorSnapshot(ref)?.jumpCount ?? 0,\n\t}),\n});\n"],"mappings":"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","names":["Platformer2DState","Platformer2DEvent"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/behaviors/jumper-3d/components.ts"],"sourcesContent":["/**\n * Jumper 3D ECS Components\n *\n * Type definitions and factory functions for the 3D jump behavior system.\n *\n * - JumpConfig3D: tunable parameters (stored as the capability component)\n * - JumpInput3D: per-tick intent written by the player/AI controller\n * - JumpContext3D: per-tick snapshot provided by the system adapter\n * - JumpState3D: internal runtime state owned by the behavior\n */\n\nimport type { Vector3 } from 'three';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Vec3-like interface for cross-library compatibility\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface Vec3Like {\n\tx: number;\n\ty: number;\n\tz: number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// JumpConfig3D (capability / configuration)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface JumpConfig3D {\n\t/** Desired peak height in world units */\n\tjumpHeight: number;\n\t/** Gravity magnitude (positive, e.g. 20) */\n\tgravity: number;\n\t/** Terminal fall speed magnitude (optional) */\n\tmaxFallSpeed?: number;\n\n\t/** 1 = single jump, 2 = double, etc. */\n\tmaxJumps: number;\n\t/** Reset jump counter when grounded (usually true) */\n\tresetJumpsOnGround: boolean;\n\t/** Reset jump counter on wall contact (future wall-jump support) */\n\tresetJumpsOnWall?: boolean;\n\n\t/** Grace period after leaving ground where first jump is still allowed (ms) */\n\tcoyoteTimeMs: number;\n\t/** Queue a jump press this many ms before landing (ms) */\n\tjumpBufferMs: number;\n\t/** Optional cooldown between consecutive jumps (ms) */\n\tminTimeBetweenJumpsMs?: number;\n\n\t/** Variable jump height via early release */\n\tvariableJump?: {\n\t\tenabled: boolean;\n\t\t/** Gravity multiplier applied when jump is released early while ascending */\n\t\tcutGravityMultiplier: number;\n\t\t/** Max hold duration before the cut triggers automatically (ms, optional) */\n\t\tmaxHoldMs?: number;\n\t};\n\n\t/** Optional planar (XZ) launch / air-control overrides */\n\tplanar?: {\n\t\t/** One-time planar speed applied at takeoff */\n\t\tlaunchPlanarSpeed?: number;\n\t\t/** If true, preserve current planar speed instead of replacing it */\n\t\tpreservePlanarSpeed?: boolean;\n\t\tairControl?: {\n\t\t\tmaxPlanarSpeed: number;\n\t\t\t/** Acceleration per second while airborne */\n\t\t\tacceleration: number;\n\t\t\t/** Deceleration per second when no input */\n\t\t\tdeceleration: number;\n\t\t};\n\t};\n\n\t/** Snappier descent tuning */\n\tfall?: {\n\t\t/** Gravity multiplier while falling (e.g. 1.5-2.5) */\n\t\tfallGravityMultiplier: number;\n\t\t/** Additional multiplier when fast-fall input is held */\n\t\tfastFallMultiplier?: number;\n\t};\n}\n\nexport function createJumpConfig3D(\n\toptions: Partial<JumpConfig3D> = {},\n): JumpConfig3D {\n\treturn {\n\t\tjumpHeight: options.jumpHeight ?? 2.5,\n\t\tgravity: options.gravity ?? 20,\n\t\tmaxFallSpeed: options.maxFallSpeed,\n\t\tmaxJumps: options.maxJumps ?? 1,\n\t\tresetJumpsOnGround: options.resetJumpsOnGround ?? true,\n\t\tresetJumpsOnWall: options.resetJumpsOnWall,\n\t\tcoyoteTimeMs: options.coyoteTimeMs ?? 100,\n\t\tjumpBufferMs: options.jumpBufferMs ?? 80,\n\t\tminTimeBetweenJumpsMs: options.minTimeBetweenJumpsMs,\n\t\tvariableJump: options.variableJump,\n\t\tplanar: options.planar,\n\t\tfall: options.fall,\n\t};\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// JumpInput3D (intent)\n// Written by: Player controller, AI controller\n// Read by: Jumper3DSystem\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface JumpInput3D {\n\t/** True on the frame the jump button is first pressed (rising edge) */\n\tjumpPressed: boolean;\n\t/** True while the jump button is held down */\n\tjumpHeld: boolean;\n\t/** True on the frame the jump button is released (falling edge) */\n\tjumpReleased: boolean;\n\t/** Desired planar direction in world space (camera-relative), optional */\n\tmoveDirWorld?: Vec3Like;\n\t/** Hold to drop faster (e.g. crouch / down input) */\n\tfastFall?: boolean;\n}\n\nexport function createJumpInput3D(): JumpInput3D {\n\treturn {\n\t\tjumpPressed: false,\n\t\tjumpHeld: false,\n\t\tjumpReleased: false,\n\t\tmoveDirWorld: undefined,\n\t\tfastFall: false,\n\t};\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// JumpContext3D (per-tick snapshot from entity / controller)\n// Built by the system adapter — never written to by user code.\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface JumpContext3D {\n\t/** Frame delta in seconds */\n\tdt: number;\n\t/** World up direction (usually 0,1,0) */\n\tup: Vec3Like;\n\t/** Current vertical (Y) velocity of the entity */\n\tvelocityY: number;\n\t/** Current horizontal velocity of the entity (read from body) */\n\thorizontalVelocity: { x: number; z: number };\n\t/** Whether the entity is on the ground */\n\tisGrounded: boolean;\n\t/** Surface normal at ground contact (optional) */\n\tgroundNormal?: Vec3Like;\n\t/** Time since entity was last grounded (ms) */\n\ttimeSinceGroundedMs: number;\n\n\t/** Set only the vertical (Y) component of velocity */\n\tsetVerticalVelocity(y: number): void;\n\t/** Set only the horizontal (X/Z) components of velocity */\n\tsetHorizontalVelocity(x: number, z: number): void;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// JumpState3D (internal runtime state)\n// Owned and mutated exclusively by Jumper3DSystem.tick()\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface JumpState3D {\n\t/** Number of jumps consumed since last reset */\n\tjumpsUsed: number;\n\t/** Timestamp (ms) of the most recent jump execution */\n\tlastJumpTimeMs: number;\n\t/** Remaining ms in the jump-buffer window (counts down) */\n\tbufferedJumpMs: number;\n\t/** Remaining ms in the coyote-time window (counts down) */\n\tcoyoteMs: number;\n\t/** True while the entity is in a jump arc (ascending phase) */\n\tisJumping: boolean;\n\t/** Elapsed ms since jump button was first held (for variable jump) */\n\tjumpHoldMs: number;\n\t/** Whether the variable-jump cut has already been applied this jump */\n\tjumpCutApplied: boolean;\n}\n\nexport function createJumpState3D(): JumpState3D {\n\treturn {\n\t\tjumpsUsed: 0,\n\t\tlastJumpTimeMs: 0,\n\t\tbufferedJumpMs: 0,\n\t\tcoyoteMs: 0,\n\t\tisJumping: false,\n\t\tjumpHoldMs: 0,\n\t\tjumpCutApplied: false,\n\t};\n}\n"],"mappings":";AAkFO,SAAS,mBACf,UAAiC,CAAC,GACnB;AACf,SAAO;AAAA,IACN,YAAY,QAAQ,cAAc;AAAA,IAClC,SAAS,QAAQ,WAAW;AAAA,IAC5B,cAAc,QAAQ;AAAA,IACtB,UAAU,QAAQ,YAAY;AAAA,IAC9B,oBAAoB,QAAQ,sBAAsB;AAAA,IAClD,kBAAkB,QAAQ;AAAA,IAC1B,cAAc,QAAQ,gBAAgB;AAAA,IACtC,cAAc,QAAQ,gBAAgB;AAAA,IACtC,uBAAuB,QAAQ;AAAA,IAC/B,cAAc,QAAQ;AAAA,IACtB,QAAQ,QAAQ;AAAA,IAChB,MAAM,QAAQ;AAAA,EACf;AACD;AAqBO,SAAS,oBAAiC;AAChD,SAAO;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,cAAc;AAAA,IACd,cAAc;AAAA,IACd,UAAU;AAAA,EACX;AACD;AAmDO,SAAS,oBAAiC;AAChD,SAAO;AAAA,IACN,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,UAAU;AAAA,IACV,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,gBAAgB;AAAA,EACjB;AACD;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/coordinators/shared/shooter-fire.ts"],"sourcesContent":["import type {\n\tShooter2DHandle,\n\tShooter2DSourceEntity,\n\tShooter2DStageLike,\n} from '../../behaviors/shooter-2d/shooter-2d.descriptor';\nimport {\n\tgetEntityFacingAngle2D,\n\tresolveAim2D,\n\ttype ResolvedAim2D,\n} from './top-down-aim';\n\n/**\n * Aim + fire input fields shared by the 2D shooter coordinators\n * (top-down-shooter, multidirectional-space-shooter).\n */\nexport interface Shooter2DAimFireInput {\n\taimX: number;\n\taimY: number;\n\tshootPressed: boolean;\n\tshootHeld: boolean;\n}\n\n/**\n * Fire the entity's Shooter2D behavior when the input requests it.\n *\n * Resolves the 2D aim (explicit aim axes, falling back to the entity's\n * current facing) and fires toward a point one unit along the aim direction.\n * Pass a pre-resolved `aim` to avoid recomputing when the coordinator already\n * resolved it for rotation.\n *\n * @returns true when a fire attempt was issued\n */\nexport function fireShooter2DIfRequested(\n\tentity: Shooter2DSourceEntity,\n\tshooter: Shooter2DHandle,\n\tstage: Shooter2DStageLike,\n\tinput: Shooter2DAimFireInput,\n\taim?: ResolvedAim2D,\n): boolean {\n\tif (!input.shootPressed && !input.shootHeld) {\n\t\treturn false;\n\t}\n\n\tconst sourcePosition = entity.body?.translation();\n\tif (!sourcePosition) {\n\t\treturn false;\n\t}\n\n\tconst resolved =\n\t\taim ?? resolveAim2D(input.aimX, input.aimY, getEntityFacingAngle2D(entity));\n\n\tvoid shooter.fire({\n\t\tsource: entity,\n\t\tstage,\n\t\ttarget: {\n\t\t\tx: sourcePosition.x + resolved.direction.x,\n\t\t\ty: sourcePosition.y + resolved.direction.y,\n\t\t},\n\t});\n\treturn true;\n}\n"],"mappings":";;;;;;AAgCO,SAAS,yBACf,QACA,SACA,OACA,OACA,KACU;AACV,MAAI,CAAC,MAAM,gBAAgB,CAAC,MAAM,WAAW;AAC5C,WAAO;AAAA,EACR;AAEA,QAAM,iBAAiB,OAAO,MAAM,YAAY;AAChD,MAAI,CAAC,gBAAgB;AACpB,WAAO;AAAA,EACR;AAEA,QAAM,WACL,OAAO,aAAa,MAAM,MAAM,MAAM,MAAM,uBAAuB,MAAM,CAAC;AAE3E,OAAK,QAAQ,KAAK;AAAA,IACjB,QAAQ;AAAA,IACR;AAAA,IACA,QAAQ;AAAA,MACP,GAAG,eAAe,IAAI,SAAS,UAAU;AAAA,MACzC,GAAG,eAAe,IAAI,SAAS,UAAU;AAAA,IAC1C;AAAA,EACD,CAAC;AACD,SAAO;AACR;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/behaviors/use-behavior.ts","../src/lib/behaviors/components.ts"],"sourcesContent":["import { GameEntity } from '../entities/entity';\nimport { BehaviorDescriptor } from './behavior-descriptor';\n\n/**\n * Type-safe helper to apply a behavior to an entity and return the entity cast to the behavior's interface.\n * \n * @param entity The entity to apply the behavior to\n * @param descriptor The behavior descriptor\n * @param options Behavior options\n * @returns The entity, cast to E & I (where I is the behavior's interface)\n */\nexport function useBehavior<\n E extends GameEntity<any>,\n O extends Record<string, any>,\n H extends Record<string, any>,\n I // Entity Interface\n>(\n entity: E,\n descriptor: BehaviorDescriptor<O, H, I>,\n options?: Partial<O>\n): E & I {\n entity.use(descriptor, options);\n return entity as unknown as E & I;\n}\n","/**\n * Core behavior helper types\n *\n * Plain data interfaces shared by movement behaviors and coordinators.\n */\n\nimport { Vector3, Quaternion } from 'three';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// TransformComponent (render-facing)\n// Written only by PhysicsSyncBehavior, read by rendering/animation\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface TransformComponent {\n\tposition: Vector3;\n\trotation: Quaternion;\n}\n\nexport function createTransformComponent(): TransformComponent {\n\treturn {\n\t\tposition: new Vector3(),\n\t\trotation: new Quaternion(),\n\t};\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// PhysicsBodyComponent (bridge to the host physics reference, not state)\n// ECS does not store velocity, mass, etc. — the wasm runtime owns all\n// physical truth; `body` is an opaque host-owned reference.\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface PhysicsBodyComponent {\n\tbody: unknown;\n}\n\nexport function createPhysicsBodyComponent(body: unknown): PhysicsBodyComponent {\n\treturn { body };\n}\n"],"mappings":";AAWO,SAAS,YAMZ,QACA,YACA,SACK;AACL,SAAO,IAAI,YAAY,OAAO;AAC9B,SAAO;AACX;;;ACjBA,SAAS,SAAS,kBAAkB;AAY7B,SAAS,2BAA+C;AAC9D,SAAO;AAAA,IACN,UAAU,IAAI,QAAQ;AAAA,IACtB,UAAU,IAAI,WAAW;AAAA,EAC1B;AACD;AAYO,SAAS,2BAA2B,MAAqC;AAC/E,SAAO,EAAE,KAAK;AACf;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/behaviors/cooldown/cooldown-store.ts","../src/lib/behaviors/cooldown/cooldown.descriptor.ts"],"sourcesContent":["import { proxy } from 'valtio/vanilla';\n\n/**\n * A single cooldown entry in the global store.\n */\nexport interface CooldownEntry {\n\t/** Identifier for this cooldown */\n\tname: string;\n\t/** Total cooldown time in seconds */\n\tduration: number;\n\t/** Time accumulated since last fire */\n\telapsed: number;\n\t/** Whether the cooldown is ready (elapsed >= duration) */\n\tready: boolean;\n\t/** Normalized progress 0..1 (0 = just fired, 1 = ready) */\n\tprogress: number;\n\t/** Whether this cooldown is currently counting down */\n\tactive: boolean;\n}\n\n/**\n * Global reactive cooldown registry (valtio proxy).\n * Accessible from entities, behaviors, and UI components.\n */\nconst cooldownStore = proxy<Record<string, CooldownEntry>>({});\n\n/**\n * Register a named cooldown in the global store.\n * If a cooldown with the same name already exists, it is overwritten.\n *\n * @param name Unique cooldown identifier\n * @param duration Cooldown duration in seconds\n * @param immediate If true, the cooldown starts ready (default: true)\n */\nexport function registerCooldown(\n\tname: string,\n\tduration: number,\n\timmediate: boolean = true,\n): void {\n\tcooldownStore[name] = {\n\t\tname,\n\t\tduration,\n\t\telapsed: immediate ? duration : 0,\n\t\tready: immediate,\n\t\tprogress: immediate ? 1 : 0,\n\t\tactive: !immediate,\n\t};\n}\n\n/**\n * Get a cooldown entry by name.\n * Returns undefined if the cooldown has not been registered.\n */\nexport function getCooldown(name: string): CooldownEntry | undefined {\n\treturn cooldownStore[name];\n}\n\n/**\n * Fire (trigger) a cooldown, resetting its timer.\n * Sets the cooldown to not-ready and starts the countdown.\n */\nexport function fireCooldown(name: string): void {\n\tconst entry = cooldownStore[name];\n\tif (!entry) return;\n\tentry.elapsed = 0;\n\tentry.ready = false;\n\tentry.progress = 0;\n\tentry.active = true;\n}\n\n/**\n * Force a cooldown to ready immediately.\n */\nexport function resetCooldown(name: string): void {\n\tconst entry = cooldownStore[name];\n\tif (!entry) return;\n\tentry.elapsed = entry.duration;\n\tentry.ready = true;\n\tentry.progress = 1;\n\tentry.active = false;\n}\n\n/**\n * Advance all active cooldowns by delta seconds.\n * Called once per frame by the CooldownBehavior system.\n */\nexport function tickCooldowns(delta: number): void {\n\tfor (const name in cooldownStore) {\n\t\tconst entry = cooldownStore[name];\n\t\tif (!entry.active) continue;\n\n\t\tentry.elapsed += delta;\n\t\tif (entry.elapsed >= entry.duration) {\n\t\t\tentry.elapsed = entry.duration;\n\t\t\tentry.ready = true;\n\t\t\tentry.progress = 1;\n\t\t\tentry.active = false;\n\t\t} else {\n\t\t\tentry.progress = entry.duration > 0 ? entry.elapsed / entry.duration : 1;\n\t\t}\n\t}\n}\n\n/**\n * Get the raw cooldown store (for advanced/debugging use).\n */\nexport function getCooldownStore(): Record<string, CooldownEntry> {\n\treturn cooldownStore;\n}\n","/**\n * CooldownBehavior\n *\n * A stage-scoped behavior that manages named cooldowns via the global CooldownStore.\n * Entities use this to register, check, and fire cooldowns.\n * UI components (CooldownIcon) can read from the same store.\n */\n\nimport { defineBehavior, type BehaviorRef } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport {\n\tregisterCooldown,\n\tgetCooldown,\n\tfireCooldown,\n\tresetCooldown,\n\ttickCooldowns,\n} from './cooldown-store';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Options\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface CooldownConfig {\n\t/** Duration in seconds */\n\tduration: number;\n\t/** Whether the cooldown starts ready (default: true) */\n\timmediate?: boolean;\n}\n\nexport interface CooldownOptions {\n\t/**\n\t * Named cooldowns to register.\n\t * Keys are the cooldown names, values are their config.\n\t */\n\tcooldowns: Record<string, CooldownConfig>;\n}\n\ninterface CompiledCooldownEntry {\n\tname: string;\n\tduration: number;\n\timmediate: boolean;\n}\n\nconst COOLDOWN_BEHAVIOR_KEY = Symbol.for('zylem:behavior:cooldown');\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Handle\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Handle methods returned by entity.use(CooldownBehavior, ...).\n */\nexport interface CooldownHandle {\n\t/** Check if a named cooldown is ready */\n\tisReady(name: string): boolean;\n\t/** Fire (trigger) a named cooldown, resetting its timer */\n\tfire(name: string): void;\n\t/** Force a cooldown to ready immediately */\n\treset(name: string): void;\n\t/** Get cooldown progress 0..1 (0 = just fired, 1 = ready) */\n\tgetProgress(name: string): number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// System\n// ─────────────────────────────────────────────────────────────────────────────\n\nclass CooldownSystem implements BehaviorSystem {\n\tconstructor(\n\t\tprivate getBehaviorLinks?: (key: symbol) => Iterable<BehaviorEntityLink>,\n\t) { }\n\n\tupdate(_ecs: unknown, delta: number): void {\n\t\tconst links = this.getBehaviorLinks?.(COOLDOWN_BEHAVIOR_KEY);\n\t\tif (links) {\n\t\t\tfor (const link of links) {\n\t\t\t\tensureCooldownEntriesRegistered(link.ref as BehaviorRef<CooldownOptions>);\n\t\t\t}\n\t\t}\n\n\t\ttickCooldowns(delta);\n\t}\n\n\tdestroy(_ecs: unknown): void { }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Handle factory\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction createCooldownHandle(ref: BehaviorRef<CooldownOptions>): CooldownHandle {\n\tensureCooldownEntriesRegistered(ref);\n\n\treturn {\n\t\tisReady: (name: string) => getCooldown(name)?.ready ?? false,\n\t\tfire: (name: string) => fireCooldown(name),\n\t\treset: (name: string) => resetCooldown(name),\n\t\tgetProgress: (name: string) => getCooldown(name)?.progress ?? 1,\n\t};\n}\n\nfunction getCompiledCooldownEntries(\n\tref: BehaviorRef<CooldownOptions>,\n): CompiledCooldownEntry[] {\n\tconst compiled = (ref as any).__compiledCooldownEntries as CompiledCooldownEntry[] | undefined;\n\tif (compiled) return compiled;\n\n\tconst entries = Object.entries(ref.options.cooldowns).map(([name, config]) => ({\n\t\tname,\n\t\tduration: config.duration,\n\t\timmediate: config.immediate ?? true,\n\t}));\n\t(ref as any).__compiledCooldownEntries = entries;\n\treturn entries;\n}\n\nfunction ensureCooldownEntriesRegistered(ref: BehaviorRef<CooldownOptions>): void {\n\tif ((ref as any).__cooldownsRegistered) return;\n\n\tfor (const entry of getCompiledCooldownEntries(ref)) {\n\t\tregisterCooldown(entry.name, entry.duration, entry.immediate);\n\t}\n\n\t(ref as any).__cooldownsRegistered = true;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Behavior Definition\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * CooldownBehavior\n *\n * @example\n * ```ts\n * import { CooldownBehavior } from '@zylem/game-lib/behavior';\n * import { moveBy } from '@zylem/game-lib/actions';\n *\n * const hero = createBox({ ... });\n * const cd = hero.use(CooldownBehavior, {\n * cooldowns: {\n * attack: { duration: 5 },\n * dash: { duration: 2, immediate: false },\n * },\n * });\n *\n * hero.onUpdate(({ me, inputs }) => {\n * if (cd.isReady('attack') && inputs.p1.buttons.A.pressed) {\n * cd.fire('attack');\n * // perform attack\n * }\n * if (cd.isReady('dash') && inputs.p1.buttons.B.pressed) {\n * cd.fire('dash');\n * me.runAction(moveBy({ x: 10, duration: 0.3 }));\n * }\n * });\n * ```\n */\nexport const CooldownBehavior = defineBehavior<CooldownOptions, CooldownHandle>({\n\tname: 'cooldown',\n\tdefaultOptions: { cooldowns: {} },\n\tsystemFactory: (ctx) =>\n\t\tnew CooldownSystem(ctx.getBehaviorLinks),\n\tcreateHandle: createCooldownHandle,\n});\n"],"mappings":";;;;;AAAA,SAAS,aAAa;AAwBtB,IAAM,gBAAgB,MAAqC,CAAC,CAAC;AAUtD,SAAS,iBACf,MACA,UACA,YAAqB,MACd;AACP,gBAAc,IAAI,IAAI;AAAA,IACrB;AAAA,IACA;AAAA,IACA,SAAS,YAAY,WAAW;AAAA,IAChC,OAAO;AAAA,IACP,UAAU,YAAY,IAAI;AAAA,IAC1B,QAAQ,CAAC;AAAA,EACV;AACD;AAMO,SAAS,YAAY,MAAyC;AACpE,SAAO,cAAc,IAAI;AAC1B;AAMO,SAAS,aAAa,MAAoB;AAChD,QAAM,QAAQ,cAAc,IAAI;AAChC,MAAI,CAAC,MAAO;AACZ,QAAM,UAAU;AAChB,QAAM,QAAQ;AACd,QAAM,WAAW;AACjB,QAAM,SAAS;AAChB;AAKO,SAAS,cAAc,MAAoB;AACjD,QAAM,QAAQ,cAAc,IAAI;AAChC,MAAI,CAAC,MAAO;AACZ,QAAM,UAAU,MAAM;AACtB,QAAM,QAAQ;AACd,QAAM,WAAW;AACjB,QAAM,SAAS;AAChB;AAMO,SAAS,cAAc,OAAqB;AAClD,aAAW,QAAQ,eAAe;AACjC,UAAM,QAAQ,cAAc,IAAI;AAChC,QAAI,CAAC,MAAM,OAAQ;AAEnB,UAAM,WAAW;AACjB,QAAI,MAAM,WAAW,MAAM,UAAU;AACpC,YAAM,UAAU,MAAM;AACtB,YAAM,QAAQ;AACd,YAAM,WAAW;AACjB,YAAM,SAAS;AAAA,IAChB,OAAO;AACN,YAAM,WAAW,MAAM,WAAW,IAAI,MAAM,UAAU,MAAM,WAAW;AAAA,IACxE;AAAA,EACD;AACD;AAKO,SAAS,mBAAkD;AACjE,SAAO;AACR;;;ACjEA,IAAM,wBAAwB,uBAAO,IAAI,yBAAyB;AAwBlE,IAAM,iBAAN,MAA+C;AAAA,EAC9C,YACS,kBACP;AADO;AAAA,EACL;AAAA,EADK;AAAA,EAGT,OAAO,MAAe,OAAqB;AAC1C,UAAM,QAAQ,KAAK,mBAAmB,qBAAqB;AAC3D,QAAI,OAAO;AACV,iBAAW,QAAQ,OAAO;AACzB,wCAAgC,KAAK,GAAmC;AAAA,MACzE;AAAA,IACD;AAEA,kBAAc,KAAK;AAAA,EACpB;AAAA,EAEA,QAAQ,MAAqB;AAAA,EAAE;AAChC;AAMA,SAAS,qBAAqB,KAAmD;AAChF,kCAAgC,GAAG;AAEnC,SAAO;AAAA,IACN,SAAS,CAAC,SAAiB,YAAY,IAAI,GAAG,SAAS;AAAA,IACvD,MAAM,CAAC,SAAiB,aAAa,IAAI;AAAA,IACzC,OAAO,CAAC,SAAiB,cAAc,IAAI;AAAA,IAC3C,aAAa,CAAC,SAAiB,YAAY,IAAI,GAAG,YAAY;AAAA,EAC/D;AACD;AAEA,SAAS,2BACR,KAC0B;AAC1B,QAAM,WAAY,IAAY;AAC9B,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,OAAO,QAAQ,IAAI,QAAQ,SAAS,EAAE,IAAI,CAAC,CAAC,MAAM,MAAM,OAAO;AAAA,IAC9E;AAAA,IACA,UAAU,OAAO;AAAA,IACjB,WAAW,OAAO,aAAa;AAAA,EAChC,EAAE;AACF,EAAC,IAAY,4BAA4B;AACzC,SAAO;AACR;AAEA,SAAS,gCAAgC,KAAyC;AACjF,MAAK,IAAY,sBAAuB;AAExC,aAAW,SAAS,2BAA2B,GAAG,GAAG;AACpD,qBAAiB,MAAM,MAAM,MAAM,UAAU,MAAM,SAAS;AAAA,EAC7D;AAEA,EAAC,IAAY,wBAAwB;AACtC;AAkCO,IAAM,mBAAmB,eAAgD;AAAA,EAC/E,MAAM;AAAA,EACN,gBAAgB,EAAE,WAAW,CAAC,EAAE;AAAA,EAChC,eAAe,CAAC,QACf,IAAI,eAAe,IAAI,gBAAgB;AAAA,EACxC,cAAc;AACf,CAAC;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/behaviors/world-boundary-2d/world-boundary-2d-fsm.ts","../src/lib/behaviors/world-boundary-2d/world-boundary-2d.descriptor.ts"],"sourcesContent":["/**\n * WorldBoundary2DFSM\n *\n * Minimal FSM + extended state to track which world boundaries were hit.\n *\n * Notes:\n * - \"Hit boundaries\" is inherently a *set* (can hit left+bottom in one frame),\n * so we store it as extended state (`lastHits`) rather than a single FSM state.\n * - The FSM state is still useful for coarse status like \"inside\" vs \"touching\".\n */\n\nimport { SyncStateMachine, t } from '../../core/utility/sync-state-machine';\nimport {\n\tcomputeBounds2DHits,\n\tconstrainMovementToBounds2D,\n\thasAnyBounds2DHit,\n} from '../shared/bounds-2d';\n\nexport type WorldBoundary2DHit = 'top' | 'bottom' | 'left' | 'right';\nexport type WorldBoundary2DHits = Record<WorldBoundary2DHit, boolean>;\n\nexport interface WorldBoundary2DPosition {\n\tx: number;\n\ty: number;\n}\n\nexport interface WorldBoundary2DBounds {\n\ttop: number;\n\tbottom: number;\n\tleft: number;\n\tright: number;\n}\n\nexport enum WorldBoundary2DState {\n\tInside = 'inside',\n\tTouching = 'touching',\n}\n\nexport enum WorldBoundary2DEvent {\n\tEnterInside = 'enter-inside',\n\tTouchBoundary = 'touch-boundary',\n}\n\n/**\n * Compute which boundaries are being hit for a position and bounds.\n * This matches the semantics of the legacy `boundary2d` behavior:\n * - left hit if x <= left\n * - right hit if x >= right\n * - bottom hit if y <= bottom\n * - top hit if y >= top\n */\nexport function computeWorldBoundary2DHits(\n\tposition: WorldBoundary2DPosition,\n\tbounds: WorldBoundary2DBounds\n): WorldBoundary2DHits {\n\treturn computeBounds2DHits(position, {\n\t\tminX: bounds.left,\n\t\tmaxX: bounds.right,\n\t\tminY: bounds.bottom,\n\t\tmaxY: bounds.top,\n\t});\n}\n\nexport function hasAnyWorldBoundary2DHit(hits: WorldBoundary2DHits): boolean {\n\treturn hasAnyBounds2DHit(hits);\n}\n\n/**\n * FSM wrapper with \"extended state\" (lastHits / lastPosition).\n * Systems should call `update(...)` once per frame.\n */\nexport class WorldBoundary2DFSM {\n\tpublic readonly machine: SyncStateMachine<WorldBoundary2DState, WorldBoundary2DEvent, never>;\n\n\tprivate lastHits: WorldBoundary2DHits = { top: false, bottom: false, left: false, right: false };\n\tprivate lastPosition: WorldBoundary2DPosition | null = null;\n\tprivate lastUpdatedAtMs: number | null = null;\n\n\tconstructor() {\n\t\tthis.machine = new SyncStateMachine<WorldBoundary2DState, WorldBoundary2DEvent, never>(\n\t\t\tWorldBoundary2DState.Inside,\n\t\t\t[\n\t\t\t\tt(WorldBoundary2DState.Inside, WorldBoundary2DEvent.TouchBoundary, WorldBoundary2DState.Touching),\n\t\t\t\tt(WorldBoundary2DState.Touching, WorldBoundary2DEvent.EnterInside, WorldBoundary2DState.Inside),\n\n\t\t\t\t// Self transitions (no-ops)\n\t\t\t\tt(WorldBoundary2DState.Inside, WorldBoundary2DEvent.EnterInside, WorldBoundary2DState.Inside),\n\t\t\t\tt(WorldBoundary2DState.Touching, WorldBoundary2DEvent.TouchBoundary, WorldBoundary2DState.Touching),\n\t\t\t]\n\t\t);\n\t}\n\n\tgetState(): WorldBoundary2DState {\n\t\treturn this.machine.getState();\n\t}\n\n\t/**\n\t * Returns the last computed hits (always available after first update call).\n\t */\n\tgetLastHits(): WorldBoundary2DHits {\n\t\treturn this.lastHits;\n\t}\n\n\t/**\n\t * Returns adjusted movement values based on boundary hits.\n\t * If the entity is touching a boundary and trying to move further into it,\n\t * that axis component is zeroed out.\n\t *\n\t * @param moveX - The desired X movement\n\t * @param moveY - The desired Y movement\n\t * @returns Adjusted { moveX, moveY } with boundary-blocked axes zeroed\n\t */\n\tgetMovement(moveX: number, moveY: number): { moveX: number; moveY: number } {\n\t\treturn constrainMovementToBounds2D(this.lastHits, moveX, moveY);\n\t}\n\n\t/**\n\t * Returns the last position passed to `update`, if any.\n\t */\n\tgetLastPosition(): WorldBoundary2DPosition | null {\n\t\treturn this.lastPosition;\n\t}\n\n\t/**\n\t * Best-effort timestamp (ms) of the last `update(...)` call.\n\t * This is optional metadata; systems can ignore it.\n\t */\n\tgetLastUpdatedAtMs(): number | null {\n\t\treturn this.lastUpdatedAtMs;\n\t}\n\n\t/**\n\t * Update FSM + extended state based on current position and bounds.\n\t * Returns the computed hits for convenience.\n\t */\n\tupdate(position: WorldBoundary2DPosition, bounds: WorldBoundary2DBounds): WorldBoundary2DHits {\n\t\tconst hits = computeWorldBoundary2DHits(position, bounds);\n\n\t\tthis.lastHits = hits;\n\t\tthis.lastPosition = { x: position.x, y: position.y };\n\t\tthis.lastUpdatedAtMs = Date.now();\n\n\t\tif (hasAnyWorldBoundary2DHit(hits)) {\n\t\t\tthis.dispatch(WorldBoundary2DEvent.TouchBoundary);\n\t\t} else {\n\t\t\tthis.dispatch(WorldBoundary2DEvent.EnterInside);\n\t\t}\n\n\t\treturn hits;\n\t}\n\n\tprivate dispatch(event: WorldBoundary2DEvent): void {\n\t\tif (this.machine.can(event)) {\n\t\t\tthis.machine.syncDispatch(event);\n\t\t}\n\t}\n}\n","/**\n * WorldBoundary2DBehavior\n *\n * Tracks which 2D world boundaries an entity is touching.\n * Use `getMovement()` on the behavior handle to adjust movement based on hits.\n *\n * Source of truth: the WASM stage boundary query, consistent with other behaviors.\n */\n\nimport { defineBehavior, type BehaviorRef } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport {\n\tWorldBoundary2DFSM,\n\ttype WorldBoundary2DBounds,\n\ttype WorldBoundary2DHits,\n} from './world-boundary-2d-fsm';\nimport {\n\tStageBoundaryDim,\n\ttype BehaviorRuntime,\n} from '../../runtime/wasm-stage-runtime';\n\nexport interface WorldBoundary2DOptions {\n\t/**\n\t * World boundaries (in world units).\n\t * - left hit if x <= left\n\t * - right hit if x >= right\n\t * - bottom hit if y <= bottom\n\t * - top hit if y >= top\n\t */\n\tboundaries: WorldBoundary2DBounds;\n}\n\n/**\n * Handle methods provided by WorldBoundary2DBehavior\n */\nexport interface WorldBoundary2DHandle {\n\t/**\n\t * Get the last computed boundary hits.\n\t * Returns null until entity is spawned and FSM is initialized.\n\t */\n\tgetLastHits(): WorldBoundary2DHits | null;\n\n\t/**\n\t * Get adjusted movement values based on boundary hits.\n\t * Zeros out movement into boundaries the entity is touching.\n\t */\n\tgetMovement(moveX: number, moveY: number): { moveX: number; moveY: number };\n}\n\nconst defaultOptions: WorldBoundary2DOptions = {\n\tboundaries: { top: 0, bottom: 0, left: 0, right: 0 },\n};\n\nconst WORLD_BOUNDARY_BEHAVIOR_KEY = Symbol.for(\n\t'zylem:behavior:world-boundary-2d',\n);\n\n/**\n * Creates behavior-specific handle methods for WorldBoundary2DBehavior.\n */\nfunction createWorldBoundary2DHandle(\n\tref: BehaviorRef<WorldBoundary2DOptions>\n): WorldBoundary2DHandle {\n\treturn {\n\t\tgetLastHits: () => {\n\t\t\tconst fsm = ref.fsm as WorldBoundary2DFSM | undefined;\n\t\t\treturn fsm?.getLastHits() ?? null;\n\t\t},\n\t\tgetMovement: (moveX: number, moveY: number) => {\n\t\t\tconst fsm = ref.fsm as WorldBoundary2DFSM | undefined;\n\t\t\treturn fsm?.getMovement(moveX, moveY) ?? { moveX, moveY };\n\t\t},\n\t};\n}\n\n/**\n * WorldBoundary2DSystem\n *\n * Stage-level system that:\n * - finds entities with this behavior attached\n * - computes and tracks boundary hits using the FSM\n *\n * When a {@link BehaviorRuntime} is present in `BehaviorSystemContext` and the\n * entity has been registered with the unified Stage (`runtimeHandle >= 0`), the\n * system uses the Rust `world_boundary` behavior as the source of truth and\n * mirrors its query into the local FSM so handle methods (`getLastHits`,\n * `getMovement`) return the same shape as the legacy code path.\n */\nclass WorldBoundary2DSystem implements BehaviorSystem {\n\tprivate attachedRuntimeSlots = new Set<number>();\n\n\tconstructor(\n\t\tprivate wasmStage: BehaviorRuntime | null,\n\t\tprivate getBehaviorLinks?: (key: symbol) => Iterable<BehaviorEntityLink>,\n\t) {}\n\n\tupdate(_ecs: unknown, _delta: number): void {\n\t\tconst links = this.getBehaviorLinks?.(WORLD_BOUNDARY_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 boundaryRef = link.ref as any;\n\t\t\tconst options = boundaryRef.options as WorldBoundary2DOptions;\n\n\t\t\tif (!boundaryRef.fsm) {\n\t\t\t\tboundaryRef.fsm = new WorldBoundary2DFSM();\n\t\t\t}\n\n\t\t\tconst handle = (gameEntity.runtimeHandle ?? -1) as number;\n\t\t\tif (!this.wasmStage || handle < 0) continue;\n\n\t\t\tthis.ensureWasmAttached(handle, options.boundaries);\n\t\t\tconst query = this.wasmStage.queryWorldBoundary(handle);\n\t\t\tif (query) {\n\t\t\t\tboundaryRef.fsm.update(\n\t\t\t\t\t{ x: query.clamped[0], y: query.clamped[1] },\n\t\t\t\t\toptions.boundaries,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate ensureWasmAttached(handle: number, bounds: WorldBoundary2DBounds): void {\n\t\tif (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;\n\t\tthis.wasmStage.attachWorldBoundary(handle, StageBoundaryDim.Two, {\n\t\t\ttop: bounds.top,\n\t\t\tbottom: bounds.bottom,\n\t\t\tleft: bounds.left,\n\t\t\tright: bounds.right,\n\t\t\tfront: 0,\n\t\t\tback: 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 * WorldBoundary2DBehavior\n *\n * @example\n * ```ts\n * import { WorldBoundary2DBehavior } from \"@zylem/game-lib/behavior\";\n *\n * const ship = createSprite({ ... });\n * const boundary = ship.use(WorldBoundary2DBehavior, {\n * boundaries: { left: -10, right: 10, bottom: -7.5, top: 7.5 },\n * });\n *\n * ship.onUpdate(({ me }) => {\n * let moveX = ..., moveY = ...;\n * const hits = boundary.getLastHits(); // Fully typed!\n * ({ moveX, moveY } = boundary.getMovement(moveX, moveY));\n * me.moveXY(moveX, moveY);\n * });\n * ```\n */\nexport const WorldBoundary2DBehavior = defineBehavior({\n\tname: 'world-boundary-2d',\n\tdefaultOptions,\n\tsystemFactory: (ctx) =>\n\t\tnew WorldBoundary2DSystem(ctx.wasmStage ?? null, ctx.getBehaviorLinks),\n\tcreateHandle: createWorldBoundary2DHandle,\n});\n"],"mappings":"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","names":["WorldBoundary2DState","WorldBoundary2DEvent"]}
|