@zylem/game-lib 0.6.2 → 0.6.3

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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -16
  3. package/dist/actions.d.ts +30 -21
  4. package/dist/actions.js +628 -145
  5. package/dist/actions.js.map +1 -1
  6. package/dist/behavior/platformer-3d.d.ts +296 -0
  7. package/dist/behavior/platformer-3d.js +518 -0
  8. package/dist/behavior/platformer-3d.js.map +1 -0
  9. package/dist/behavior/ricochet-2d.d.ts +274 -0
  10. package/dist/behavior/ricochet-2d.js +394 -0
  11. package/dist/behavior/ricochet-2d.js.map +1 -0
  12. package/dist/behavior/screen-wrap.d.ts +86 -0
  13. package/dist/behavior/screen-wrap.js +195 -0
  14. package/dist/behavior/screen-wrap.js.map +1 -0
  15. package/dist/behavior/thruster.d.ts +10 -0
  16. package/dist/behavior/thruster.js +234 -0
  17. package/dist/behavior/thruster.js.map +1 -0
  18. package/dist/behavior/world-boundary-2d.d.ts +141 -0
  19. package/dist/behavior/world-boundary-2d.js +181 -0
  20. package/dist/behavior/world-boundary-2d.js.map +1 -0
  21. package/dist/behavior-descriptor-BWNWmIjv.d.ts +142 -0
  22. package/dist/{blueprints-Cq3Ko6_G.d.ts → blueprints-BWGz8fII.d.ts} +2 -2
  23. package/dist/camera-B5e4c78l.d.ts +468 -0
  24. package/dist/camera.d.ts +3 -2
  25. package/dist/camera.js +900 -211
  26. package/dist/camera.js.map +1 -1
  27. package/dist/composition-DrzFrbqI.d.ts +218 -0
  28. package/dist/{core-bO8TzV7u.d.ts → core-DAkskq6Y.d.ts} +60 -62
  29. package/dist/core.d.ts +10 -6
  30. package/dist/core.js +6896 -5020
  31. package/dist/core.js.map +1 -1
  32. package/dist/{entities-DvByhMGU.d.ts → entities-DC9ce_vx.d.ts} +113 -3
  33. package/dist/entities.d.ts +5 -3
  34. package/dist/entities.js +3727 -3167
  35. package/dist/entities.js.map +1 -1
  36. package/dist/entity-BpbZqg19.d.ts +1100 -0
  37. package/dist/global-change-Dc8uCKi2.d.ts +25 -0
  38. package/dist/main.d.ts +418 -15
  39. package/dist/main.js +11384 -8515
  40. package/dist/main.js.map +1 -1
  41. package/dist/{stage-types-Bd-KtcYT.d.ts → stage-types-BFsm3qsZ.d.ts} +205 -13
  42. package/dist/stage.d.ts +10 -7
  43. package/dist/stage.js +5311 -3880
  44. package/dist/stage.js.map +1 -1
  45. package/dist/thruster-DhRaJnoL.d.ts +172 -0
  46. package/dist/world-Be5m1XC1.d.ts +31 -0
  47. package/package.json +29 -13
  48. package/dist/behaviors.d.ts +0 -854
  49. package/dist/behaviors.js +0 -1209
  50. package/dist/behaviors.js.map +0 -1
  51. package/dist/camera-CeJPAgGg.d.ts +0 -116
  52. package/dist/moveable-B_vyA6cw.d.ts +0 -67
  53. package/dist/transformable-CUhvyuYO.d.ts +0 -67
  54. package/dist/world-C8tQ7Plj.d.ts +0 -774
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/actions/behaviors/actions.ts","../src/lib/actions/capabilities/moveable.ts","../src/lib/actions/capabilities/rotatable.ts","../src/lib/actions/capabilities/transformable.ts"],"sourcesContent":["// TODO: rewrite these functions to work well within game loop\n\nexport function wait(delay: number, callback: Function) {\n\t// TODO: needs ticks from loop\n\tsetTimeout(callback, delay);\n}\n\nexport const actionOnPress = (() => {\n\tlet buttonPressed = false;\n\n\treturn (isPressed: boolean, callback: Function) => {\n\t\tif (isPressed && !buttonPressed) {\n\t\t\tbuttonPressed = true;\n\t\t\tcallback();\n\t\t} else if (!isPressed) {\n\t\t\tbuttonPressed = false;\n\t\t}\n\t};\n})();\n\nexport const actionOnRelease = (() => {\n\tlet buttonPressed = false;\n\n\treturn (isPressed: boolean, callback: Function) => {\n\t\tif (!isPressed && buttonPressed) {\n\t\t\tbuttonPressed = false;\n\t\t\tcallback();\n\t\t} else if (isPressed) {\n\t\t\tbuttonPressed = true;\n\t\t}\n\t};\n})();\n\ntype CooldownOptions = { timer: number; immediate?: boolean };\n\nexport const actionWithCooldown = (() => {\n\tlet lastExecutionTime = -Infinity;\n\tlet flagImmediate = false;\n\n\treturn ({ timer, immediate = true }: CooldownOptions, callback: Function, update: Function) => {\n\t\tlet currentTime = Date.now();\n\n\t\tif (!flagImmediate && !immediate) {\n\t\t\tflagImmediate = true;\n\t\t\tlastExecutionTime = currentTime;\n\t\t}\n\n\t\tconst delta = currentTime - lastExecutionTime;\n\n\t\tif (delta >= timer) {\n\t\t\tlastExecutionTime = currentTime;\n\t\t\tcallback();\n\t\t}\n\t\tupdate({ delta });\n\t};\n})();\n\nexport const actionWithThrottle = (() => {\n\tlet lastExecutionTime = 0;\n\n\treturn (timer: number, callback: Function) => {\n\t\tconst currentTime = Date.now();\n\t\tconst delta = currentTime - lastExecutionTime;\n\n\t\tif (delta >= timer) {\n\t\t\tlastExecutionTime = currentTime;\n\t\t\tcallback();\n\t\t}\n\t};\n})();\n","import { Vector3 } from 'three';\nimport { RigidBody, Vector } from '@dimforge/rapier3d-compat';\n\nexport interface EntityWithBody {\n\tbody: RigidBody | null;\n}\n\n/**\n * Move an entity along the X axis, preserving other velocities\n */\nexport function moveX(entity: EntityWithBody, delta: number): void {\n\tif (!entity.body) return;\n\tconst currentVelocity = entity.body.linvel();\n\tconst newVelocity = new Vector3(delta, currentVelocity.y, currentVelocity.z);\n\tentity.body.setLinvel(newVelocity, true);\n}\n\n/**\n * Move an entity along the Y axis, preserving other velocities\n */\nexport function moveY(entity: EntityWithBody, delta: number): void {\n\tif (!entity.body) return;\n\tconst currentVelocity = entity.body.linvel();\n\tconst newVelocity = new Vector3(currentVelocity.x, delta, currentVelocity.z);\n\tentity.body.setLinvel(newVelocity, true);\n}\n\n/**\n * Move an entity along the Z axis, preserving other velocities\n */\nexport function moveZ(entity: EntityWithBody, delta: number): void {\n\tif (!entity.body) return;\n\tconst currentVelocity = entity.body.linvel();\n\tconst newVelocity = new Vector3(currentVelocity.x, currentVelocity.y, delta);\n\tentity.body.setLinvel(newVelocity, true);\n}\n\n/**\n * Move an entity along the X and Y axis, preserving Z velocity\n */\nexport function moveXY(entity: EntityWithBody, deltaX: number, deltaY: number): void {\n\tif (!entity.body) return;\n\tconst currentVelocity = entity.body.linvel();\n\tconst newVelocity = new Vector3(deltaX, deltaY, currentVelocity.z);\n\tentity.body.setLinvel(newVelocity, true);\n}\n\n/**\n * Move an entity along the X and Z axis, preserving Y velocity\n */\nexport function moveXZ(entity: EntityWithBody, deltaX: number, deltaZ: number): void {\n\tif (!entity.body) return;\n\tconst currentVelocity = entity.body.linvel();\n\tconst newVelocity = new Vector3(deltaX, currentVelocity.y, deltaZ);\n\tentity.body.setLinvel(newVelocity, true);\n}\n\n/**\n * Move entity based on a vector, adding to existing velocities\n */\nexport function move(entity: EntityWithBody, vector: Vector3): void {\n\tif (!entity.body) return;\n\tconst currentVelocity = entity.body.linvel();\n\tconst newVelocity = new Vector3(\n\t\tcurrentVelocity.x + vector.x,\n\t\tcurrentVelocity.y + vector.y,\n\t\tcurrentVelocity.z + vector.z\n\t);\n\tentity.body.setLinvel(newVelocity, true);\n}\n\n/**\n * Reset entity velocity\n */\nexport function resetVelocity(entity: EntityWithBody): void {\n\tif (!entity.body) return;\n\tentity.body.setLinvel(new Vector3(0, 0, 0), true);\n\tentity.body.setLinearDamping(5);\n}\n\n/**\n * Move entity forward in 2D space, preserving Z velocity\n */\nexport function moveForwardXY(entity: EntityWithBody, delta: number, rotation2DAngle: number): void {\n\tconst deltaX = Math.sin(-rotation2DAngle) * delta;\n\tconst deltaY = Math.cos(-rotation2DAngle) * delta;\n\tmoveXY(entity, deltaX, deltaY);\n}\n\n/**\n * Get entity position\n */\nexport function getPosition(entity: EntityWithBody): Vector | null {\n\tif (!entity.body) return null;\n\treturn entity.body.translation();\n}\n\n/**\n * Get entity velocity\n */\nexport function getVelocity(entity: EntityWithBody): Vector | null {\n\tif (!entity.body) return null;\n\treturn entity.body.linvel();\n}\n\n/**\n * Set entity position\n */\nexport function setPosition(entity: EntityWithBody, x: number, y: number, z: number): void {\n\tif (!entity.body) return;\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Set entity X position\n */\nexport function setPositionX(entity: EntityWithBody, x: number): void {\n\tif (!entity.body) return;\n\tconst { y, z } = entity.body.translation();\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Set entity Y position\n */\nexport function setPositionY(entity: EntityWithBody, y: number): void {\n\tif (!entity.body) return;\n\tconst { x, z } = entity.body.translation();\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Set entity Z position\n */\nexport function setPositionZ(entity: EntityWithBody, z: number): void {\n\tif (!entity.body) return;\n\tconst { x, y } = entity.body.translation();\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Wrap entity around 2D bounds\n */\nexport function wrapAroundXY(entity: EntityWithBody, boundsX: number, boundsY: number): void {\n\tconst position = getPosition(entity);\n\tif (!position) return;\n\n\tconst { x, y } = position;\n\tconst newX = x > boundsX ? -boundsX : (x < -boundsX ? boundsX : x);\n\tconst newY = y > boundsY ? -boundsY : (y < -boundsY ? boundsY : y);\n\n\tif (newX !== x || newY !== y) {\n\t\tsetPosition(entity, newX, newY, 0);\n\t}\n}\n\n/**\n * Wrap entity around 3D bounds\n */\nexport function wrapAround3D(entity: EntityWithBody, boundsX: number, boundsY: number, boundsZ: number): void {\n\tconst position = getPosition(entity);\n\tif (!position) return;\n\n\tconst { x, y, z } = position;\n\tconst newX = x > boundsX ? -boundsX : (x < -boundsX ? boundsX : x);\n\tconst newY = y > boundsY ? -boundsY : (y < -boundsY ? boundsY : y);\n\tconst newZ = z > boundsZ ? -boundsZ : (z < -boundsZ ? boundsZ : z);\n\n\tif (newX !== x || newY !== y || newZ !== z) {\n\t\tsetPosition(entity, newX, newY, newZ);\n\t}\n}\n\n/**\n * Enhanced moveable entity with bound methods\n */\nexport interface MoveableEntity extends EntityWithBody {\n\tmoveX(delta: number): void;\n\tmoveY(delta: number): void;\n\tmoveZ(delta: number): void;\n\tmoveXY(deltaX: number, deltaY: number): void;\n\tmoveXZ(deltaX: number, deltaZ: number): void;\n\tmove(vector: Vector3): void;\n\tresetVelocity(): void;\n\tmoveForwardXY(delta: number, rotation2DAngle: number): void;\n\tgetPosition(): Vector | null;\n\tgetVelocity(): Vector | null;\n\tsetPosition(x: number, y: number, z: number): void;\n\tsetPositionX(x: number): void;\n\tsetPositionY(y: number): void;\n\tsetPositionZ(z: number): void;\n\twrapAroundXY(boundsX: number, boundsY: number): void;\n\twrapAround3D(boundsX: number, boundsY: number, boundsZ: number): void;\n}\n\n/**\n * Class decorator to enhance an entity with additive movement methods\n */\nexport function moveable<T extends { new(...args: any[]): EntityWithBody }>(constructor: T) {\n\treturn class extends constructor implements MoveableEntity {\n\t\tmoveX(delta: number): void {\n\t\t\tmoveX(this, delta);\n\t\t}\n\t\tmoveY(delta: number): void {\n\t\t\tmoveY(this, delta);\n\t\t}\n\t\tmoveZ(delta: number): void {\n\t\t\tmoveZ(this, delta);\n\t\t}\n\t\tmoveXY(deltaX: number, deltaY: number): void {\n\t\t\tmoveXY(this, deltaX, deltaY);\n\t\t}\n\t\tmoveXZ(deltaX: number, deltaZ: number): void {\n\t\t\tmoveXZ(this, deltaX, deltaZ);\n\t\t}\n\t\tmove(vector: Vector3): void {\n\t\t\tmove(this, vector);\n\t\t}\n\t\tresetVelocity(): void {\n\t\t\tresetVelocity(this);\n\t\t}\n\t\tmoveForwardXY(delta: number, rotation2DAngle: number): void {\n\t\t\tmoveForwardXY(this, delta, rotation2DAngle);\n\t\t}\n\t\tgetPosition(): Vector | null {\n\t\t\treturn getPosition(this);\n\t\t}\n\t\tgetVelocity(): Vector | null {\n\t\t\treturn getVelocity(this);\n\t\t}\n\t\tsetPosition(x: number, y: number, z: number): void {\n\t\t\tsetPosition(this, x, y, z);\n\t\t}\n\t\tsetPositionX(x: number): void {\n\t\t\tsetPositionX(this, x);\n\t\t}\n\t\tsetPositionY(y: number): void {\n\t\t\tsetPositionY(this, y);\n\t\t}\n\t\tsetPositionZ(z: number): void {\n\t\t\tsetPositionZ(this, z);\n\t\t}\n\t\twrapAroundXY(boundsX: number, boundsY: number): void {\n\t\t\twrapAroundXY(this, boundsX, boundsY);\n\t\t}\n\t\twrapAround3D(boundsX: number, boundsY: number, boundsZ: number): void {\n\t\t\twrapAround3D(this, boundsX, boundsY, boundsZ);\n\t\t}\n\t};\n}\n\n/**\n * Enhance an entity with additive movement methods (retained for compatibility)\n */\nexport function makeMoveable<T extends EntityWithBody>(entity: T): T & MoveableEntity {\n\tconst moveable = entity as T & MoveableEntity;\n\n\tmoveable.moveX = (delta: number) => moveX(entity, delta);\n\tmoveable.moveY = (delta: number) => moveY(entity, delta);\n\tmoveable.moveZ = (delta: number) => moveZ(entity, delta);\n\tmoveable.moveXY = (deltaX: number, deltaY: number) => moveXY(entity, deltaX, deltaY);\n\tmoveable.moveXZ = (deltaX: number, deltaZ: number) => moveXZ(entity, deltaX, deltaZ);\n\tmoveable.move = (vector: Vector3) => move(entity, vector);\n\tmoveable.resetVelocity = () => resetVelocity(entity);\n\tmoveable.moveForwardXY = (delta: number, rotation2DAngle: number) => moveForwardXY(entity, delta, rotation2DAngle);\n\tmoveable.getPosition = () => getPosition(entity);\n\tmoveable.getVelocity = () => getVelocity(entity);\n\tmoveable.setPosition = (x: number, y: number, z: number) => setPosition(entity, x, y, z);\n\tmoveable.setPositionX = (x: number) => setPositionX(entity, x);\n\tmoveable.setPositionY = (y: number) => setPositionY(entity, y);\n\tmoveable.setPositionZ = (z: number) => setPositionZ(entity, z);\n\tmoveable.wrapAroundXY = (boundsX: number, boundsY: number) => wrapAroundXY(entity, boundsX, boundsY);\n\tmoveable.wrapAround3D = (boundsX: number, boundsY: number, boundsZ: number) => wrapAround3D(entity, boundsX, boundsY, boundsZ);\n\n\treturn moveable;\n}\n\n/**\n * Wrap a standalone function with movement capabilities\n */\nexport function withMovement<T extends (...args: any[]) => any>(\n\tfn: T,\n\tentity: EntityWithBody\n): (...args: Parameters<T>) => ReturnType<T> & MoveableEntity {\n\tconst wrapped = (...args: Parameters<T>) => {\n\t\tconst result = fn(...args);\n\t\tconst moveableEntity = makeMoveable(entity);\n\t\treturn Object.assign(result, moveableEntity);\n\t};\n\treturn wrapped as (...args: Parameters<T>) => ReturnType<T> & MoveableEntity;\n}","import { Euler, Vector3, MathUtils, Quaternion } from 'three';\nimport { RigidBody } from '@dimforge/rapier3d-compat';\n\nexport interface RotatableEntity {\n\tbody: RigidBody | null;\n\tgroup: any;\n}\n\n/**\n * Rotate an entity in the direction of a movement vector\n */\nexport function rotateInDirection(entity: RotatableEntity, moveVector: Vector3): void {\n\tif (!entity.body) return;\n\tconst rotate = Math.atan2(-moveVector.x, moveVector.z);\n\trotateYEuler(entity, rotate);\n}\n\n/**\n * Rotate an entity around the Y axis using Euler angles\n */\nexport function rotateYEuler(entity: RotatableEntity, amount: number): void {\n\trotateEuler(entity, new Vector3(0, -amount, 0));\n}\n\n/**\n * Rotate an entity using Euler angles\n */\nexport function rotateEuler(entity: RotatableEntity, rotation: Vector3): void {\n\tif (!entity.group) return;\n\tconst euler = new Euler(rotation.x, rotation.y, rotation.z);\n\tentity.group.setRotationFromEuler(euler);\n}\n\n/**\n * Rotate an entity around the Y axis\n */\nexport function rotateY(entity: RotatableEntity, delta: number): void {\n\tsetRotationY(entity, delta);\n}\n\n/**\n * Rotate an entity around the Z axis\n */\nexport function rotateZ(entity: RotatableEntity, delta: number): void {\n\tsetRotationZ(entity, delta);\n}\n\n/**\n * Set rotation around Y axis\n */\nexport function setRotationY(entity: RotatableEntity, y: number): void {\n\tif (!entity.body) return;\n\tconst halfAngle = y / 2;\n\tconst w = Math.cos(halfAngle);\n\tconst yComponent = Math.sin(halfAngle);\n\tentity.body.setRotation({ w: w, x: 0, y: yComponent, z: 0 }, true);\n}\n\n/**\n * Set rotation around Y axis\n */\nexport function setRotationDegreesY(entity: RotatableEntity, y: number): void {\n\tif (!entity.body) return;\n\tsetRotationY(entity, MathUtils.degToRad(y));\n}\n\n/**\n * Set rotation around X axis\n */\nexport function setRotationX(entity: RotatableEntity, x: number): void {\n\tif (!entity.body) return;\n\tconst halfAngle = x / 2;\n\tconst w = Math.cos(halfAngle);\n\tconst xComponent = Math.sin(halfAngle);\n\tentity.body.setRotation({ w: w, x: xComponent, y: 0, z: 0 }, true);\n}\n\n/**\n * Set rotation around X axis\n */\nexport function setRotationDegreesX(entity: RotatableEntity, x: number): void {\n\tif (!entity.body) return;\n\tsetRotationX(entity, MathUtils.degToRad(x));\n}\n\n/**\n * Set rotation around Z axis\n */\nexport function setRotationZ(entity: RotatableEntity, z: number): void {\n\tif (!entity.body) return;\n\tconst halfAngle = z / 2;\n\tconst w = Math.cos(halfAngle);\n\tconst zComponent = Math.sin(halfAngle);\n\tentity.body.setRotation({ w: w, x: 0, y: 0, z: zComponent }, true);\n}\n\n/**\n * Set rotation around Z axis\n */\nexport function setRotationDegreesZ(entity: RotatableEntity, z: number): void {\n\tif (!entity.body) return;\n\tsetRotationZ(entity, MathUtils.degToRad(z));\n}\n\n/**\n * Set rotation for all axes\n */\nexport function setRotation(entity: RotatableEntity, x: number, y: number, z: number): void {\n\tif (!entity.body) return;\n\tconst quat = new Quaternion().setFromEuler(new Euler(x, y, z));\n\tentity.body.setRotation({ w: quat.w, x: quat.x, y: quat.y, z: quat.z }, true);\n}\n\n/**\n * Set rotation for all axes\n */\nexport function setRotationDegrees(entity: RotatableEntity, x: number, y: number, z: number): void {\n\tif (!entity.body) return;\n\tsetRotation(entity, MathUtils.degToRad(x), MathUtils.degToRad(y), MathUtils.degToRad(z));\n}\n\n/**\n * Get current rotation\n */\nexport function getRotation(entity: RotatableEntity): any {\n\tif (!entity.body) return null;\n\treturn entity.body.rotation();\n}\n\n/**\n * Rotatable entity API with bound methods\n */\nexport interface RotatableEntityAPI extends RotatableEntity {\n\trotateInDirection(moveVector: Vector3): void;\n\trotateYEuler(amount: number): void;\n\trotateEuler(rotation: Vector3): void;\n\trotateY(delta: number): void;\n\trotateZ(delta: number): void;\n\tsetRotationY(y: number): void;\n\tsetRotationX(x: number): void;\n\tsetRotationZ(z: number): void;\n\tsetRotationDegrees(x: number, y: number, z: number): void;\n\tsetRotationDegreesY(y: number): void;\n\tsetRotationDegreesX(x: number): void;\n\tsetRotationDegreesZ(z: number): void;\n\tsetRotation(x: number, y: number, z: number): void;\n\tgetRotation(): any;\n}\n\n/**\n * Class decorator to enhance an entity with rotatable methods\n */\nexport function rotatable<T extends { new(...args: any[]): RotatableEntity }>(constructor: T) {\n\treturn class extends constructor implements RotatableEntityAPI {\n\t\trotateInDirection(moveVector: Vector3): void {\n\t\t\trotateInDirection(this, moveVector);\n\t\t}\n\t\trotateYEuler(amount: number): void {\n\t\t\trotateYEuler(this, amount);\n\t\t}\n\t\trotateEuler(rotation: Vector3): void {\n\t\t\trotateEuler(this, rotation);\n\t\t}\n\t\trotateY(delta: number): void {\n\t\t\trotateY(this, delta);\n\t\t}\n\t\trotateZ(delta: number): void {\n\t\t\trotateZ(this, delta);\n\t\t}\n\t\tsetRotationY(y: number): void {\n\t\t\tsetRotationY(this, y);\n\t\t}\n\t\tsetRotationX(x: number): void {\n\t\t\tsetRotationX(this, x);\n\t\t}\n\t\tsetRotationZ(z: number): void {\n\t\t\tsetRotationZ(this, z);\n\t\t}\n\t\tsetRotationDegrees(x: number, y: number, z: number): void {\n\t\t\tsetRotationDegrees(this, x, y, z);\n\t\t}\n\t\tsetRotationDegreesY(y: number): void {\n\t\t\tsetRotationDegreesY(this, y);\n\t\t}\n\t\tsetRotationDegreesX(x: number): void {\n\t\t\tsetRotationDegreesX(this, x);\n\t\t}\n\t\tsetRotationDegreesZ(z: number): void {\n\t\t\tsetRotationDegreesZ(this, z);\n\t\t}\n\t\tsetRotation(x: number, y: number, z: number): void {\n\t\t\tsetRotation(this, x, y, z);\n\t\t}\n\t\tgetRotation(): any {\n\t\t\treturn getRotation(this);\n\t\t}\n\t};\n}\n\n/**\n * Enhance an entity instance with rotatable methods\n */\nexport function makeRotatable<T extends RotatableEntity>(entity: T): T & RotatableEntityAPI {\n\tconst rotatableEntity = entity as T & RotatableEntityAPI;\n\n\trotatableEntity.rotateInDirection = (moveVector: Vector3) => rotateInDirection(entity, moveVector);\n\trotatableEntity.rotateYEuler = (amount: number) => rotateYEuler(entity, amount);\n\trotatableEntity.rotateEuler = (rotation: Vector3) => rotateEuler(entity, rotation);\n\trotatableEntity.rotateY = (delta: number) => rotateY(entity, delta);\n\trotatableEntity.rotateZ = (delta: number) => rotateZ(entity, delta);\n\trotatableEntity.setRotationY = (y: number) => setRotationY(entity, y);\n\trotatableEntity.setRotationX = (x: number) => setRotationX(entity, x);\n\trotatableEntity.setRotationZ = (z: number) => setRotationZ(entity, z);\n\trotatableEntity.setRotationDegreesY = (y: number) => setRotationDegreesY(entity, y);\n\trotatableEntity.setRotationDegreesX = (x: number) => setRotationDegreesX(entity, x);\n\trotatableEntity.setRotationDegreesZ = (z: number) => setRotationDegreesZ(entity, z);\n\trotatableEntity.setRotationDegrees = (x: number, y: number, z: number) => setRotationDegrees(entity, x, y, z);\n\trotatableEntity.setRotation = (x: number, y: number, z: number) => setRotation(entity, x, y, z);\n\trotatableEntity.getRotation = () => getRotation(entity);\n\n\treturn rotatableEntity;\n}","import { makeMoveable, EntityWithBody, MoveableEntity } from './moveable';\nimport { makeRotatable, RotatableEntity, RotatableEntityAPI } from './rotatable';\n\n/**\n * Enhance an entity with both movement and rotation capabilities.\n */\nexport function makeTransformable<\n\tT extends RotatableEntity & EntityWithBody\n>(entity: T): T & MoveableEntity & RotatableEntityAPI {\n\tconst withMovement = makeMoveable(entity);\n\tconst withRotation = makeRotatable(withMovement);\n\treturn withRotation;\n}\n\n\n"],"mappings":"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","names":["Vector3"]}
1
+ {"version":3,"sources":["../src/lib/actions/action.ts","../src/lib/actions/interval-actions.ts","../src/lib/actions/persistent-actions.ts","../src/lib/actions/composition.ts","../src/lib/actions/capabilities/transform-store.ts","../src/lib/actions/capabilities/apply-transform.ts","../src/lib/actions/capabilities/moveable.ts","../src/lib/actions/capabilities/rotatable.ts","../src/lib/actions/global-change.ts"],"sourcesContent":["import type { GameEntity, GameEntityOptions } from '../entities/entity';\n\n/**\n * Action interface -- the base contract for all actions.\n *\n * Actions are entity-scoped, self-contained objects that modify entity state\n * over time. They are ticked automatically by the entity update loop.\n */\nexport interface Action {\n\t/** Internal duration in seconds (0 = instant, Infinity = persistent) */\n\treadonly duration: number;\n\t/** Whether this action has completed */\n\treadonly done: boolean;\n\t/** Whether this action auto-removes when done (set by entity.action()) */\n\tpersistent: boolean;\n\t/** Advance the action by delta seconds */\n\ttick(entity: GameEntity<any>, delta: number): void;\n\t/** Reset the action to its initial state */\n\treset(): void;\n}\n\n/**\n * Base class for interval actions that run over a fixed duration.\n * Accepts duration in **milliseconds**; converts to seconds internally\n * since the game loop delta is in seconds.\n */\nexport abstract class BaseAction implements Action {\n\tpublic readonly duration: number;\n\tpublic done: boolean = false;\n\tpublic persistent: boolean = false;\n\tprotected elapsed: number = 0;\n\n\t/** @param durationMs Duration in milliseconds */\n\tconstructor(durationMs: number) {\n\t\tthis.duration = durationMs / 1000;\n\t}\n\n\ttick(entity: GameEntity<any>, delta: number): void {\n\t\tif (this.done) return;\n\t\tthis.elapsed += delta;\n\t\tconst progress = this.duration > 0 ? Math.min(this.elapsed / this.duration, 1) : 1;\n\t\tthis.onTick(entity, delta, progress);\n\t\tif (this.elapsed >= this.duration) {\n\t\t\tthis.done = true;\n\t\t}\n\t}\n\n\treset(): void {\n\t\tthis.elapsed = 0;\n\t\tthis.done = false;\n\t}\n\n\t/**\n\t * Subclasses implement this to apply their effect each frame.\n\t * @param entity The entity this action is running on\n\t * @param delta Frame delta in seconds\n\t * @param progress 0..1 normalized progress through the duration\n\t */\n\tprotected abstract onTick(\n\t\tentity: GameEntity<any>,\n\t\tdelta: number,\n\t\tprogress: number,\n\t): void;\n}\n","import type { GameEntity } from '../entities/entity';\nimport { BaseAction, type Action } from './action';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// MoveBy -- accumulate position delta over duration via velocity\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface MoveByOptions {\n\t/** X displacement (default: 0) */\n\tx?: number;\n\t/** Y displacement (default: 0) */\n\ty?: number;\n\t/** Z displacement (default: 0) */\n\tz?: number;\n\t/** Duration in milliseconds */\n\tduration: number;\n}\n\n/**\n * Move an entity by a displacement over a duration.\n * Distributes the movement as velocity each frame so physics stays in sync.\n *\n * @example\n * ```ts\n * entity.runAction(moveBy({ x: 10, duration: 500 }));\n * ```\n */\nexport function moveBy(opts: MoveByOptions): Action {\n\treturn new MoveByAction(opts);\n}\n\nclass MoveByAction extends BaseAction {\n\tprivate dx: number;\n\tprivate dy: number;\n\tprivate dz: number;\n\n\tconstructor(opts: MoveByOptions) {\n\t\tsuper(opts.duration);\n\t\tthis.dx = opts.x ?? 0;\n\t\tthis.dy = opts.y ?? 0;\n\t\tthis.dz = opts.z ?? 0;\n\t}\n\n\tprotected onTick(entity: GameEntity<any>, delta: number, _progress: number): void {\n\t\tif (this.duration <= 0) return;\n\t\t// Distribute displacement as velocity: displacement/duration per second\n\t\tconst vx = this.dx / this.duration;\n\t\tconst vy = this.dy / this.duration;\n\t\tconst vz = this.dz / this.duration;\n\t\tconst store = entity.transformStore;\n\t\tstore.velocity.x += vx;\n\t\tstore.velocity.y += vy;\n\t\tstore.velocity.z += vz;\n\t\tstore.dirty.velocity = true;\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// MoveTo -- move to an absolute position over duration\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface MoveToOptions {\n\t/** Target X position */\n\tx: number;\n\t/** Target Y position */\n\ty: number;\n\t/** Target Z position */\n\tz: number;\n\t/** Duration in milliseconds */\n\tduration: number;\n}\n\n/**\n * Move an entity to an absolute position over a duration.\n * Calculates displacement from the entity's position on the first tick.\n *\n * @example\n * ```ts\n * entity.runAction(moveTo({ x: 0, y: 10, z: 0, duration: 2000 }));\n * ```\n */\nexport function moveTo(opts: MoveToOptions): Action {\n\treturn new MoveToAction(opts);\n}\n\nclass MoveToAction extends BaseAction {\n\tprivate targetX: number;\n\tprivate targetY: number;\n\tprivate targetZ: number;\n\tprivate dx = 0;\n\tprivate dy = 0;\n\tprivate dz = 0;\n\tprivate initialized = false;\n\n\tconstructor(opts: MoveToOptions) {\n\t\tsuper(opts.duration);\n\t\tthis.targetX = opts.x;\n\t\tthis.targetY = opts.y;\n\t\tthis.targetZ = opts.z;\n\t}\n\n\tprotected onTick(entity: GameEntity<any>, delta: number, _progress: number): void {\n\t\tif (this.duration <= 0) return;\n\t\tif (!this.initialized) {\n\t\t\tconst pos = entity.getPosition?.();\n\t\t\tconst cx = pos?.x ?? 0;\n\t\t\tconst cy = pos?.y ?? 0;\n\t\t\tconst cz = pos?.z ?? 0;\n\t\t\tthis.dx = this.targetX - cx;\n\t\t\tthis.dy = this.targetY - cy;\n\t\t\tthis.dz = this.targetZ - cz;\n\t\t\tthis.initialized = true;\n\t\t}\n\t\tconst vx = this.dx / this.duration;\n\t\tconst vy = this.dy / this.duration;\n\t\tconst vz = this.dz / this.duration;\n\t\tconst store = entity.transformStore;\n\t\tstore.velocity.x += vx;\n\t\tstore.velocity.y += vy;\n\t\tstore.velocity.z += vz;\n\t\tstore.dirty.velocity = true;\n\t}\n\n\treset(): void {\n\t\tsuper.reset();\n\t\tthis.initialized = false;\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// RotateBy -- rotate by euler angles (degrees) over duration\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface RotateByOptions {\n\t/** X rotation in degrees (default: 0) */\n\tx?: number;\n\t/** Y rotation in degrees (default: 0) */\n\ty?: number;\n\t/** Z rotation in degrees (default: 0) */\n\tz?: number;\n\t/** Duration in milliseconds */\n\tduration: number;\n}\n\n/**\n * Rotate an entity by euler angles (degrees) over a duration.\n *\n * @example\n * ```ts\n * entity.runAction(rotateBy({ y: 360, duration: 2000 }));\n * ```\n */\nexport function rotateBy(opts: RotateByOptions): Action {\n\treturn new RotateByAction(opts);\n}\n\nclass RotateByAction extends BaseAction {\n\tprivate rx: number;\n\tprivate ry: number;\n\tprivate rz: number;\n\n\tconstructor(opts: RotateByOptions) {\n\t\tsuper(opts.duration);\n\t\tconst toRad = Math.PI / 180;\n\t\tthis.rx = (opts.x ?? 0) * toRad;\n\t\tthis.ry = (opts.y ?? 0) * toRad;\n\t\tthis.rz = (opts.z ?? 0) * toRad;\n\t}\n\n\tprotected onTick(entity: GameEntity<any>, delta: number, _progress: number): void {\n\t\tif (this.duration <= 0) return;\n\t\t// Distribute angular velocity in radians/sec\n\t\tconst wx = this.rx / this.duration;\n\t\tconst wy = this.ry / this.duration;\n\t\tconst wz = this.rz / this.duration;\n\t\tconst store = entity.transformStore;\n\t\tstore.angularVelocity.x += wx;\n\t\tstore.angularVelocity.y += wy;\n\t\tstore.angularVelocity.z += wz;\n\t\tstore.dirty.angularVelocity = true;\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Delay -- no-op for a duration (used in sequences)\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Wait for a duration. Useful inside `sequence()`.\n *\n * @param ms Duration in milliseconds\n * @example\n * ```ts\n * entity.runAction(sequence(moveBy({ x: 5, duration: 1000 }), delay(500), moveBy({ y: 3, duration: 1000 })));\n * ```\n */\nexport function delay(ms: number): Action {\n\treturn new DelayAction(ms);\n}\n\nclass DelayAction extends BaseAction {\n\tconstructor(ms: number) {\n\t\tsuper(ms);\n\t}\n\n\tprotected onTick(): void {\n\t\t// no-op -- just waits\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// CallFunc -- instant action that calls a function\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Call a function immediately. Completes in one frame.\n * Useful inside `sequence()` for side effects.\n *\n * @example\n * ```ts\n * entity.runAction(sequence(moveBy({ x: 5, duration: 1000 }), callFunc(() => console.log('done'))));\n * ```\n */\nexport function callFunc(fn: () => void): Action {\n\treturn new CallFuncAction(fn);\n}\n\nclass CallFuncAction extends BaseAction {\n\tprivate fn: () => void;\n\tprivate called = false;\n\n\tconstructor(fn: () => void) {\n\t\tsuper(0);\n\t\tthis.fn = fn;\n\t}\n\n\tprotected onTick(): void {\n\t\tif (!this.called) {\n\t\t\tthis.fn();\n\t\t\tthis.called = true;\n\t\t}\n\t}\n\n\treset(): void {\n\t\tsuper.reset();\n\t\tthis.called = false;\n\t}\n}\n","import type { GameEntity } from '../entities/entity';\nimport type { Action } from './action';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Throttle -- auto-resetting timer\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface ThrottleOptions {\n\t/** Interval in milliseconds between ready cycles */\n\tduration: number;\n}\n\n/**\n * A repeating timer that becomes ready every N milliseconds.\n * Register with `entity.action(throttle(...))`.\n *\n * @example\n * ```ts\n * const t = entity.action(throttle({ duration: 500 }));\n * entity.onUpdate(() => {\n * if (t.ready) { t.consume(); // do something every 500ms }\n * });\n * ```\n */\nexport function throttle(opts: ThrottleOptions): ThrottleAction {\n\treturn new ThrottleAction(opts.duration);\n}\n\nexport class ThrottleAction implements Action {\n\tpublic readonly duration: number;\n\tpublic done: boolean = false;\n\tpublic persistent: boolean = true;\n\tpublic ready: boolean = false;\n\tprivate elapsed: number = 0;\n\n\t/** @param durationMs Duration in milliseconds */\n\tconstructor(durationMs: number) {\n\t\tthis.duration = durationMs / 1000;\n\t}\n\n\ttick(_entity: GameEntity<any>, delta: number): void {\n\t\tthis.elapsed += delta;\n\t\tif (this.elapsed >= this.duration) {\n\t\t\tthis.ready = true;\n\t\t}\n\t}\n\n\t/** Consume the ready state and reset the timer */\n\tconsume(): void {\n\t\tthis.ready = false;\n\t\tthis.elapsed = 0;\n\t}\n\n\treset(): void {\n\t\tthis.elapsed = 0;\n\t\tthis.ready = false;\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// OnPress -- edge-detection for button press\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Detects the rising edge of a boolean signal (press).\n * Call `.check(isPressed)` each frame in your onUpdate; `.triggered` is\n * true for one frame on press.\n *\n * @example\n * ```ts\n * const press = entity.action(onPress());\n * entity.onUpdate(({ inputs }) => {\n * press.check(inputs.p1.buttons.A.pressed);\n * if (press.triggered) { // do something once on press }\n * });\n * ```\n */\nexport function onPress(): OnPressAction {\n\treturn new OnPressAction();\n}\n\nexport class OnPressAction implements Action {\n\tpublic readonly duration = Infinity;\n\tpublic done: boolean = false;\n\tpublic persistent: boolean = true;\n\tpublic triggered: boolean = false;\n\tprivate wasPressed: boolean = false;\n\n\ttick(): void {\n\t\t// Reset triggered each frame; .check() sets it\n\t\tthis.triggered = false;\n\t}\n\n\t/**\n\t * Feed the current pressed state. Sets `.triggered = true` on the\n\t * frame where `isPressed` transitions from false to true.\n\t */\n\tcheck(isPressed: boolean): void {\n\t\tif (isPressed && !this.wasPressed) {\n\t\t\tthis.triggered = true;\n\t\t}\n\t\tthis.wasPressed = isPressed;\n\t}\n\n\treset(): void {\n\t\tthis.triggered = false;\n\t\tthis.wasPressed = false;\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// OnRelease -- edge-detection for button release\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Detects the falling edge of a boolean signal (release).\n * Call `.check(isPressed)` each frame; `.triggered` is true for one frame\n * on release.\n *\n * @example\n * ```ts\n * const release = entity.action(onRelease());\n * entity.onUpdate(({ inputs }) => {\n * release.check(inputs.p1.buttons.A.pressed);\n * if (release.triggered) { // do something once on release }\n * });\n * ```\n */\nexport function onRelease(): OnReleaseAction {\n\treturn new OnReleaseAction();\n}\n\nexport class OnReleaseAction implements Action {\n\tpublic readonly duration = Infinity;\n\tpublic done: boolean = false;\n\tpublic persistent: boolean = true;\n\tpublic triggered: boolean = false;\n\tprivate wasPressed: boolean = false;\n\n\ttick(): void {\n\t\tthis.triggered = false;\n\t}\n\n\t/**\n\t * Feed the current pressed state. Sets `.triggered = true` on the\n\t * frame where `isPressed` transitions from true to false.\n\t */\n\tcheck(isPressed: boolean): void {\n\t\tif (!isPressed && this.wasPressed) {\n\t\t\tthis.triggered = true;\n\t\t}\n\t\tthis.wasPressed = isPressed;\n\t}\n\n\treset(): void {\n\t\tthis.triggered = false;\n\t\tthis.wasPressed = false;\n\t}\n}\n","import type { GameEntity } from '../entities/entity';\nimport type { Action } from './action';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Sequence -- runs actions one after another\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Run actions in order, one after another.\n *\n * @example\n * ```ts\n * entity.runAction(sequence(\n * moveBy({ x: 5, duration: 1000 }),\n * delay(500),\n * moveBy({ y: 3, duration: 1000 }),\n * ));\n * ```\n */\nexport function sequence(...actions: Action[]): Action {\n\treturn new SequenceAction(actions);\n}\n\nclass SequenceAction implements Action {\n\tpublic duration: number;\n\tpublic done: boolean = false;\n\tpublic persistent: boolean = false;\n\tprivate actions: Action[];\n\tprivate currentIndex: number = 0;\n\n\tconstructor(actions: Action[]) {\n\t\tthis.actions = actions;\n\t\tthis.duration = actions.reduce((sum, a) => sum + a.duration, 0);\n\t}\n\n\ttick(entity: GameEntity<any>, delta: number): void {\n\t\tif (this.done || this.actions.length === 0) {\n\t\t\tthis.done = true;\n\t\t\treturn;\n\t\t}\n\n\t\tlet remaining = delta;\n\t\twhile (remaining > 0 && this.currentIndex < this.actions.length) {\n\t\t\tconst current = this.actions[this.currentIndex];\n\t\t\tcurrent.tick(entity, remaining);\n\t\t\tif (current.done) {\n\t\t\t\t// Calculate overflow time for the next action\n\t\t\t\tconst actionDuration = current.duration;\n\t\t\t\tconst actionElapsed = (current as any).elapsed ?? actionDuration;\n\t\t\t\tconst overflow = Math.max(0, actionElapsed - actionDuration);\n\t\t\t\tremaining = overflow;\n\t\t\t\tthis.currentIndex++;\n\t\t\t} else {\n\t\t\t\tremaining = 0;\n\t\t\t}\n\t\t}\n\n\t\tif (this.currentIndex >= this.actions.length) {\n\t\t\tthis.done = true;\n\t\t}\n\t}\n\n\treset(): void {\n\t\tthis.currentIndex = 0;\n\t\tthis.done = false;\n\t\tfor (const action of this.actions) {\n\t\t\taction.reset();\n\t\t}\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Parallel -- runs all actions simultaneously\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Run all actions simultaneously. Done when all children are done.\n *\n * @example\n * ```ts\n * entity.runAction(parallel(\n * moveBy({ x: 5, duration: 1000 }),\n * rotateBy({ y: 360, duration: 1000 }),\n * ));\n * ```\n */\nexport function parallel(...actions: Action[]): Action {\n\treturn new ParallelAction(actions);\n}\n\nclass ParallelAction implements Action {\n\tpublic duration: number;\n\tpublic done: boolean = false;\n\tpublic persistent: boolean = false;\n\tprivate actions: Action[];\n\n\tconstructor(actions: Action[]) {\n\t\tthis.actions = actions;\n\t\tthis.duration = Math.max(0, ...actions.map(a => a.duration));\n\t}\n\n\ttick(entity: GameEntity<any>, delta: number): void {\n\t\tif (this.done) return;\n\n\t\tlet allDone = true;\n\t\tfor (const action of this.actions) {\n\t\t\tif (!action.done) {\n\t\t\t\taction.tick(entity, delta);\n\t\t\t}\n\t\t\tif (!action.done) {\n\t\t\t\tallDone = false;\n\t\t\t}\n\t\t}\n\n\t\tif (allDone) {\n\t\t\tthis.done = true;\n\t\t}\n\t}\n\n\treset(): void {\n\t\tthis.done = false;\n\t\tfor (const action of this.actions) {\n\t\t\taction.reset();\n\t\t}\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Repeat -- repeats an action N times\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Repeat an action a fixed number of times.\n *\n * @example\n * ```ts\n * entity.runAction(repeat(moveBy({ x: 2, duration: 500 }), 5));\n * ```\n */\nexport function repeat(action: Action, times: number): Action {\n\treturn new RepeatAction(action, times);\n}\n\nclass RepeatAction implements Action {\n\tpublic duration: number;\n\tpublic done: boolean = false;\n\tpublic persistent: boolean = false;\n\tprivate action: Action;\n\tprivate totalTimes: number;\n\tprivate currentCount: number = 0;\n\n\tconstructor(action: Action, times: number) {\n\t\tthis.action = action;\n\t\tthis.totalTimes = times;\n\t\tthis.duration = action.duration * times;\n\t}\n\n\ttick(entity: GameEntity<any>, delta: number): void {\n\t\tif (this.done) return;\n\n\t\tthis.action.tick(entity, delta);\n\t\tif (this.action.done) {\n\t\t\tthis.currentCount++;\n\t\t\tif (this.currentCount >= this.totalTimes) {\n\t\t\t\tthis.done = true;\n\t\t\t} else {\n\t\t\t\tthis.action.reset();\n\t\t\t}\n\t\t}\n\t}\n\n\treset(): void {\n\t\tthis.currentCount = 0;\n\t\tthis.done = false;\n\t\tthis.action.reset();\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// RepeatForever -- repeats an action indefinitely\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Repeat an action forever. Never completes.\n *\n * @example\n * ```ts\n * enemy.runAction(repeatForever(\n * sequence(moveBy({ x: 3, duration: 2000 }), moveBy({ x: -3, duration: 2000 })),\n * ));\n * ```\n */\nexport function repeatForever(action: Action): Action {\n\treturn new RepeatForeverAction(action);\n}\n\nclass RepeatForeverAction implements Action {\n\tpublic readonly duration = Infinity;\n\tpublic done: boolean = false;\n\tpublic persistent: boolean = false;\n\tprivate action: Action;\n\n\tconstructor(action: Action) {\n\t\tthis.action = action;\n\t}\n\n\ttick(entity: GameEntity<any>, delta: number): void {\n\t\tthis.action.tick(entity, delta);\n\t\tif (this.action.done) {\n\t\t\tthis.action.reset();\n\t\t}\n\t}\n\n\treset(): void {\n\t\tthis.done = false;\n\t\tthis.action.reset();\n\t}\n}\n","import { proxy } from 'valtio';\n\n/**\n * Transform state managed by Valtio for batched physics updates.\n * \n * This store accumulates transformation intents during the frame,\n * then applies them all at once after onUpdate() callbacks complete.\n * \n * Design decisions:\n * - Position: Accumulated deltas (additive)\n * - Rotation: Last value wins (replacement)\n * - Velocity: Accumulated deltas (additive)\n * - Angular velocity: Accumulated deltas (additive)\n */\nexport interface TransformState {\n\t/** Position deltas to be applied (accumulated) */\n\tposition: { x: number; y: number; z: number };\n\t\n\t/** Rotation quaternion (last value wins) */\n\trotation: { x: number; y: number; z: number; w: number };\n\t\n\t/** Linear velocity (accumulated) */\n\tvelocity: { x: number; y: number; z: number };\n\t\n\t/** Angular velocity (accumulated) */\n\tangularVelocity: { x: number; y: number; z: number };\n\t\n\t/** Dirty flags to track what needs to be applied */\n\tdirty: {\n\t\tposition: boolean;\n\t\trotation: boolean;\n\t\tvelocity: boolean;\n\t\tangularVelocity: boolean;\n\t};\n}\n\n/**\n * Create a new transform store with optional initial values.\n * The store is a Valtio proxy, making it reactive for debugging/visualization.\n * \n * @param initial Optional initial state values\n * @returns Reactive transform state\n */\nexport function createTransformStore(initial?: Partial<TransformState>): TransformState {\n\tconst defaultState: TransformState = {\n\t\tposition: { x: 0, y: 0, z: 0 },\n\t\trotation: { x: 0, y: 0, z: 0, w: 1 },\n\t\tvelocity: { x: 0, y: 0, z: 0 },\n\t\tangularVelocity: { x: 0, y: 0, z: 0 },\n\t\tdirty: {\n\t\t\tposition: false,\n\t\t\trotation: false,\n\t\t\tvelocity: false,\n\t\t\tangularVelocity: false,\n\t\t},\n\t};\n\n\treturn proxy({\n\t\t...defaultState,\n\t\t...initial,\n\t\t// Ensure dirty flags are properly initialized even if partial initial state\n\t\tdirty: {\n\t\t\t...defaultState.dirty,\n\t\t\t...initial?.dirty,\n\t\t},\n\t});\n}\n\n/**\n * Reset a transform store to its initial clean state.\n * Called after applying changes to prepare for the next frame.\n * \n * @param store The transform store to reset\n */\nexport function resetTransformStore(store: TransformState): void {\n\t// Reset position deltas\n\tstore.position.x = 0;\n\tstore.position.y = 0;\n\tstore.position.z = 0;\n\n\t// Reset rotation to identity quaternion\n\tstore.rotation.x = 0;\n\tstore.rotation.y = 0;\n\tstore.rotation.z = 0;\n\tstore.rotation.w = 1;\n\n\t// Reset velocity\n\tstore.velocity.x = 0;\n\tstore.velocity.y = 0;\n\tstore.velocity.z = 0;\n\n\t// Reset angular velocity\n\tstore.angularVelocity.x = 0;\n\tstore.angularVelocity.y = 0;\n\tstore.angularVelocity.z = 0;\n\n\t// Clear all dirty flags\n\tstore.dirty.position = false;\n\tstore.dirty.rotation = false;\n\tstore.dirty.velocity = false;\n\tstore.dirty.angularVelocity = false;\n}\n","import { RigidBody } from '@dimforge/rapier3d-compat';\nimport { TransformState } from './transform-store';\n\n/**\n * Entity that can have transformations applied from a store\n */\nexport interface TransformableEntity {\n\tbody: RigidBody | null;\n\ttransformStore?: TransformState;\n}\n\n/**\n * Apply accumulated transformations from the store to the physics body.\n * \n * This is called automatically after onUpdate() callbacks complete,\n * flushing all pending transformations to the physics engine in a single batch.\n * \n * Flow:\n * 1. Check dirty flags to see what changed\n * 2. Apply changes to RigidBody\n * 3. Reset store for next frame\n * \n * @param entity Entity with physics body and transform store\n * @param store Transform store containing pending changes\n */\nexport function applyTransformChanges(\n\tentity: TransformableEntity,\n\tstore: TransformState\n): void {\n\tif (!entity.body) return;\n\n\t// Apply velocity if dirty\n\tif (store.dirty.velocity) {\n\t\tentity.body.setLinvel(store.velocity, true);\n\t}\n\n\t// Apply rotation if dirty\n\tif (store.dirty.rotation) {\n\t\tentity.body.setRotation(store.rotation, true);\n\t}\n\n\t// Apply angular velocity if dirty\n\tif (store.dirty.angularVelocity) {\n\t\tentity.body.setAngvel(store.angularVelocity, true);\n\t}\n\n\t// Apply position deltas if dirty\n\tif (store.dirty.position) {\n\t\tconst current = entity.body.translation();\n\t\tentity.body.setTranslation(\n\t\t\t{\n\t\t\t\tx: current.x + store.position.x,\n\t\t\t\ty: current.y + store.position.y,\n\t\t\t\tz: current.z + store.position.z,\n\t\t\t},\n\t\t\ttrue\n\t\t);\n\t}\n}\n","import { Vector3 } from 'three';\nimport { RigidBody, Vector } from '@dimforge/rapier3d-compat';\nimport type { TransformState } from './transform-store';\nimport { createTransformStore } from './transform-store';\n\nexport interface EntityWithBody {\n\tbody: RigidBody | null;\n\ttransformStore?: TransformState;\n}\n\n/**\n * Move an entity along the X axis, preserving other velocities.\n */\nexport function moveX(entity: EntityWithBody, delta: number): void {\n\tif (!entity.transformStore) return;\n\tentity.transformStore.velocity.x = delta;\n\tentity.transformStore.dirty.velocity = true;\n}\n\n/**\n * Move an entity along the Y axis, preserving other velocities.\n */\nexport function moveY(entity: EntityWithBody, delta: number): void {\n\tif (!entity.transformStore) return;\n\tentity.transformStore.velocity.y = delta;\n\tentity.transformStore.dirty.velocity = true;\n}\n\n/**\n * Move an entity along the Z axis, preserving other velocities.\n */\nexport function moveZ(entity: EntityWithBody, delta: number): void {\n\tif (!entity.transformStore) return;\n\tentity.transformStore.velocity.z = delta;\n\tentity.transformStore.dirty.velocity = true;\n}\n\n/**\n * Move an entity along the X and Y axis, preserving Z velocity.\n */\nexport function moveXY(entity: EntityWithBody, deltaX: number, deltaY: number): void {\n\tif (!entity.transformStore) return;\n\tentity.transformStore.velocity.x = deltaX;\n\tentity.transformStore.velocity.y = deltaY;\n\tentity.transformStore.dirty.velocity = true;\n}\n\n/**\n * Move an entity along the X and Z axis, preserving Y velocity.\n */\nexport function moveXZ(entity: EntityWithBody, deltaX: number, deltaZ: number): void {\n\tif (!entity.transformStore) return;\n\tentity.transformStore.velocity.x = deltaX;\n\tentity.transformStore.velocity.z = deltaZ;\n\tentity.transformStore.dirty.velocity = true;\n}\n\n/**\n * Move entity based on a vector, adding to existing velocities.\n */\nexport function move(entity: EntityWithBody, vector: Vector3): void {\n\tif (!entity.transformStore) return;\n\tentity.transformStore.velocity.x += vector.x;\n\tentity.transformStore.velocity.y += vector.y;\n\tentity.transformStore.velocity.z += vector.z;\n\tentity.transformStore.dirty.velocity = true;\n}\n\n/**\n * Reset entity velocity\n */\nexport function resetVelocity(entity: EntityWithBody): void {\n\tif (!entity.body) return;\n\tentity.body.setLinvel(new Vector3(0, 0, 0), true);\n\tentity.body.setLinearDamping(5);\n}\n\n/**\n * Move entity forward in 2D space, preserving Z velocity\n */\nexport function moveForwardXY(entity: EntityWithBody, delta: number, rotation2DAngle: number): void {\n\tconst deltaX = Math.sin(-rotation2DAngle) * delta;\n\tconst deltaY = Math.cos(-rotation2DAngle) * delta;\n\tmoveXY(entity, deltaX, deltaY);\n}\n\n/**\n * Get entity position\n */\nexport function getPosition(entity: EntityWithBody): Vector | null {\n\tif (!entity.body) return null;\n\treturn entity.body.translation();\n}\n\n/**\n * Get entity velocity\n */\nexport function getVelocity(entity: EntityWithBody): Vector | null {\n\tif (!entity.body) return null;\n\treturn entity.body.linvel();\n}\n\n/**\n * Set entity position\n */\nexport function setPosition(entity: EntityWithBody, x: number, y: number, z: number): void {\n\tif (!entity.body) return;\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Set entity X position\n */\nexport function setPositionX(entity: EntityWithBody, x: number): void {\n\tif (!entity.body) return;\n\tconst { y, z } = entity.body.translation();\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Set entity Y position\n */\nexport function setPositionY(entity: EntityWithBody, y: number): void {\n\tif (!entity.body) return;\n\tconst { x, z } = entity.body.translation();\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Set entity Z position\n */\nexport function setPositionZ(entity: EntityWithBody, z: number): void {\n\tif (!entity.body) return;\n\tconst { x, y } = entity.body.translation();\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Wrap entity around 2D bounds\n */\nexport function wrapAroundXY(entity: EntityWithBody, boundsX: number, boundsY: number): void {\n\tconst position = getPosition(entity);\n\tif (!position) return;\n\n\tconst { x, y } = position;\n\tconst newX = x > boundsX ? -boundsX : (x < -boundsX ? boundsX : x);\n\tconst newY = y > boundsY ? -boundsY : (y < -boundsY ? boundsY : y);\n\n\tif (newX !== x || newY !== y) {\n\t\tsetPosition(entity, newX, newY, 0);\n\t}\n}\n\n/**\n * Wrap entity around 3D bounds\n */\nexport function wrapAround3D(entity: EntityWithBody, boundsX: number, boundsY: number, boundsZ: number): void {\n\tconst position = getPosition(entity);\n\tif (!position) return;\n\n\tconst { x, y, z } = position;\n\tconst newX = x > boundsX ? -boundsX : (x < -boundsX ? boundsX : x);\n\tconst newY = y > boundsY ? -boundsY : (y < -boundsY ? boundsY : y);\n\tconst newZ = z > boundsZ ? -boundsZ : (z < -boundsZ ? boundsZ : z);\n\n\tif (newX !== x || newY !== y || newZ !== z) {\n\t\tsetPosition(entity, newX, newY, newZ);\n\t}\n}\n\n/**\n * Enhanced moveable entity with bound methods\n */\nexport interface MoveableEntity extends EntityWithBody {\n\tmoveX(delta: number): void;\n\tmoveY(delta: number): void;\n\tmoveZ(delta: number): void;\n\tmoveXY(deltaX: number, deltaY: number): void;\n\tmoveXZ(deltaX: number, deltaZ: number): void;\n\tmove(vector: Vector3): void;\n\tresetVelocity(): void;\n\tmoveForwardXY(delta: number, rotation2DAngle: number): void;\n\tgetPosition(): Vector | null;\n\tgetVelocity(): Vector | null;\n\tsetPosition(x: number, y: number, z: number): void;\n\tsetPositionX(x: number): void;\n\tsetPositionY(y: number): void;\n\tsetPositionZ(z: number): void;\n\twrapAroundXY(boundsX: number, boundsY: number): void;\n\twrapAround3D(boundsX: number, boundsY: number, boundsZ: number): void;\n}\n\n/**\n * Enhance an entity with additive movement methods.\n * Automatically creates a transform store if one doesn't exist.\n */\nexport function makeMoveable<T extends EntityWithBody>(entity: T): T & MoveableEntity {\n\tconst moveable = entity as T & MoveableEntity;\n\n\t// Create transform store if it doesn't exist\n\tif (!moveable.transformStore) {\n\t\tmoveable.transformStore = createTransformStore();\n\t}\n\n\tmoveable.moveX = (delta: number) => moveX(entity, delta);\n\tmoveable.moveY = (delta: number) => moveY(entity, delta);\n\tmoveable.moveZ = (delta: number) => moveZ(entity, delta);\n\tmoveable.moveXY = (deltaX: number, deltaY: number) => moveXY(entity, deltaX, deltaY);\n\tmoveable.moveXZ = (deltaX: number, deltaZ: number) => moveXZ(entity, deltaX, deltaZ);\n\tmoveable.move = (vector: Vector3) => move(entity, vector);\n\tmoveable.resetVelocity = () => resetVelocity(entity);\n\tmoveable.moveForwardXY = (delta: number, rotation2DAngle: number) => moveForwardXY(entity, delta, rotation2DAngle);\n\tmoveable.getPosition = () => getPosition(entity);\n\tmoveable.getVelocity = () => getVelocity(entity);\n\tmoveable.setPosition = (x: number, y: number, z: number) => setPosition(entity, x, y, z);\n\tmoveable.setPositionX = (x: number) => setPositionX(entity, x);\n\tmoveable.setPositionY = (y: number) => setPositionY(entity, y);\n\tmoveable.setPositionZ = (z: number) => setPositionZ(entity, z);\n\tmoveable.wrapAroundXY = (boundsX: number, boundsY: number) => wrapAroundXY(entity, boundsX, boundsY);\n\tmoveable.wrapAround3D = (boundsX: number, boundsY: number, boundsZ: number) => wrapAround3D(entity, boundsX, boundsY, boundsZ);\n\n\treturn moveable;\n}","import { Euler, Vector3, MathUtils, Quaternion } from 'three';\nimport { RigidBody } from '@dimforge/rapier3d-compat';\nimport type { TransformState } from './transform-store';\nimport { createTransformStore } from './transform-store';\n\nexport interface RotatableEntity {\n\tbody: RigidBody | null;\n\tgroup: any;\n\ttransformStore?: TransformState;\n}\n\n/**\n * Rotate an entity in the direction of a movement vector\n */\nexport function rotateInDirection(entity: RotatableEntity, moveVector: Vector3): void {\n\tif (!entity.body) return;\n\tconst rotate = Math.atan2(-moveVector.x, moveVector.z);\n\trotateYEuler(entity, rotate);\n}\n\n/**\n * Rotate an entity around the Y axis using Euler angles\n */\nexport function rotateYEuler(entity: RotatableEntity, amount: number): void {\n\trotateEuler(entity, new Vector3(0, -amount, 0));\n}\n\n/**\n * Rotate an entity using Euler angles\n */\nexport function rotateEuler(entity: RotatableEntity, rotation: Vector3): void {\n\tif (!entity.group) return;\n\tconst euler = new Euler(rotation.x, rotation.y, rotation.z);\n\tentity.group.setRotationFromEuler(euler);\n}\n\n/**\n * Rotate an entity around the Y axis.\n */\nexport function rotateY(entity: RotatableEntity, delta: number): void {\n\tif (!entity.transformStore) return;\n\t\n\t// Create delta rotation quaternion\n\tconst halfAngle = delta / 2;\n\tconst deltaW = Math.cos(halfAngle);\n\tconst deltaY = Math.sin(halfAngle);\n\t\n\t// Get current rotation from store\n\tconst q = entity.transformStore.rotation;\n\t\n\t// Multiply quaternions: q_new = q_current * q_delta\n\t// For Y-axis rotation: q_delta = (0, deltaY, 0, deltaW)\n\tconst newW = q.w * deltaW - q.y * deltaY;\n\tconst newX = q.x * deltaW + q.z * deltaY;\n\tconst newY = q.y * deltaW + q.w * deltaY;\n\tconst newZ = q.z * deltaW - q.x * deltaY;\n\t\n\tentity.transformStore.rotation.w = newW;\n\tentity.transformStore.rotation.x = newX;\n\tentity.transformStore.rotation.y = newY;\n\tentity.transformStore.rotation.z = newZ;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Rotate an entity around the X axis.\n */\nexport function rotateX(entity: RotatableEntity, delta: number): void {\n\tif (!entity.transformStore) return;\n\t\n\t// Create delta rotation quaternion\n\tconst halfAngle = delta / 2;\n\tconst deltaW = Math.cos(halfAngle);\n\tconst deltaX = Math.sin(halfAngle);\n\t\n\t// Get current rotation from store\n\tconst q = entity.transformStore.rotation;\n\t\n\t// Multiply quaternions: q_new = q_current * q_delta\n\t// For X-axis rotation: q_delta = (deltaX, 0, 0, deltaW)\n\tconst newW = q.w * deltaW - q.x * deltaX;\n\tconst newX = q.x * deltaW + q.w * deltaX;\n\tconst newY = q.y * deltaW + q.z * deltaX;\n\tconst newZ = q.z * deltaW - q.y * deltaX;\n\t\n\tentity.transformStore.rotation.w = newW;\n\tentity.transformStore.rotation.x = newX;\n\tentity.transformStore.rotation.y = newY;\n\tentity.transformStore.rotation.z = newZ;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Rotate an entity around the Z axis.\n */\nexport function rotateZ(entity: RotatableEntity, delta: number): void {\n\tif (!entity.transformStore) return;\n\t\n\t// Create delta rotation quaternion\n\tconst halfAngle = delta / 2;\n\tconst deltaW = Math.cos(halfAngle);\n\tconst deltaZ = Math.sin(halfAngle);\n\t\n\t// Get current rotation from store\n\tconst q = entity.transformStore.rotation;\n\t\n\t// Multiply quaternions: q_new = q_current * q_delta\n\t// For Z-axis rotation: q_delta = (0, 0, deltaZ, deltaW)\n\tconst newW = q.w * deltaW - q.z * deltaZ;\n\tconst newX = q.x * deltaW - q.y * deltaZ;\n\tconst newY = q.y * deltaW + q.x * deltaZ;\n\tconst newZ = q.z * deltaW + q.w * deltaZ;\n\t\n\tentity.transformStore.rotation.w = newW;\n\tentity.transformStore.rotation.x = newX;\n\tentity.transformStore.rotation.y = newY;\n\tentity.transformStore.rotation.z = newZ;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Set rotation around Y axis.\n */\nexport function setRotationY(entity: RotatableEntity, y: number): void {\n\tif (!entity.transformStore) return;\n\tconst halfAngle = y / 2;\n\tconst w = Math.cos(halfAngle);\n\tconst yComponent = Math.sin(halfAngle);\n\tentity.transformStore.rotation.w = w;\n\tentity.transformStore.rotation.x = 0;\n\tentity.transformStore.rotation.y = yComponent;\n\tentity.transformStore.rotation.z = 0;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Set rotation around Y axis\n */\nexport function setRotationDegreesY(entity: RotatableEntity, y: number): void {\n\tif (!entity.body) return;\n\tsetRotationY(entity, MathUtils.degToRad(y));\n}\n\n/**\n * Set rotation around X axis.\n */\nexport function setRotationX(entity: RotatableEntity, x: number): void {\n\tif (!entity.transformStore) return;\n\tconst halfAngle = x / 2;\n\tconst w = Math.cos(halfAngle);\n\tconst xComponent = Math.sin(halfAngle);\n\tentity.transformStore.rotation.w = w;\n\tentity.transformStore.rotation.x = xComponent;\n\tentity.transformStore.rotation.y = 0;\n\tentity.transformStore.rotation.z = 0;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Set rotation around X axis\n */\nexport function setRotationDegreesX(entity: RotatableEntity, x: number): void {\n\tif (!entity.body) return;\n\tsetRotationX(entity, MathUtils.degToRad(x));\n}\n\n/**\n * Set rotation around Z axis.\n */\nexport function setRotationZ(entity: RotatableEntity, z: number): void {\n\tif (!entity.transformStore) return;\n\tconst halfAngle = z / 2;\n\tconst w = Math.cos(halfAngle);\n\tconst zComponent = Math.sin(halfAngle);\n\tentity.transformStore.rotation.w = w;\n\tentity.transformStore.rotation.x = 0;\n\tentity.transformStore.rotation.y = 0;\n\tentity.transformStore.rotation.z = zComponent;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Set rotation around Z axis\n */\nexport function setRotationDegreesZ(entity: RotatableEntity, z: number): void {\n\tif (!entity.body) return;\n\tsetRotationZ(entity, MathUtils.degToRad(z));\n}\n\n/**\n * Set rotation for all axes.\n */\nexport function setRotation(entity: RotatableEntity, x: number, y: number, z: number): void {\n\tif (!entity.transformStore) return;\n\tconst quat = new Quaternion().setFromEuler(new Euler(x, y, z));\n\tentity.transformStore.rotation.w = quat.w;\n\tentity.transformStore.rotation.x = quat.x;\n\tentity.transformStore.rotation.y = quat.y;\n\tentity.transformStore.rotation.z = quat.z;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Set rotation for all axes\n */\nexport function setRotationDegrees(entity: RotatableEntity, x: number, y: number, z: number): void {\n\tif (!entity.body) return;\n\tsetRotation(entity, MathUtils.degToRad(x), MathUtils.degToRad(y), MathUtils.degToRad(z));\n}\n\n/**\n * Get current rotation\n */\nexport function getRotation(entity: RotatableEntity): any {\n\tif (!entity.body) return null;\n\treturn entity.body.rotation();\n}\n\n/**\n * Rotatable entity API with bound methods\n */\nexport interface RotatableEntityAPI extends RotatableEntity {\n\trotateInDirection(moveVector: Vector3): void;\n\trotateYEuler(amount: number): void;\n\trotateEuler(rotation: Vector3): void;\n\trotateY(delta: number): void;\n\trotateX(delta: number): void;\n\trotateZ(delta: number): void;\n\tsetRotationY(y: number): void;\n\tsetRotationX(x: number): void;\n\tsetRotationZ(z: number): void;\n\tsetRotationDegrees(x: number, y: number, z: number): void;\n\tsetRotationDegreesY(y: number): void;\n\tsetRotationDegreesX(x: number): void;\n\tsetRotationDegreesZ(z: number): void;\n\tsetRotation(x: number, y: number, z: number): void;\n\tgetRotation(): any;\n}\n\n/**\n * Enhance an entity instance with rotatable methods.\n * Automatically creates a transform store if one doesn't exist.\n */\nexport function makeRotatable<T extends RotatableEntity>(entity: T): T & RotatableEntityAPI {\n\tconst rotatableEntity = entity as T & RotatableEntityAPI;\n\n\t// Create transform store if it doesn't exist\n\tif (!rotatableEntity.transformStore) {\n\t\trotatableEntity.transformStore = createTransformStore();\n\t}\n\n\trotatableEntity.rotateInDirection = (moveVector: Vector3) => rotateInDirection(entity, moveVector);\n\trotatableEntity.rotateYEuler = (amount: number) => rotateYEuler(entity, amount);\n\trotatableEntity.rotateEuler = (rotation: Vector3) => rotateEuler(entity, rotation);\n\trotatableEntity.rotateX = (delta: number) => rotateX(entity, delta);\n\trotatableEntity.rotateY = (delta: number) => rotateY(entity, delta);\n\trotatableEntity.rotateZ = (delta: number) => rotateZ(entity, delta);\n\trotatableEntity.setRotationY = (y: number) => setRotationY(entity, y);\n\trotatableEntity.setRotationX = (x: number) => setRotationX(entity, x);\n\trotatableEntity.setRotationZ = (z: number) => setRotationZ(entity, z);\n\trotatableEntity.setRotationDegreesY = (y: number) => setRotationDegreesY(entity, y);\n\trotatableEntity.setRotationDegreesX = (x: number) => setRotationDegreesX(entity, x);\n\trotatableEntity.setRotationDegreesZ = (z: number) => setRotationDegreesZ(entity, z);\n\trotatableEntity.setRotationDegrees = (x: number, y: number, z: number) => setRotationDegrees(entity, x, y, z);\n\trotatableEntity.setRotation = (x: number, y: number, z: number) => setRotation(entity, x, y, z);\n\trotatableEntity.getRotation = () => getRotation(entity);\n\n\treturn rotatableEntity;\n}","import { UpdateContext } from \"../core/base-node-life-cycle\";\n\n/**\n * Listen for a single global key change inside an onUpdate pipeline.\n * Usage: onUpdate(globalChange('p1Score', (value) => { ... }))\n */\nexport function globalChange<T = any>(\n\tkey: string,\n\tcallback: (value: T, ctx: UpdateContext<any>) => void\n) {\n\tlet previousValue: T | undefined = undefined;\n\treturn (ctx: UpdateContext<any>) => {\n\t\tconst currentValue = ctx.globals?.[key] as T;\n\t\tif (previousValue !== currentValue) {\n\t\t\t// Ignore the very first undefined->value transition only if both are undefined\n\t\t\tif (!(previousValue === undefined && currentValue === undefined)) {\n\t\t\t\tcallback(currentValue, ctx);\n\t\t\t}\n\t\t\tpreviousValue = currentValue;\n\t\t}\n\t};\n}\n\n/**\n * Listen for multiple global key changes inside an onUpdate pipeline.\n * Calls back when any of the provided keys changes.\n * Usage: onUpdate(globalChanges(['p1Score','p2Score'], ([p1,p2]) => { ... }))\n */\nexport function globalChanges<T = any>(\n\tkeys: string[],\n\tcallback: (values: T[], ctx: UpdateContext<any>) => void\n) {\n\tlet previousValues: (T | undefined)[] = new Array(keys.length).fill(undefined);\n\treturn (ctx: UpdateContext<any>) => {\n\t\tconst currentValues = keys.map((k) => ctx.globals?.[k] as T);\n\t\tconst hasAnyChange = currentValues.some((val, idx) => previousValues[idx] !== val);\n\t\tif (hasAnyChange) {\n\t\t\t// Ignore initial all-undefined state\n\t\t\tconst allPrevUndef = previousValues.every((v) => v === undefined);\n\t\t\tconst allCurrUndef = currentValues.every((v) => v === undefined);\n\t\t\tif (!(allPrevUndef && allCurrUndef)) {\n\t\t\t\tcallback(currentValues as T[], ctx);\n\t\t\t}\n\t\t\tpreviousValues = currentValues;\n\t\t}\n\t};\n}\n\n\n/**\n * Listen for a single stage variable change inside an onUpdate pipeline.\n * Usage: onUpdate(variableChange('score', (value, ctx) => { ... }))\n */\nexport function variableChange<T = any>(\n\tkey: string,\n\tcallback: (value: T, ctx: UpdateContext<any>) => void\n) {\n\tlet previousValue: T | undefined = undefined;\n\treturn (ctx: UpdateContext<any>) => {\n\t\t// @ts-ignore - stage is optional on UpdateContext\n\t\tconst currentValue = (ctx.stage?.getVariable?.(key) ?? undefined) as T;\n\t\tif (previousValue !== currentValue) {\n\t\t\tif (!(previousValue === undefined && currentValue === undefined)) {\n\t\t\t\tcallback(currentValue, ctx);\n\t\t\t}\n\t\t\tpreviousValue = currentValue;\n\t\t}\n\t};\n}\n\n/**\n * Listen for multiple stage variable changes; fires when any changes.\n * Usage: onUpdate(variableChanges(['a','b'], ([a,b], ctx) => { ... }))\n */\nexport function variableChanges<T = any>(\n\tkeys: string[],\n\tcallback: (values: T[], ctx: UpdateContext<any>) => void\n) {\n\tlet previousValues: (T | undefined)[] = new Array(keys.length).fill(undefined);\n\treturn (ctx: UpdateContext<any>) => {\n\t\t// @ts-ignore - stage is optional on UpdateContext\n\t\tconst reader = (k: string) => ctx.stage?.getVariable?.(k) as T;\n\t\tconst currentValues = keys.map(reader);\n\t\tconst hasAnyChange = currentValues.some((val, idx) => previousValues[idx] !== val);\n\t\tif (hasAnyChange) {\n\t\t\tconst allPrevUndef = previousValues.every((v) => v === undefined);\n\t\t\tconst allCurrUndef = currentValues.every((v) => v === undefined);\n\t\t\tif (!(allPrevUndef && allCurrUndef)) {\n\t\t\t\tcallback(currentValues as T[], ctx);\n\t\t\t}\n\t\t\tpreviousValues = currentValues;\n\t\t}\n\t};\n}\n\n\n"],"mappings":"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","names":["Vector3","Vector3"]}
@@ -0,0 +1,296 @@
1
+ import { StateMachine } from 'typescript-fsm';
2
+ import { b as BehaviorDescriptor } from '../behavior-descriptor-BWNWmIjv.js';
3
+ import 'bitecs';
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
+ }
33
+ declare function createPlatformer3DMovementComponent(options?: Partial<Platformer3DMovementComponent>): Platformer3DMovementComponent;
34
+ interface Platformer3DInputComponent {
35
+ /** Horizontal movement input (-1 to 1) */
36
+ moveX: number;
37
+ /** Forward/backward movement input (-1 to 1) */
38
+ moveZ: number;
39
+ /** Jump button pressed */
40
+ jump: boolean;
41
+ /** Run/sprint button held */
42
+ run: boolean;
43
+ }
44
+ declare function createPlatformer3DInputComponent(): Platformer3DInputComponent;
45
+ interface Platformer3DStateComponent {
46
+ /** Is the entity on the ground */
47
+ grounded: boolean;
48
+ /** Is currently in a jump arc */
49
+ jumping: boolean;
50
+ /** Is falling (not jumping) */
51
+ falling: boolean;
52
+ /** Current jump count (for multi-jump) */
53
+ jumpCount: number;
54
+ /** Y position when jump started */
55
+ jumpStartHeight: number;
56
+ /** Current movement speed being applied */
57
+ currentSpeed: number;
58
+ /** Last known ground Y position */
59
+ lastGroundedY: number;
60
+ /** Was jump button pressed last frame (for edge detection) */
61
+ jumpPressedLastFrame: boolean;
62
+ /** Is currently colliding with ground (from physics collision callback) */
63
+ collisionGrounded: boolean;
64
+ /** Timestamp of last ground collision */
65
+ groundedCollisionTime: number;
66
+ /** Time in seconds since last grounded */
67
+ timeSinceGrounded: number;
68
+ /** Is a jump allowed due to buffer? */
69
+ jumpBuffered: boolean;
70
+ /** Time remaining in jump buffer */
71
+ jumpBufferTimer: number;
72
+ /** Is jump button currently held */
73
+ jumpHeld: boolean;
74
+ /** Has the jump cut been applied for this jump? */
75
+ jumpCutApplied: boolean;
76
+ /** Has jump button been released since last jump (required for multi-jump) */
77
+ jumpReleasedSinceLastJump: boolean;
78
+ /** Time since current jump started (for multi-jump window) */
79
+ timeSinceJump: number;
80
+ }
81
+ declare function createPlatformer3DStateComponent(): Platformer3DStateComponent;
82
+
83
+ /**
84
+ * Platformer 3D Finite State Machine
85
+ *
86
+ * Manages state transitions for 3D platformer movement:
87
+ * - Idle: Standing still on ground
88
+ * - Walking: Moving on ground (slow)
89
+ * - Running: Moving on ground (fast)
90
+ * - Jumping: Ascending from jump
91
+ * - Falling: Descending (gravity)
92
+ * - Landing: Just touched ground
93
+ */
94
+
95
+ /**
96
+ * Simplified Collision Context interface
97
+ */
98
+ interface PlatformerCollisionContext {
99
+ contact: {
100
+ normal: {
101
+ x: number;
102
+ y: number;
103
+ z?: number;
104
+ };
105
+ };
106
+ }
107
+ /**
108
+ * Platformer states
109
+ */
110
+ declare enum Platformer3DState {
111
+ Idle = "idle",
112
+ Walking = "walking",
113
+ Running = "running",
114
+ Jumping = "jumping",
115
+ Falling = "falling",
116
+ Landing = "landing"
117
+ }
118
+ /**
119
+ * Events that trigger state transitions
120
+ */
121
+ declare enum Platformer3DEvent {
122
+ Walk = "walk",
123
+ Run = "run",
124
+ Jump = "jump",
125
+ Fall = "fall",
126
+ Land = "land",
127
+ Stop = "stop"
128
+ }
129
+ /**
130
+ * Context for the FSM
131
+ */
132
+ interface Platformer3DContext {
133
+ input: Platformer3DInputComponent;
134
+ state: Platformer3DStateComponent;
135
+ }
136
+ /**
137
+ * Platformer 3D FSM
138
+ */
139
+ declare class Platformer3DFSM {
140
+ private ctx;
141
+ machine: StateMachine<Platformer3DState, Platformer3DEvent, never>;
142
+ constructor(ctx: Platformer3DContext);
143
+ /**
144
+ * Get the current state
145
+ */
146
+ getState(): Platformer3DState;
147
+ /**
148
+ * Dispatch an event to the FSM
149
+ */
150
+ dispatch(event: Platformer3DEvent): void;
151
+ /**
152
+ * Check if grounded
153
+ */
154
+ isGrounded(): boolean;
155
+ /**
156
+ * Get current jump count from context
157
+ */
158
+ getJumpCount(): number;
159
+ /**
160
+ * Handle collision event to update ground state
161
+ */
162
+ handleCollision(ctx: PlatformerCollisionContext): void;
163
+ /**
164
+ * Update FSM based on current state
165
+ */
166
+ update(input: Platformer3DInputComponent, state: Platformer3DStateComponent): void;
167
+ }
168
+
169
+ /**
170
+ * Platformer 3D Behavior System
171
+ *
172
+ * Handles 3D platformer physics including:
173
+ * - Ground detection via raycasting
174
+ * - Horizontal movement (walk/run)
175
+ * - Jumping with multi-jump support
176
+ * - Gravity application
177
+ * - State synchronization with FSM
178
+ */
179
+
180
+ /**
181
+ * Entity with platformer components
182
+ */
183
+ interface Platformer3DEntity {
184
+ uuid: string;
185
+ body: any;
186
+ platformer: Platformer3DMovementComponent;
187
+ $platformer: Platformer3DInputComponent;
188
+ platformerState: Platformer3DStateComponent;
189
+ transformStore?: any;
190
+ }
191
+ /**
192
+ * Platformer 3D Movement Behavior
193
+ *
194
+ * Core physics system for 3D platformer movement
195
+ */
196
+ declare class Platformer3DBehavior$1 {
197
+ private world;
198
+ private scene;
199
+ private rays;
200
+ private debugLines;
201
+ constructor(world: any, scene: any);
202
+ /**
203
+ * Detect if entity is on the ground using raycasting
204
+ */
205
+ /**
206
+ * Detect if entity is on the ground using raycasting (multi-sample: center + 4 corners)
207
+ */
208
+ private detectGround;
209
+ private updateDebugLines;
210
+ /**
211
+ * Apply horizontal movement based on input
212
+ */
213
+ private applyMovement;
214
+ /**
215
+ * Handle jump logic with multi-jump support
216
+ */
217
+ /**
218
+ * Handle jump logic with multi-jump, coyote time, and buffering
219
+ */
220
+ private handleJump;
221
+ /**
222
+ * Apply gravity when not grounded
223
+ */
224
+ private applyGravity;
225
+ /**
226
+ * Update entity state based on physics
227
+ */
228
+ private updateState;
229
+ /**
230
+ * Update all platformer entities
231
+ */
232
+ update(delta: number): void;
233
+ /**
234
+ * Cleanup
235
+ */
236
+ destroy(): void;
237
+ }
238
+
239
+ /**
240
+ * Platformer behavior options (typed for entity.use() autocomplete)
241
+ */
242
+ interface Platformer3DBehaviorOptions {
243
+ /** Base walking speed (default: 12) */
244
+ walkSpeed?: number;
245
+ /** Sprint/run speed (default: 24) */
246
+ runSpeed?: number;
247
+ /** Initial jump force (default: 12) */
248
+ jumpForce?: number;
249
+ /** Maximum number of jumps (default: 1) */
250
+ maxJumps?: number;
251
+ /** Gravity force (default: 9.82) */
252
+ gravity?: number;
253
+ /** Ray length for ground detection (default: 1.0) */
254
+ groundRayLength?: number;
255
+ }
256
+ /**
257
+ * Platformer3DBehavior - typed descriptor for 3D platformer movement
258
+ *
259
+ * Provides complete 3D platformer physics including:
260
+ * - Walking and running
261
+ * - Jumping with multi-jump support
262
+ * - Gravity and falling
263
+ * - Ground detection
264
+ *
265
+ * @example
266
+ * ```typescript
267
+ * import { Platformer3DBehavior } from "@zylem/game-lib";
268
+ *
269
+ * const player = await playgroundActor('player');
270
+ * const platformer = player.use(Platformer3DBehavior, {
271
+ * walkSpeed: 12,
272
+ * runSpeed: 24,
273
+ * jumpForce: 12,
274
+ * maxJumps: 2, // Double jump!
275
+ * });
276
+ *
277
+ * // In update loop
278
+ * player.onUpdate(({ inputs }) => {
279
+ * player.$platformer.moveX = inputs.p1.axes.Horizontal.value;
280
+ * player.$platformer.moveZ = inputs.p1.axes.Vertical.value;
281
+ * player.$platformer.jump = inputs.p1.buttons.A.held > 0;
282
+ * player.$platformer.run = inputs.p1.shoulders.LTrigger.held > 0;
283
+ *
284
+ * const state = platformer.getState();
285
+ * const grounded = platformer.isGrounded();
286
+ * });
287
+ * ```
288
+ */
289
+ declare const Platformer3DBehavior: BehaviorDescriptor<Platformer3DBehaviorOptions, {
290
+ getState: () => Platformer3DState;
291
+ isGrounded: () => boolean;
292
+ getJumpCount: () => number;
293
+ onPlatformCollision: (ctx: PlatformerCollisionContext) => void;
294
+ }, Platformer3DEntity>;
295
+
296
+ 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 };