emeraldengine 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +1498 -1659
  2. package/dist/types/index.d.ts +4 -1
  3. package/dist/types/src/Animator.d.ts +1 -1
  4. package/dist/types/src/CollisionLayers.d.ts +2 -2
  5. package/dist/types/src/Color.d.ts +1 -0
  6. package/dist/types/src/Drawable.d.ts +1 -1
  7. package/dist/types/src/EmeraldDB.d.ts +2 -2
  8. package/dist/types/src/InstancedTexture.d.ts +17 -2
  9. package/dist/types/src/Material.d.ts +2 -2
  10. package/dist/types/src/MathUtils.d.ts +2 -1
  11. package/dist/types/src/ParticleEmitter.d.ts +1 -1
  12. package/dist/types/src/Physics.d.ts +148 -18
  13. package/dist/types/src/Scene.d.ts +1 -1
  14. package/dist/types/src/Shaders.d.ts +2 -2
  15. package/dist/types/src/Tilemap.d.ts +1 -1
  16. package/dist/types/src/UI.d.ts +1 -1
  17. package/dist/types/src/components/Behaviour.d.ts +2 -2
  18. package/dist/types/src/components/Collider.d.ts +7 -1
  19. package/dist/types/src/components/GameObject.d.ts +2 -2
  20. package/dist/types/src/components/PolygonCollider.d.ts +33 -0
  21. package/dist/types/src/components/RigidBody.d.ts +281 -8
  22. package/dist/types/src/importers/Aseprite.d.ts +2 -2
  23. package/dist/types/src/importers/ForgeLevel.d.ts +97 -0
  24. package/dist/types/src/importers/TiledMap.d.ts +1 -1
  25. package/dist/types/src/managers/EventManager.d.ts +1 -1
  26. package/dist/types/src/managers/Gamepad.d.ts +102 -0
  27. package/dist/types/src/managers/InputManager.d.ts +93 -2
  28. package/dist/types/src/managers/NetworkManager.d.ts +2 -2
  29. package/dist/types/src/managers/RenderStats.d.ts +1 -1
  30. package/dist/types/src/managers/TextureManager.d.ts +1 -1
  31. package/dist/types/src/physics/AABB.d.ts +92 -0
  32. package/dist/types/src/physics/Body.d.ts +435 -0
  33. package/dist/types/src/physics/BodyType.d.ts +6 -0
  34. package/dist/types/src/physics/BroadPhase.d.ts +210 -0
  35. package/dist/types/src/physics/Collision.d.ts +102 -0
  36. package/dist/types/src/physics/Contact.d.ts +206 -0
  37. package/dist/types/src/physics/ContactSolver.d.ts +108 -0
  38. package/dist/types/src/physics/Distance.d.ts +54 -0
  39. package/dist/types/src/physics/DistanceJoint.d.ts +90 -0
  40. package/dist/types/src/physics/Fixture.d.ts +221 -0
  41. package/dist/types/src/physics/Island.d.ts +52 -0
  42. package/dist/types/src/physics/Joint.d.ts +59 -0
  43. package/dist/types/src/physics/Math2D.d.ts +371 -0
  44. package/dist/types/src/physics/RevoluteJoint.d.ts +119 -0
  45. package/dist/types/src/physics/Settings.d.ts +22 -0
  46. package/dist/types/src/physics/Shapes.d.ts +207 -0
  47. package/dist/types/src/physics/TimeOfImpact.d.ts +22 -0
  48. package/dist/types/src/physics/World.d.ts +274 -0
  49. package/dist/types/src/physics/index.d.ts +34 -0
  50. package/index.js +6 -0
  51. package/package.json +2 -3
  52. package/src/Animator.js +1 -1
  53. package/src/CollisionLayers.js +3 -3
  54. package/src/Color.js +8 -0
  55. package/src/Drawable.js +1 -1
  56. package/src/Emerald.js +1 -1
  57. package/src/EmeraldDB.js +2 -2
  58. package/src/InstancedTexture.js +57 -9
  59. package/src/Material.js +2 -2
  60. package/src/MathUtils.js +2 -1
  61. package/src/ParticleEmitter.js +1 -1
  62. package/src/Physics.js +270 -60
  63. package/src/Scene.js +1 -1
  64. package/src/Shaders.js +20 -20
  65. package/src/Tilemap.js +1 -1
  66. package/src/UI.js +1 -1
  67. package/src/components/Behaviour.js +2 -2
  68. package/src/components/BoxCollider.js +7 -9
  69. package/src/components/BoxColliderDebug.js +3 -4
  70. package/src/components/CircleCollider.js +7 -9
  71. package/src/components/CircleColliderDebug.js +3 -2
  72. package/src/components/Collider.js +13 -3
  73. package/src/components/GameObject.js +2 -2
  74. package/src/components/PolygonCollider.js +55 -0
  75. package/src/components/RigidBody.js +441 -14
  76. package/src/importers/Aseprite.js +2 -2
  77. package/src/importers/ForgeLevel.js +581 -0
  78. package/src/importers/TiledMap.js +1 -1
  79. package/src/managers/EventManager.js +1 -1
  80. package/src/managers/Gamepad.js +126 -0
  81. package/src/managers/InputManager.js +129 -3
  82. package/src/managers/NetworkManager.js +2 -2
  83. package/src/managers/RenderStats.js +1 -1
  84. package/src/managers/TextureManager.js +1 -1
  85. package/src/physics/AABB.js +207 -0
  86. package/src/physics/Body.js +862 -0
  87. package/src/physics/BodyType.js +16 -0
  88. package/src/physics/BroadPhase.js +641 -0
  89. package/src/physics/Collision.js +534 -0
  90. package/src/physics/Contact.js +500 -0
  91. package/src/physics/ContactSolver.js +526 -0
  92. package/src/physics/Distance.js +403 -0
  93. package/src/physics/DistanceJoint.js +227 -0
  94. package/src/physics/Fixture.js +346 -0
  95. package/src/physics/Island.js +203 -0
  96. package/src/physics/Joint.js +78 -0
  97. package/src/physics/Math2D.js +573 -0
  98. package/src/physics/RevoluteJoint.js +278 -0
  99. package/src/physics/Settings.js +78 -0
  100. package/src/physics/Shapes.js +549 -0
  101. package/src/physics/TimeOfImpact.js +87 -0
  102. package/src/physics/World.js +731 -0
  103. package/src/physics/index.js +79 -0
@@ -40,6 +40,7 @@ import ParticleEmitter from "./src/ParticleEmitter.js";
40
40
  import CollisionLayers from "./src/CollisionLayers.js";
41
41
  import TiledMap from "./src/importers/TiledMap.js";
42
42
  import Aseprite from "./src/importers/Aseprite.js";
43
+ import ForgeLevel from "./src/importers/ForgeLevel.js";
43
44
  import RenderTarget from "./src/RenderTarget.js";
44
45
  import RenderStats from "./src/managers/RenderStats.js";
45
46
  import PostProcessor from "./src/PostProcessor.js";
@@ -49,6 +50,7 @@ import { BloomEffect } from "./src/PostEffects.js";
49
50
  import Material from "./src/Material.js";
50
51
  import UI from "./src/UI.js";
51
52
  import InputManager from "./src/managers/InputManager.js";
53
+ import Gamepad from "./src/managers/Gamepad.js";
52
54
  import Particle from "./src/particlesystem/Particle.js";
53
55
  import Particles from "./src/particlesystem/Particles.js";
54
56
  import ParticleSettings from "./src/particlesystem/ParticleSettings.js";
@@ -65,8 +67,9 @@ import BoxCollider from "./src/components/BoxCollider.js";
65
67
  import BoxColliderDebug from "./src/components/BoxColliderDebug.js";
66
68
  import CircleCollider from "./src/components/CircleCollider.js";
67
69
  import CircleColliderDebug from "./src/components/CircleColliderDebug.js";
70
+ import PolygonCollider from "./src/components/PolygonCollider.js";
68
71
  import Collider from "./src/components/Collider.js";
69
72
  import GameObject from "./src/components/GameObject.js";
70
73
  import RigidBody from "./src/components/RigidBody.js";
71
74
  import Behaviour from "./src/components/Behaviour.js";
72
- export { Emerald, BitmapText, Color, Drawable, FPSCounter, Instance, InstancedTexture, Physics, Vector2, Vector3, Scene, Square2D, Triangle2D, Circle2D, Storage, EmeraldDB, Texture, Time, Transform, MathUtils, Pool, Animator, Tilemap, CameraController, Camera, Easing, Tween, Timer, StateMachine, SpatialGrid, TextureAtlas, CanvasText, DebugOverlay, Serializer, Coroutine, Interpolator, ScreenEffects, SpriteBatch, ParticleEmitter, CollisionLayers, TiledMap, Aseprite, RenderTarget, RenderStats, PostProcessor, PostEffect, PostEffects, BloomEffect, Material, UI, InputManager, Particle, Particles, ParticleSettings, AudioManager, CameraManager, EventManager, SceneManager, TextureManager, AssetManager, NetworkManager, DirectionalLight, PointLight, BoxCollider, BoxColliderDebug, CircleCollider, CircleColliderDebug, Collider, GameObject, RigidBody, Behaviour };
75
+ export { Emerald, BitmapText, Color, Drawable, FPSCounter, Instance, InstancedTexture, Physics, Vector2, Vector3, Scene, Square2D, Triangle2D, Circle2D, Storage, EmeraldDB, Texture, Time, Transform, MathUtils, Pool, Animator, Tilemap, CameraController, Camera, Easing, Tween, Timer, StateMachine, SpatialGrid, TextureAtlas, CanvasText, DebugOverlay, Serializer, Coroutine, Interpolator, ScreenEffects, SpriteBatch, ParticleEmitter, CollisionLayers, TiledMap, Aseprite, ForgeLevel, RenderTarget, RenderStats, PostProcessor, PostEffect, PostEffects, BloomEffect, Material, UI, InputManager, Gamepad, Particle, Particles, ParticleSettings, AudioManager, CameraManager, EventManager, SceneManager, TextureManager, AssetManager, NetworkManager, DirectionalLight, PointLight, BoxCollider, BoxColliderDebug, CircleCollider, CircleColliderDebug, PolygonCollider, Collider, GameObject, RigidBody, Behaviour };
@@ -3,7 +3,7 @@ export default Animator;
3
3
  * @class Animator
4
4
  * @description A component that manages named animation clips for a Texture (or
5
5
  * any Drawable) on the same GameObject. Register clips once, then switch between
6
- * them by name handy for character states like idle/run/jump.
6
+ * them by name, handy for character states like idle/run/jump.
7
7
  *
8
8
  * @example
9
9
  * const anim = new Animator();
@@ -40,13 +40,13 @@ declare namespace CollisionLayers {
40
40
  /**
41
41
  * @class CollisionLayers
42
42
  * @description A small registry that maps human-readable layer names to the
43
- * category bits planck uses for collision filtering, so games can say
43
+ * category bits the physics engine uses for collision filtering, so games can
44
44
  * "players collide with ground and enemies, but not with each other" without
45
45
  * juggling raw bitmasks.
46
46
  *
47
47
  * Two fixtures collide only if each one's category is in the other's mask, so
48
48
  * filtering is symmetric by construction. Up to 16 distinct layers are
49
- * supported (planck filter bits are 16-bit).
49
+ * supported (filter bits are 16-bit).
50
50
  *
51
51
  * @example
52
52
  * CollisionLayers.define("ground", "player", "enemy", "pickup");
@@ -8,6 +8,7 @@ export default Color;
8
8
  * @param {number} a - The alpha value
9
9
  */
10
10
  declare class Color {
11
+ static fromHex(hex: any): Color;
11
12
  constructor(r: any, g: any, b: any, a?: number);
12
13
  r: any;
13
14
  g: any;
@@ -206,7 +206,7 @@ declare class Drawable {
206
206
  * @description Frees this drawable's GPU resources: its vertex/texcoord
207
207
  * buffers and its reference on the shared texture (the GL texture itself is
208
208
  * deleted when the last drawable using it is disposed). Call it when the
209
- * owning object is permanently removed GameObject.destroy() and
209
+ * owning object is permanently removed. GameObject.destroy() and
210
210
  * Scene.remove(obj, { dispose: true }) do it for you. Safe to call twice.
211
211
  */
212
212
  dispose(): void;
@@ -1,7 +1,7 @@
1
1
  export default EmeraldDB;
2
2
  /**
3
3
  * @class EmeraldDB
4
- * @description Async game-save storage on IndexedDB the big-world companion
4
+ * @description Async game-save storage on IndexedDB, the big-world companion
5
5
  * to `Storage` (localStorage). Same versioned-envelope semantics (`{v,t,data}`
6
6
  * with a `.bak` backup and forward migration), but with no ~5MB quota and no
7
7
  * JSON round-trip: values are structured-cloned, so large nested world state
@@ -56,7 +56,7 @@ declare class EmeraldDB {
56
56
  private static _tx;
57
57
  /**
58
58
  * @method set
59
- * @description Stores a value under a key (structured clone objects, Maps,
59
+ * @description Stores a value under a key (structured clone: objects, Maps,
60
60
  * Sets, typed arrays all survive).
61
61
  * @param {string} key
62
62
  * @param {*} value
@@ -28,6 +28,8 @@ declare class InstancedTexture extends Drawable {
28
28
  static: boolean;
29
29
  /** @private */
30
30
  private _matricesDirty;
31
+ /** The animation every instance starts with; set by playAnimation/playAnimationOnce. @private */
32
+ private _defaultAnimation;
31
33
  /**
32
34
  * @method setStatic
33
35
  * @description Toggles static mode (see constructor notes).
@@ -257,11 +259,24 @@ declare class InstancedTexture extends Drawable {
257
259
  handleInstanceHover(event: Event, x: number, y: number, lastHoveredInstance: Instance): Instance;
258
260
  /**
259
261
  * @method playAnimationOnce
260
- * @description Plays an animation once
262
+ * @description Plays the same animation once, in lockstep, on every
263
+ * instance, then holds each on its last frame: the current instances
264
+ * immediately, and any added later via {@link InstancedTexture#addInstance}.
261
265
  * @param {Array} frames - The frames to play
262
- * @param {number} speed - The speed of the animation
266
+ * @param {number} [speed=1000] - Milliseconds per frame
263
267
  */
264
268
  playAnimationOnce(frames: any[], speed?: number): void;
269
+ /**
270
+ * @method stopAnimation
271
+ * @description Stops the shared animation started by playAnimation/
272
+ * playAnimationOnce on every current instance, and clears it so instances
273
+ * added afterwards no longer start playing it either. Instances animated
274
+ * individually via {@link InstancedTexture#animateInstance} are unaffected
275
+ * unless you stop them the same way, through {@link InstancedTexture#stopInstanceAnimation}.
276
+ * @param {boolean} [revertToOriginal=false] - Whether to reset each
277
+ * instance back to the frame it had before playAnimation was called
278
+ */
279
+ stopAnimation(revertToOriginal?: boolean): void;
265
280
  }
266
281
  import Drawable from "./Drawable.js";
267
282
  import Instance from "./Instance.js";
@@ -4,7 +4,7 @@ export default Material;
4
4
  * @description A custom shader for a Drawable. By default it reuses the engine's
5
5
  * standard vertex shader (so transforms, the camera, and instancing keep
6
6
  * working) and only overrides the fragment program. Pass `options.vertex` to
7
- * also supply a custom VERTEX program the escape hatch for effects the fixed
7
+ * also supply a custom VERTEX program: the escape hatch for effects the fixed
8
8
  * pipeline can't express (perspective tilt, vertex waves, billboarding, ...).
9
9
  *
10
10
  * The fragment shader always has: `vTexCoord`, `vFragPos`, `vInstanceColor`,
@@ -13,7 +13,7 @@ export default Material;
13
13
  * `uTime`, and must write `vTexCoord` + `gl_Position`.
14
14
  *
15
15
  * Declare extra uniforms and set them via `set(name, value)`. A uniform value
16
- * may be a number, an array (vec2/3/4), or a FUNCTION the function is called
16
+ * may be a number, an array (vec2/3/4), or a FUNCTION: the function is called
17
17
  * each draw and receives the Drawable currently rendering, so a single shared
18
18
  * Material can read PER-OBJECT state (e.g. each card's own tilt angle).
19
19
  *
@@ -3,7 +3,8 @@ export default MathUtils;
3
3
  * @class MathUtils
4
4
  * @description Common math helpers for games: interpolation, clamping, angle
5
5
  * conversion, random ranges, and lightweight 2D vector operations that work on
6
- * any `{ x, y }` object (including planck Vec2 and Emerald Vector2).
6
+ * any `{ x, y }` object (including the physics engine's Vec2 and Emerald
7
+ * Vector2).
7
8
  */
8
9
  declare class MathUtils {
9
10
  /**
@@ -3,7 +3,7 @@ export default ParticleEmitter;
3
3
  * @class ParticleEmitter
4
4
  * @description A reliable, allocation-free particle system built from a fixed
5
5
  * pool of ordinary textured GameObjects. Each live particle's transform, tint
6
- * and opacity are driven by hand every frame there is no instanced-draw /
6
+ * and opacity are driven by hand every frame; there is no instanced-draw /
7
7
  * dynamic-buffer lifecycle to desync, so it keeps drawing for the whole session
8
8
  * (unlike the InstancedTexture-based `Particles`, which can stop emitting after
9
9
  * heavy reuse on some GPUs).
@@ -1,9 +1,14 @@
1
1
  /**
2
2
  * @class Physics
3
- * @description Represents the physics engine
3
+ * @description The game-facing front end of Emerald's own rigid-body engine
4
+ * (see `src/physics`). It owns the {@link World}, converts between world
5
+ * (pixel) units and physics units via `scale`, steps the simulation on a fixed
6
+ * timestep, and routes contacts to `onCollisionEnter`/`onCollisionExit` on your
7
+ * objects and {@link Behaviour} components.
4
8
  * @param {number} gravity - The gravity of the physics engine
5
- * @param {number} scale - The scale of the physics engine
6
- * @param {number} velocityThreshold - The velocity threshold of the physics engine
9
+ * @param {number} scale - Pixels per physics unit (meter)
10
+ * @param {number} velocityThreshold - Relative speed below which impacts stop
11
+ * bouncing, which is what lets resting bodies settle instead of jittering
7
12
  */
8
13
  export class Physics {
9
14
  /**
@@ -13,18 +18,30 @@ export class Physics {
13
18
  */
14
19
  static scheduleAction(callback: Function): void;
15
20
  constructor(gravity: any, scale: any, velocityThreshold?: number);
16
- world: planck.World;
21
+ world: World;
17
22
  gravity: any;
18
23
  scale: any;
19
24
  fixedTimeStep: number;
20
25
  maxSubSteps: number;
26
+ /** Largest slice the variable mode will simulate in one step. */
27
+ maxTimeStep: number;
28
+ /** "fixed" or "variable", see {@link Physics#setVariableTimeStep}. */
29
+ timeStepMode: string;
30
+ /** Steps taken by the last process() call. */
31
+ lastStepCount: number;
21
32
  /** @private */
22
33
  private _accumulator;
34
+ /** World-level listeners added via onCollisionEnter. @private */
35
+ private _enterCallbacks;
36
+ /** World-level listeners added via onCollisionExit. @private */
37
+ private _exitCallbacks;
23
38
  /**
24
39
  * @method _dispatchContacts
25
- * @description Routes planck contacts to the owning objects so Behaviour
26
- * components receive onCollisionEnter/onCollisionExit. Bodies created through
27
- * RigidBody carry the owner via userData.
40
+ * @description Binds contact routing to the current world: owning objects (so
41
+ * Behaviour components receive onCollisionEnter/onCollisionExit) first, then
42
+ * any world-level listeners. Bodies created through RigidBody carry the owner
43
+ * via userData. Re-run whenever the world is replaced, so subscriptions
44
+ * survive a clear().
28
45
  * @private
29
46
  */
30
47
  private _dispatchContacts;
@@ -52,11 +69,54 @@ export class Physics {
52
69
  queryPoint(point: any): any[];
53
70
  /**
54
71
  * @method setFixedTimeStep
55
- * @description Sets the fixed physics step (seconds) and optional substep cap.
72
+ * @description Runs the simulation in constant-size slices, independent of
73
+ * the frame rate: `process()` banks the elapsed time and steps as many whole
74
+ * slices as fit. This is the default and the safe choice: the same inputs
75
+ * produce the same result on every machine, and a slow frame can't destabilise
76
+ * the solver.
77
+ *
78
+ * The cost is that motion updates at the step rate, not the display rate. On
79
+ * a 120Hz screen with a 1/60 step, every simulated position is shown for two
80
+ * frames, so anything that moves in the render frame (a smoothly lerped
81
+ * camera, for instance) will slide against sprites that only move every other
82
+ * frame. Either drive those from the same fixed step, or use
83
+ * {@link Physics#setVariableTimeStep}.
84
+ *
56
85
  * @param {number} step - Fixed step in seconds (e.g. 1/60)
57
86
  * @param {number} [maxSubSteps] - Max steps per process() call (spiral guard)
87
+ * @returns {Physics} - this
58
88
  */
59
- setFixedTimeStep(step: number, maxSubSteps?: number): void;
89
+ setFixedTimeStep(step: number, maxSubSteps?: number): Physics;
90
+ /**
91
+ * @method setVariableTimeStep
92
+ * @description Advances the simulation once per `process()` call using the
93
+ * frame's own delta, so physics runs at exactly the rendering rate. Every
94
+ * rendered frame then shows a freshly simulated position, which is what
95
+ * removes the stepping you otherwise see when the display refreshes faster
96
+ * than the simulation.
97
+ *
98
+ * The trade-offs are real and worth knowing:
99
+ * - **Not deterministic.** Results depend on the frame timings the machine
100
+ * happened to produce, so replays and lockstep networking need fixed steps.
101
+ * - **Solver accuracy tracks the frame rate.** Contacts are resolved
102
+ * iteratively, so a long frame is a coarser solve; deep stacks and fast
103
+ * bodies are more forgiving under a fixed step.
104
+ *
105
+ * A frame longer than `maxStep` is split into several equal steps rather than
106
+ * simulated in one lump, up to `maxSubSteps`; beyond that the excess time is
107
+ * dropped instead of letting the world explode or spiral.
108
+ *
109
+ * @param {number} [maxStep=1/30] - Longest slice to simulate in one step
110
+ * @param {number} [maxSubSteps] - Max steps per process() call
111
+ * @returns {Physics} - this
112
+ */
113
+ setVariableTimeStep(maxStep?: number, maxSubSteps?: number): Physics;
114
+ /**
115
+ * @method getTimeStepMode
116
+ * @description Returns "fixed" or "variable".
117
+ * @returns {string}
118
+ */
119
+ getTimeStepMode(): string;
60
120
  /**
61
121
  * @method createBody
62
122
  * @description Creates a body in the physics engine
@@ -71,27 +131,97 @@ export class Physics {
71
131
  * @returns {Body} - The body
72
132
  */
73
133
  createBody(type: string, position?: Vector2, fixedRotation?: boolean, attachFixture?: boolean, fixtureSize?: Vector2, density?: number, friction?: number, restitution?: number): Body;
134
+ /**
135
+ * @method createDistanceJoint
136
+ * @description Connects two rigid bodies with a fixed-length rod between two
137
+ * world-space anchor points, or a damped spring toward that length when
138
+ * `frequencyHz` is set.
139
+ * @param {RigidBody} rigidBodyA
140
+ * @param {RigidBody} rigidBodyB
141
+ * @param {Object} [options] - `{ anchorA, anchorB, length, frequencyHz,
142
+ * dampingRatio, collideConnected }`. `anchorA`/`anchorB` are world-space
143
+ * pixel points; each defaults to its body's own center. `length` is in
144
+ * pixels; it defaults to the current distance between the anchors.
145
+ * @returns {DistanceJoint}
146
+ */
147
+ createDistanceJoint(rigidBodyA: RigidBody, rigidBodyB: RigidBody, options?: any): DistanceJoint;
148
+ /**
149
+ * @method createRevoluteJoint
150
+ * @description Pins two rigid bodies together at a shared world-space point,
151
+ * like a hinge: a door, a pendulum arm, a see-saw. Set `enableMotor` to
152
+ * drive it toward a target angular speed instead of swinging freely.
153
+ * @param {RigidBody} rigidBodyA
154
+ * @param {RigidBody} rigidBodyB
155
+ * @param {Object} anchor - World-space pixel point both bodies pin to
156
+ * @param {Object} [options] - `{ enableMotor, motorSpeed, maxMotorTorque,
157
+ * collideConnected }`
158
+ * @returns {RevoluteJoint}
159
+ */
160
+ createRevoluteJoint(rigidBodyA: RigidBody, rigidBodyB: RigidBody, anchor: any, options?: any): RevoluteJoint;
161
+ /**
162
+ * @method destroyJoint
163
+ * @description Removes a joint created by {@link Physics#createDistanceJoint}
164
+ * or {@link Physics#createRevoluteJoint}.
165
+ * @param {Joint} joint
166
+ */
167
+ destroyJoint(joint: Joint): void;
74
168
  /**
75
169
  * @method onCollisionEnter
76
- * @description Handles the collision enter event
77
- * @param {Function} callback - The callback function to handle the collision enter event
170
+ * @description Registers a world-level listener called whenever any two
171
+ * fixtures start touching. Survives {@link Physics#clear}.
172
+ * @param {Function} callback - Called with (bodyA, bodyB, contact)
78
173
  */
79
174
  onCollisionEnter(callback: Function): void;
80
175
  /**
81
176
  * @method onCollisionExit
82
- * @description Handles the collision exit event
83
- * @param {Function} callback - The callback function to handle the collision exit event
177
+ * @description Registers a world-level listener called whenever any two
178
+ * fixtures stop touching. Survives {@link Physics#clear}.
179
+ * @param {Function} callback - Called with (bodyA, bodyB, contact)
84
180
  */
85
181
  onCollisionExit(callback: Function): void;
86
182
  /**
87
183
  * @method process
88
- * @description Processes the physics engine
89
- * @param {number} dt - The delta time
184
+ * @description Advances the simulation by `dt` seconds, in whichever way the
185
+ * current time-step mode calls for. Call it once per frame.
186
+ * @param {number} dt - Seconds elapsed since the previous call
187
+ * @returns {number} - How many steps were simulated
188
+ */
189
+ process(dt: number): number;
190
+ /**
191
+ * @method _stepVariable
192
+ * @description Simulates the frame's own delta. Normally that is a single
193
+ * step of exactly `dt`, so physics advances in lock-step with rendering. Only
194
+ * an unusually long frame is divided, and only far enough to keep each slice
195
+ * within `maxTimeStep`.
196
+ * @param {number} dt
197
+ * @returns {number} - Steps taken
198
+ * @private
199
+ */
200
+ private _stepVariable;
201
+ /**
202
+ * @method _stepFixed
203
+ * @description Banks elapsed time and simulates as many constant-size slices
204
+ * as have accumulated, leaving the remainder for next frame.
205
+ * @param {number} dt
206
+ * @returns {number} - Steps taken
207
+ * @private
208
+ */
209
+ private _stepFixed;
210
+ /**
211
+ * @method getInterpolationAlpha
212
+ * @description How far the fixed-step simulation currently sits between its
213
+ * last completed step and the next one (0..1). Useful if you interpolate
214
+ * renderables between physics states. Always 0 in variable mode, where every
215
+ * frame already renders a freshly simulated position.
216
+ * @returns {number}
90
217
  */
91
- process(dt: number): void;
218
+ getInterpolationAlpha(): number;
92
219
  /**
93
220
  * @method clear
94
- * @description Clears the physics engine objects and resets the gravity
221
+ * @description Drops every body and starts a fresh world with the original
222
+ * gravity; use it when tearing a level down. Collision routing and any
223
+ * listeners added through onCollisionEnter/onCollisionExit are re-bound to
224
+ * the new world, so they keep working afterwards.
95
225
  */
96
226
  clear(): void;
97
227
  /**
@@ -204,4 +334,4 @@ export class Vector3 {
204
334
  */
205
335
  getZ(): number;
206
336
  }
207
- import * as planck from "planck";
337
+ import { World } from "./physics/index.js";
@@ -27,7 +27,7 @@ declare class Scene {
27
27
  * @method dispose
28
28
  * @description Destroys every object in the scene (freeing their GPU
29
29
  * resources and physics bodies) and empties it. Call when a level/screen is
30
- * torn down for good removing objects without disposing leaks GL buffers
30
+ * torn down for good; removing objects without disposing leaks GL buffers
31
31
  * over repeated scene swaps.
32
32
  */
33
33
  dispose(): void;
@@ -1,2 +1,2 @@
1
- export const STANDARD_VERTEX_SHADER: "\n attribute vec4 aVertexPosition;\n attribute vec2 aTextureCoord;\n \n attribute vec4 aInstanceMatrix0;\n attribute vec4 aInstanceMatrix1;\n attribute vec4 aInstanceMatrix2;\n attribute vec4 aInstanceMatrix3;\n \n attribute vec2 aInstanceTexCoord0;\n attribute vec2 aInstanceTexCoord1;\n attribute vec2 aInstanceTexCoord2;\n attribute vec2 aInstanceTexCoord3;\n\n attribute vec4 aInstanceColor;\n\n uniform mat4 uModelViewMatrix;\n uniform mat4 uInstancedModelViewMatrix;\n uniform mat4 uProjectionMatrix;\n uniform bool useInstances;\n\n varying highp vec2 vTexCoord;\n varying vec2 vFragPos;\n varying vec4 vInstanceColor;\n\n void main() {\n mat4 instanceMatrix = mat4(\n aInstanceMatrix0,\n aInstanceMatrix1,\n aInstanceMatrix2,\n aInstanceMatrix3\n );\n \n if(useInstances) {\n gl_Position = uProjectionMatrix * uInstancedModelViewMatrix * instanceMatrix * aVertexPosition;\n vFragPos = (uInstancedModelViewMatrix * instanceMatrix * aVertexPosition).xy;\n vInstanceColor = aInstanceColor;\n\n int vertexIndex = int(aVertexPosition.x > 0.0 ? (aVertexPosition.y > 0.0 ? 0 : 2) : (aVertexPosition.y > 0.0 ? 1 : 3));\n \n if(vertexIndex == 0) {\n vTexCoord = aInstanceTexCoord0;\n } else if(vertexIndex == 1) {\n vTexCoord = aInstanceTexCoord1;\n } else if(vertexIndex == 2) {\n vTexCoord = aInstanceTexCoord2;\n } else {\n vTexCoord = aInstanceTexCoord3;\n }\n } else {\n gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;\n vFragPos = (uModelViewMatrix * aVertexPosition).xy;\n vTexCoord = aTextureCoord;\n vInstanceColor = vec4(1.0);\n }\n }\n";
2
- export const STANDARD_FRAGMENT_SHADER: "\n #ifdef GL_ES\n precision highp float;\n #endif\n uniform bool useTexture;\n uniform vec4 uColor;\n uniform sampler2D uSampler;\n uniform float uOpacity;\n\n uniform vec2 uLightPosition[4];\n uniform vec3 uLightColor[4];\n uniform float uLightIntensity[4];\n uniform float uLightRadius[4];\n uniform int uActiveLights;\n \n uniform vec2 uDirLightPosition[4];\n uniform vec2 uDirLightDirection[4];\n uniform vec3 uDirLightColor[4];\n uniform float uDirLightIntensity[4];\n uniform float uDirLightWidth[4];\n uniform int uActiveDirLights;\n \n uniform vec3 uAmbientLightValues;\n uniform bool uUseLighting;\n\n varying vec2 vTexCoord;\n varying vec2 vFragPos;\n varying vec4 vInstanceColor;\n\n void main() {\n vec4 ambientLight = vec4(uAmbientLightValues.xyz, 1.0);\n\n vec4 texColor;\n if (useTexture) {\n texColor = texture2D(uSampler, vTexCoord);\n if (texColor.a < 0.01) discard;\n texColor *= uColor;\n } else {\n texColor = uColor;\n }\n\n texColor *= vInstanceColor;\n \n vec3 lighting = ambientLight.rgb;\n \n for(int i = 0; i < 4; i++) {\n if(i >= uActiveLights) break;\n \n float distance = length(uLightPosition[i] - vFragPos);\n \n if(distance < uLightRadius[i]) {\n float attenuation = 1.0 - distance / uLightRadius[i];\n \n lighting += uLightColor[i] * attenuation * uLightIntensity[i];\n }\n }\n \n for(int i = 0; i < 4; i++) {\n if(i >= uActiveDirLights) break;\n \n vec2 lightPos = uDirLightPosition[i];\n vec2 lightDir = normalize(uDirLightDirection[i]);\n vec2 toFrag = vFragPos - lightPos;\n \n float projection = dot(toFrag, lightDir);\n if(projection < 0.0) continue;\n \n float perpDistance = abs(dot(toFrag, vec2(-lightDir.y, lightDir.x)));\n \n if(perpDistance > uDirLightWidth[i] * 0.5) continue;\n \n float widthFactor = 1.0 - (perpDistance / (uDirLightWidth[i] * 0.5));\n \n float distance = length(toFrag);\n float maxDistance = 1000.0;\n float distanceFactor = max(0.0, 1.0 - (distance / maxDistance));\n \n lighting += uDirLightColor[i] * uDirLightIntensity[i] * widthFactor * distanceFactor;\n }\n \n vec4 outColor;\n if (uUseLighting) {\n outColor = vec4(texColor.rgb * lighting, texColor.a);\n } else {\n outColor = texColor;\n }\n outColor.a *= clamp(uOpacity, 0.0, 1.0);\n gl_FragColor = outColor;\n }\n";
1
+ export const STANDARD_VERTEX_SHADER: "\n attribute vec4 aVertexPosition;\n attribute vec2 aTextureCoord;\n\n attribute vec4 aInstanceMatrix0;\n attribute vec4 aInstanceMatrix1;\n attribute vec4 aInstanceMatrix2;\n attribute vec4 aInstanceMatrix3;\n\n attribute vec2 aInstanceTexCoord0;\n attribute vec2 aInstanceTexCoord1;\n attribute vec2 aInstanceTexCoord2;\n attribute vec2 aInstanceTexCoord3;\n\n attribute vec4 aInstanceColor;\n\n uniform mat4 uModelViewMatrix;\n uniform mat4 uInstancedModelViewMatrix;\n uniform mat4 uProjectionMatrix;\n uniform bool useInstances;\n\n varying highp vec2 vTexCoord;\n varying vec2 vFragPos;\n varying vec4 vInstanceColor;\n\n void main() {\n mat4 instanceMatrix = mat4(\n aInstanceMatrix0,\n aInstanceMatrix1,\n aInstanceMatrix2,\n aInstanceMatrix3\n );\n\n if(useInstances) {\n gl_Position = uProjectionMatrix * uInstancedModelViewMatrix * instanceMatrix * aVertexPosition;\n vFragPos = (uInstancedModelViewMatrix * instanceMatrix * aVertexPosition).xy;\n vInstanceColor = aInstanceColor;\n\n int vertexIndex = int(aVertexPosition.x > 0.0 ? (aVertexPosition.y > 0.0 ? 0 : 2) : (aVertexPosition.y > 0.0 ? 1 : 3));\n\n if(vertexIndex == 0) {\n vTexCoord = aInstanceTexCoord0;\n } else if(vertexIndex == 1) {\n vTexCoord = aInstanceTexCoord1;\n } else if(vertexIndex == 2) {\n vTexCoord = aInstanceTexCoord2;\n } else {\n vTexCoord = aInstanceTexCoord3;\n }\n } else {\n gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;\n vFragPos = (uModelViewMatrix * aVertexPosition).xy;\n vTexCoord = aTextureCoord;\n vInstanceColor = vec4(1.0);\n }\n }\n";
2
+ export const STANDARD_FRAGMENT_SHADER: "\n #ifdef GL_ES\n precision highp float;\n #endif\n uniform bool useTexture;\n uniform vec4 uColor;\n uniform sampler2D uSampler;\n uniform float uOpacity;\n\n uniform vec2 uLightPosition[4];\n uniform vec3 uLightColor[4];\n uniform float uLightIntensity[4];\n uniform float uLightRadius[4];\n uniform int uActiveLights;\n\n uniform vec2 uDirLightPosition[4];\n uniform vec2 uDirLightDirection[4];\n uniform vec3 uDirLightColor[4];\n uniform float uDirLightIntensity[4];\n uniform float uDirLightWidth[4];\n uniform int uActiveDirLights;\n\n uniform vec3 uAmbientLightValues;\n uniform bool uUseLighting;\n\n varying vec2 vTexCoord;\n varying vec2 vFragPos;\n varying vec4 vInstanceColor;\n\n void main() {\n vec4 ambientLight = vec4(uAmbientLightValues.xyz, 1.0);\n\n vec4 texColor;\n if (useTexture) {\n texColor = texture2D(uSampler, vTexCoord);\n if (texColor.a < 0.01) discard;\n texColor *= uColor;\n } else {\n texColor = uColor;\n }\n\n texColor *= vInstanceColor;\n\n vec3 lighting = ambientLight.rgb;\n\n for(int i = 0; i < 4; i++) {\n if(i >= uActiveLights) break;\n\n float distance = length(uLightPosition[i] - vFragPos);\n\n if(distance < uLightRadius[i]) {\n float attenuation = 1.0 - distance / uLightRadius[i];\n\n lighting += uLightColor[i] * attenuation * uLightIntensity[i];\n }\n }\n\n for(int i = 0; i < 4; i++) {\n if(i >= uActiveDirLights) break;\n\n vec2 lightPos = uDirLightPosition[i];\n vec2 lightDir = normalize(uDirLightDirection[i]);\n vec2 toFrag = vFragPos - lightPos;\n\n float projection = dot(toFrag, lightDir);\n if(projection < 0.0) continue;\n\n float perpDistance = abs(dot(toFrag, vec2(-lightDir.y, lightDir.x)));\n\n if(perpDistance > uDirLightWidth[i] * 0.5) continue;\n\n float widthFactor = 1.0 - (perpDistance / (uDirLightWidth[i] * 0.5));\n\n float distance = length(toFrag);\n float maxDistance = 1000.0;\n float distanceFactor = max(0.0, 1.0 - (distance / maxDistance));\n\n lighting += uDirLightColor[i] * uDirLightIntensity[i] * widthFactor * distanceFactor;\n }\n\n vec4 outColor;\n if (uUseLighting) {\n outColor = vec4(texColor.rgb * lighting, texColor.a);\n } else {\n outColor = texColor;\n }\n outColor.a *= clamp(uOpacity, 0.0, 1.0);\n gl_FragColor = outColor;\n }\n";
@@ -61,7 +61,7 @@ declare class Tilemap {
61
61
  * @method buildColliders
62
62
  * @description Generates static physics colliders from the current map. Solid
63
63
  * cells are merged greedily into horizontal runs, so a row of N tiles becomes
64
- * one box collider instead of N far fewer bodies for the physics engine.
64
+ * one box collider instead of N, far fewer bodies for the physics engine.
65
65
  * The bodies are tagged so collision callbacks resolve back to `ownerObject`
66
66
  * (defaults to the tilemap's GameObject). Call again after setMap to rebuild.
67
67
  *
@@ -99,7 +99,7 @@ declare class UI {
99
99
  private _hitTest;
100
100
  /**
101
101
  * @method isOver
102
- * @description Whether an interactive element is under the given page point
102
+ * @description Whether an interactive element is under the given page point,
103
103
  * useful to suppress game clicks behind the UI.
104
104
  */
105
105
  isOver(clientX: any, clientY: any): boolean;
@@ -58,14 +58,14 @@ declare class Behaviour {
58
58
  * @description Called when the owner's body starts touching another. Requires
59
59
  * the Physics world to be ticked. Override in subclasses.
60
60
  * @param {Object} other - The other GameObject/Instance (or null)
61
- * @param {Object} contact - The planck contact
61
+ * @param {Object} contact - The physics contact
62
62
  */
63
63
  onCollisionEnter(other: any, contact: any): void;
64
64
  /**
65
65
  * @method onCollisionExit
66
66
  * @description Called when the owner's body stops touching another.
67
67
  * @param {Object} other - The other GameObject/Instance (or null)
68
- * @param {Object} contact - The planck contact
68
+ * @param {Object} contact - The physics contact
69
69
  */
70
70
  onCollisionExit(other: any, contact: any): void;
71
71
  }
@@ -18,12 +18,18 @@ declare class Collider {
18
18
  * @method syncDebugShape
19
19
  * @description Mirrors a transform onto the debug shape, but only if one has
20
20
  * already been created. Never forces lazy creation.
21
+ *
22
+ * The rigidbody's spawn offset is added back, because the collider sits at
23
+ * `transform + offset` while the transform tracks the renderable. Without it
24
+ * the debug shape would drift away from the collider it is supposed to be
25
+ * showing on any body built with an offset.
26
+ *
21
27
  * @param {Transform} transform - The source transform
22
28
  */
23
29
  syncDebugShape(transform: Transform): void;
24
30
  /**
25
31
  * @method setFilter
26
- * @description Sets the raw planck collision filter on this collider's
32
+ * @description Sets the raw collision filter on this collider's
27
33
  * fixture. Two fixtures collide only when each one's category bit is present
28
34
  * in the other's mask. Subclasses must have created `this.collider`
29
35
  * (the fixture) first.
@@ -26,7 +26,7 @@ declare class GameObject {
26
26
  setLayer(layer: number): GameObject;
27
27
  /**
28
28
  * @method setScreenSpace
29
- * @description When true, the object ignores the camera (fixed on screen)
29
+ * @description When true, the object ignores the camera (fixed on screen),
30
30
  * useful for HUD/UI. Position is then in pixels from the viewport center.
31
31
  * Note: not supported for InstancedTexture-based objects.
32
32
  * @param {boolean} value
@@ -114,7 +114,7 @@ declare class GameObject {
114
114
  * @description Permanently tears the object down: disposes every Drawable's
115
115
  * GPU resources, destroys physics bodies, and runs Behaviour.onDestroy().
116
116
  * Use it (or Scene.remove(obj, { dispose: true })) when an object will not
117
- * be re-added plain Scene.remove() keeps GPU resources alive for re-use.
117
+ * be re-added: plain Scene.remove() keeps GPU resources alive for re-use.
118
118
  * Safe to call twice.
119
119
  */
120
120
  destroy(): void;
@@ -0,0 +1,33 @@
1
+ export default PolygonCollider;
2
+ /**
3
+ * @class PolygonCollider
4
+ * @extends Collider
5
+ * @description A convex-polygon fixture, for collision shapes a box or
6
+ * circle can't approximate, like ramps, wedges, or arbitrary tile outlines (see
7
+ * {@link ForgeLevel}). Points outside the convex hull of what you pass are
8
+ * dropped automatically; a concave shape needs more than one collider.
9
+ * @param {Rigidbody} rigidbody - The rigidbody to attach the collider to
10
+ * @param {Array<{x:number,y:number}>} points - Local-space points, in
11
+ * physics units, in any order
12
+ * @param {number} density - The density of the collider
13
+ * @param {number} friction - The friction of the collider
14
+ * @param {number} restitution - The restitution of the collider
15
+ * @param {boolean} [isSensor=false] - Whether the collider is a sensor
16
+ * @param {GameObject} [parentObject=null] - The parent object of the collider
17
+ * @param {Object} [filter=null] - Collision filter spec, see {@link Collider#setFilter}
18
+ */
19
+ declare class PolygonCollider extends Collider {
20
+ constructor(rigidbody: any, points: any, density: any, friction: any, restitution: any, isSensor?: boolean, parentObject?: any, filter?: any);
21
+ collider: any;
22
+ points: any;
23
+ /**
24
+ * @method getPoints
25
+ * @description Returns the local-space points this collider was built from
26
+ * @returns {Array<{x:number,y:number}>}
27
+ */
28
+ getPoints(): Array<{
29
+ x: number;
30
+ y: number;
31
+ }>;
32
+ }
33
+ import Collider from "./Collider.js";