emeraldengine 2.2.1 → 3.0.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 (162) hide show
  1. package/README.md +2359 -968
  2. package/dist/types/index.d.ts +72 -32
  3. package/dist/types/src/Animator.d.ts +50 -0
  4. package/dist/types/{BitmapText.d.ts → src/BitmapText.d.ts} +19 -21
  5. package/dist/types/src/Camera.d.ts +122 -0
  6. package/dist/types/src/CameraController.d.ts +107 -0
  7. package/dist/types/src/CanvasText.d.ts +91 -0
  8. package/dist/types/src/CollisionLayers.d.ts +58 -0
  9. package/dist/types/{Color.d.ts → src/Color.d.ts} +5 -6
  10. package/dist/types/src/Coroutine.d.ts +111 -0
  11. package/dist/types/src/DebugOverlay.d.ts +86 -0
  12. package/dist/types/src/Drawable.d.ts +271 -0
  13. package/dist/types/src/Easing.d.ts +22 -0
  14. package/dist/types/src/Emerald.d.ts +420 -0
  15. package/dist/types/src/EmeraldDB.d.ts +159 -0
  16. package/dist/types/{FPSCounter.d.ts → src/FPSCounter.d.ts} +1 -3
  17. package/dist/types/src/GLUtils.d.ts +4 -0
  18. package/dist/types/{Instance.d.ts → src/Instance.d.ts} +37 -15
  19. package/dist/types/{InstancedTexture.d.ts → src/InstancedTexture.d.ts} +60 -23
  20. package/dist/types/src/Interpolator.d.ts +66 -0
  21. package/dist/types/src/Material.d.ts +87 -0
  22. package/dist/types/src/MathUtils.d.ts +80 -0
  23. package/dist/types/src/ParticleEmitter.d.ts +131 -0
  24. package/dist/types/{Physics.d.ts → src/Physics.d.ts} +88 -20
  25. package/dist/types/src/Pool.d.ts +53 -0
  26. package/dist/types/src/PostEffects.d.ts +68 -0
  27. package/dist/types/src/PostProcessor.d.ts +124 -0
  28. package/dist/types/src/RenderTarget.d.ts +56 -0
  29. package/dist/types/src/Scene.d.ts +62 -0
  30. package/dist/types/src/ScreenEffects.d.ts +111 -0
  31. package/dist/types/src/Serializer.d.ts +86 -0
  32. package/dist/types/src/Shaders.d.ts +2 -0
  33. package/dist/types/{Shapes.d.ts → src/Shapes.d.ts} +4 -6
  34. package/dist/types/src/SpatialGrid.d.ts +50 -0
  35. package/dist/types/src/SpriteBatch.d.ts +89 -0
  36. package/dist/types/src/StateMachine.d.ts +59 -0
  37. package/dist/types/src/Storage.d.ts +89 -0
  38. package/dist/types/{Texture.d.ts → src/Texture.d.ts} +3 -4
  39. package/dist/types/src/TextureAtlas.d.ts +55 -0
  40. package/dist/types/src/Tilemap.d.ts +91 -0
  41. package/dist/types/src/Time.d.ts +53 -0
  42. package/dist/types/src/Timer.d.ts +54 -0
  43. package/dist/types/src/Transform.d.ts +94 -0
  44. package/dist/types/src/Tween.d.ts +81 -0
  45. package/dist/types/src/UI.d.ts +121 -0
  46. package/dist/types/src/components/Behaviour.d.ts +71 -0
  47. package/dist/types/{components → src/components}/BoxCollider.d.ts +14 -14
  48. package/dist/types/src/components/BoxColliderDebug.d.ts +15 -0
  49. package/dist/types/{components → src/components}/CircleCollider.d.ts +14 -12
  50. package/dist/types/src/components/CircleColliderDebug.d.ts +15 -0
  51. package/dist/types/src/components/Collider.d.ts +96 -0
  52. package/dist/types/src/components/GameObject.d.ts +135 -0
  53. package/dist/types/src/components/RigidBody.d.ts +183 -0
  54. package/dist/types/src/importers/Aseprite.d.ts +79 -0
  55. package/dist/types/src/importers/TiledMap.d.ts +62 -0
  56. package/dist/types/{lights → src/lights}/DirectionalLight.d.ts +7 -9
  57. package/dist/types/{lights → src/lights}/PointLight.d.ts +6 -9
  58. package/dist/types/src/managers/AssetManager.d.ts +116 -0
  59. package/dist/types/src/managers/AudioManager.d.ts +259 -0
  60. package/dist/types/{managers → src/managers}/CameraManager.d.ts +8 -8
  61. package/dist/types/{managers → src/managers}/EventManager.d.ts +46 -32
  62. package/dist/types/src/managers/GLManager.d.ts +84 -0
  63. package/dist/types/src/managers/GLState.d.ts +37 -0
  64. package/dist/types/src/managers/IDManager.d.ts +31 -0
  65. package/dist/types/src/managers/InputManager.d.ts +290 -0
  66. package/dist/types/src/managers/NetworkManager.d.ts +93 -0
  67. package/dist/types/src/managers/RenderStats.d.ts +34 -0
  68. package/dist/types/src/managers/SceneManager.d.ts +44 -0
  69. package/dist/types/src/managers/ShaderManager.d.ts +55 -0
  70. package/dist/types/src/managers/TextureManager.d.ts +102 -0
  71. package/dist/types/src/particlesystem/Particle.d.ts +64 -0
  72. package/dist/types/{particlesystem → src/particlesystem}/ParticleSettings.d.ts +32 -24
  73. package/dist/types/{particlesystem → src/particlesystem}/Particles.d.ts +20 -12
  74. package/index.js +72 -0
  75. package/package.json +74 -60
  76. package/src/Animator.js +95 -0
  77. package/src/BitmapText.js +6 -5
  78. package/src/Camera.js +183 -0
  79. package/src/CameraController.js +192 -0
  80. package/src/CanvasText.js +281 -0
  81. package/src/CollisionLayers.js +86 -0
  82. package/src/Color.js +18 -18
  83. package/src/Coroutine.js +259 -0
  84. package/src/DebugOverlay.js +246 -0
  85. package/src/Drawable.js +842 -582
  86. package/src/Easing.js +57 -0
  87. package/src/Emerald.js +1150 -459
  88. package/src/EmeraldDB.js +328 -0
  89. package/src/FPSCounter.js +43 -43
  90. package/src/GLUtils.js +60 -67
  91. package/src/Instance.js +41 -5
  92. package/src/InstancedTexture.js +251 -118
  93. package/src/Interpolator.js +124 -0
  94. package/src/Material.js +202 -0
  95. package/src/MathUtils.js +133 -0
  96. package/src/ParticleEmitter.js +284 -0
  97. package/src/Physics.js +186 -5
  98. package/src/Pool.js +85 -0
  99. package/src/PostEffects.js +296 -0
  100. package/src/PostProcessor.js +304 -0
  101. package/src/RenderTarget.js +134 -0
  102. package/src/Scene.js +115 -83
  103. package/src/ScreenEffects.js +266 -0
  104. package/src/Serializer.js +131 -0
  105. package/src/Shaders.js +150 -165
  106. package/src/Shapes.js +118 -129
  107. package/src/SpatialGrid.js +111 -0
  108. package/src/SpriteBatch.js +299 -0
  109. package/src/StateMachine.js +82 -0
  110. package/src/Storage.js +175 -47
  111. package/src/Texture.js +58 -67
  112. package/src/TextureAtlas.js +96 -0
  113. package/src/Tilemap.js +274 -0
  114. package/src/Time.js +51 -6
  115. package/src/Timer.js +99 -0
  116. package/src/Transform.js +100 -7
  117. package/src/Tween.js +160 -0
  118. package/src/UI.js +394 -0
  119. package/src/components/Behaviour.js +90 -0
  120. package/src/components/BoxCollider.js +22 -3
  121. package/src/components/CircleCollider.js +19 -3
  122. package/src/components/CircleColliderDebug.js +24 -24
  123. package/src/components/Collider.js +140 -34
  124. package/src/components/GameObject.js +130 -21
  125. package/src/components/RigidBody.js +123 -2
  126. package/src/importers/Aseprite.js +142 -0
  127. package/src/importers/TiledMap.js +158 -0
  128. package/src/lights/DirectionalLight.js +6 -15
  129. package/src/lights/PointLight.js +4 -4
  130. package/src/managers/AssetManager.js +239 -0
  131. package/src/managers/AudioManager.js +565 -146
  132. package/src/managers/EventManager.js +488 -477
  133. package/src/managers/GLManager.js +57 -0
  134. package/src/managers/GLState.js +70 -0
  135. package/src/managers/IDManager.js +24 -2
  136. package/src/managers/InputManager.js +779 -0
  137. package/src/managers/NetworkManager.js +178 -0
  138. package/src/managers/RenderStats.js +34 -0
  139. package/src/managers/SceneManager.js +30 -0
  140. package/src/managers/ShaderManager.js +0 -2
  141. package/src/managers/TextureManager.js +218 -0
  142. package/src/particlesystem/Particle.js +82 -7
  143. package/src/particlesystem/ParticleSettings.js +21 -3
  144. package/src/particlesystem/Particles.js +80 -31
  145. package/dist/types/Drawable.d.ts +0 -157
  146. package/dist/types/Emerald.d.ts +0 -73
  147. package/dist/types/GLUtils.d.ts +0 -6
  148. package/dist/types/Scene.d.ts +0 -39
  149. package/dist/types/Shaders.d.ts +0 -4
  150. package/dist/types/Storage.d.ts +0 -46
  151. package/dist/types/Time.d.ts +0 -22
  152. package/dist/types/Transform.d.ts +0 -41
  153. package/dist/types/components/BoxColliderDebug.d.ts +0 -19
  154. package/dist/types/components/CircleColliderDebug.d.ts +0 -19
  155. package/dist/types/components/Collider.d.ts +0 -53
  156. package/dist/types/components/GameObject.d.ts +0 -72
  157. package/dist/types/components/RigidBody.d.ts +0 -104
  158. package/dist/types/managers/AudioManager.d.ts +0 -60
  159. package/dist/types/managers/GLManager.d.ts +0 -47
  160. package/dist/types/managers/IDManager.d.ts +0 -21
  161. package/dist/types/managers/SceneManager.d.ts +0 -22
  162. package/dist/types/particlesystem/Particle.d.ts +0 -42
@@ -0,0 +1,124 @@
1
+ /**
2
+ * @class Interpolator
3
+ * @description Snapshot interpolation buffer for smoothing networked state.
4
+ * Authoritative updates arrive at a low, irregular rate (e.g. 10–20 Hz); this
5
+ * buffers timestamped snapshots and lets you sample a position "in the past" by
6
+ * a fixed render delay, so remote entities move smoothly between updates instead
7
+ * of teleporting.
8
+ *
9
+ * It is transport-agnostic and pure (no network/DOM dependency), so it works
10
+ * with the built-in NetworkManager, any other transport, or in tests.
11
+ *
12
+ * @example
13
+ * const interp = new Interpolator({ delay: 0.1 });
14
+ * // on each server update for an entity:
15
+ * interp.push(entityId, { x, y }, serverTimeSeconds);
16
+ * // each frame:
17
+ * const pos = interp.sample(entityId, nowSeconds); // { x, y } or null
18
+ */
19
+ class Interpolator {
20
+ /**
21
+ * @param {Object} [options] - { delay = 0.1, maxBuffer = 60 }
22
+ */
23
+ constructor(options = {}) {
24
+ this.delay = options.delay ?? 0.1;
25
+ this.maxBuffer = options.maxBuffer ?? 60;
26
+ /** @private */
27
+ this._buffers = new Map();
28
+ }
29
+
30
+ /**
31
+ * @method push
32
+ * @description Records a snapshot for an entity at a given timestamp.
33
+ * @param {string|number} id - Entity id
34
+ * @param {Object} state - Any object with numeric fields to interpolate (e.g. {x,y})
35
+ * @param {number} time - Snapshot timestamp in seconds
36
+ */
37
+ push(id, state, time) {
38
+ let buf = this._buffers.get(id);
39
+ if (!buf) {
40
+ buf = [];
41
+ this._buffers.set(id, buf);
42
+ }
43
+ buf.push({ t: time, state });
44
+ if (buf.length > 1 && buf[buf.length - 2].t > time) {
45
+ buf.sort((a, b) => a.t - b.t);
46
+ }
47
+ if (buf.length > this.maxBuffer) buf.shift();
48
+ }
49
+
50
+ /**
51
+ * @method sample
52
+ * @description Returns the interpolated state for an entity at (now - delay).
53
+ * Linearly interpolates numeric fields between the two surrounding snapshots.
54
+ * Returns the latest snapshot if rendering ahead of the buffer, or null if no
55
+ * data exists.
56
+ * @param {string|number} id - Entity id
57
+ * @param {number} now - Current time in seconds
58
+ * @returns {Object|null} - Interpolated state, or null
59
+ */
60
+ sample(id, now) {
61
+ const buf = this._buffers.get(id);
62
+ if (!buf || buf.length === 0) return null;
63
+ const renderTime = now - this.delay;
64
+
65
+ if (renderTime <= buf[0].t) return { ...buf[0].state };
66
+ const last = buf[buf.length - 1];
67
+ if (renderTime >= last.t) return { ...last.state };
68
+
69
+ let a = buf[0];
70
+ let b = buf[buf.length - 1];
71
+ for (let i = 0; i < buf.length - 1; i++) {
72
+ if (buf[i].t <= renderTime && buf[i + 1].t >= renderTime) {
73
+ a = buf[i];
74
+ b = buf[i + 1];
75
+ break;
76
+ }
77
+ }
78
+
79
+ const span = b.t - a.t;
80
+ const k = span <= 0 ? 0 : (renderTime - a.t) / span;
81
+ const out = {};
82
+ for (const key in a.state) {
83
+ const av = a.state[key];
84
+ const bv = b.state[key];
85
+ out[key] =
86
+ typeof av === "number" && typeof bv === "number"
87
+ ? av + (bv - av) * k
88
+ : bv;
89
+ }
90
+ return out;
91
+ }
92
+
93
+ /**
94
+ * @method remove
95
+ * @description Drops an entity's buffer (e.g. when it leaves).
96
+ */
97
+ remove(id) {
98
+ this._buffers.delete(id);
99
+ }
100
+
101
+ /**
102
+ * @method prune
103
+ * @description Drops snapshots older than (now - delay - keep) to bound memory
104
+ * for long-lived entities.
105
+ * @param {number} now - Current time in seconds
106
+ * @param {number} [keep] - Extra history to retain past the render point
107
+ */
108
+ prune(now, keep = 1) {
109
+ const cutoff = now - this.delay - keep;
110
+ for (const buf of this._buffers.values()) {
111
+ while (buf.length > 2 && buf[0].t < cutoff) buf.shift();
112
+ }
113
+ }
114
+
115
+ /**
116
+ * @method clear
117
+ * @description Removes all buffered snapshots.
118
+ */
119
+ clear() {
120
+ this._buffers.clear();
121
+ }
122
+ }
123
+
124
+ export default Interpolator;
@@ -0,0 +1,202 @@
1
+ import { initShaderProgram } from "./GLUtils.js";
2
+ import { STANDARD_VERTEX_SHADER } from "./Shaders.js";
3
+ import GLManager from "./managers/GLManager.js";
4
+
5
+ const MATERIAL_FRAGMENT_HEADER = `
6
+ #ifdef GL_ES
7
+ precision highp float;
8
+ #endif
9
+ varying highp vec2 vTexCoord;
10
+ varying vec2 vFragPos;
11
+ varying vec4 vInstanceColor;
12
+ uniform sampler2D uSampler;
13
+ uniform vec4 uColor;
14
+ uniform float uOpacity;
15
+ uniform float uTime;
16
+ `;
17
+
18
+ const MATERIAL_VERTEX_HEADER = `
19
+ attribute vec4 aVertexPosition;
20
+ attribute vec2 aTextureCoord;
21
+ uniform mat4 uProjectionMatrix;
22
+ uniform mat4 uModelViewMatrix;
23
+ uniform float uTime;
24
+ varying highp vec2 vTexCoord;
25
+ varying vec2 vFragPos;
26
+ varying vec4 vInstanceColor;
27
+ `;
28
+
29
+ /**
30
+ * @class Material
31
+ * @description A custom shader for a Drawable. By default it reuses the engine's
32
+ * standard vertex shader (so transforms, the camera, and instancing keep
33
+ * working) and only overrides the fragment program. Pass `options.vertex` to
34
+ * also supply a custom VERTEX program — the escape hatch for effects the fixed
35
+ * pipeline can't express (perspective tilt, vertex waves, billboarding, ...).
36
+ *
37
+ * The fragment shader always has: `vTexCoord`, `vFragPos`, `vInstanceColor`,
38
+ * `uSampler`, `uColor`, `uOpacity`, `uTime`. A custom vertex shader gets
39
+ * `aVertexPosition`, `aTextureCoord`, `uProjectionMatrix`, `uModelViewMatrix`,
40
+ * `uTime`, and must write `vTexCoord` + `gl_Position`.
41
+ *
42
+ * Declare extra uniforms and set them via `set(name, value)`. A uniform value
43
+ * may be a number, an array (vec2/3/4), or a FUNCTION — the function is called
44
+ * each draw and receives the Drawable currently rendering, so a single shared
45
+ * Material can read PER-OBJECT state (e.g. each card's own tilt angle).
46
+ *
47
+ * @example
48
+ * // Per-object 3D tilt with one shared material:
49
+ * const tilt = new Material(fragSrc, {
50
+ * vertex: tiltVertexSrc,
51
+ * uniforms: { uTiltX: (d) => d._tiltX || 0, uTiltY: (d) => d._tiltY || 0 },
52
+ * });
53
+ * cardA.setMaterial(tilt); cardB.setMaterial(tilt);
54
+ * cardA.getComponent(Texture)._tiltX = 0.3; // each object animates independently
55
+ */
56
+ class Material {
57
+ /**
58
+ * @param {string} fragmentSource - Fragment shader body (declares void main)
59
+ * @param {Object} [options] - { vertex?: string, uniforms?: { name: value|function } }
60
+ */
61
+ constructor(fragmentSource, options = {}) {
62
+ const gl = GLManager.getGL();
63
+ this.gl = gl;
64
+
65
+ const vertexSource = options.vertex
66
+ ? MATERIAL_VERTEX_HEADER + options.vertex
67
+ : STANDARD_VERTEX_SHADER;
68
+
69
+ /** @private */
70
+ this._vertexSource = vertexSource;
71
+ /** @private */
72
+ this._fragmentSource = MATERIAL_FRAGMENT_HEADER + fragmentSource;
73
+
74
+ this.program = initShaderProgram(
75
+ gl,
76
+ this._vertexSource,
77
+ this._fragmentSource
78
+ );
79
+
80
+ this.programInfo = {
81
+ program: this.program,
82
+ attribLocations: {
83
+ vertexPosition: gl.getAttribLocation(this.program, "aVertexPosition"),
84
+ aTexCoord: gl.getAttribLocation(this.program, "aTextureCoord"),
85
+ },
86
+ uniformLocations: {
87
+ projectionMatrix: gl.getUniformLocation(
88
+ this.program,
89
+ "uProjectionMatrix"
90
+ ),
91
+ globalViewMatrix: gl.getUniformLocation(
92
+ this.program,
93
+ "uModelViewMatrix"
94
+ ),
95
+ useInstances: gl.getUniformLocation(this.program, "useInstances"),
96
+ uSampler: gl.getUniformLocation(this.program, "uSampler"),
97
+ color: gl.getUniformLocation(this.program, "uColor"),
98
+ uOpacity: gl.getUniformLocation(this.program, "uOpacity"),
99
+ uTime: gl.getUniformLocation(this.program, "uTime"),
100
+ },
101
+ };
102
+
103
+ this.uniforms = Object.assign({}, options.uniforms);
104
+ /** @private */
105
+ this._locCache = new Map();
106
+
107
+ GLManager.registerRestorable(this);
108
+ }
109
+
110
+ /**
111
+ * @method _restoreGL
112
+ * @description Recompiles the material's program and refreshes every cached
113
+ * location after a WebGL context loss.
114
+ * @private
115
+ */
116
+ _restoreGL() {
117
+ const gl = this.gl;
118
+ if (!gl) return;
119
+ this.program = initShaderProgram(
120
+ gl,
121
+ this._vertexSource,
122
+ this._fragmentSource
123
+ );
124
+ this._locCache.clear();
125
+ this.programInfo.program = this.program;
126
+ const a = this.programInfo.attribLocations;
127
+ a.vertexPosition = gl.getAttribLocation(this.program, "aVertexPosition");
128
+ a.aTexCoord = gl.getAttribLocation(this.program, "aTextureCoord");
129
+ const u = this.programInfo.uniformLocations;
130
+ u.projectionMatrix = gl.getUniformLocation(
131
+ this.program,
132
+ "uProjectionMatrix"
133
+ );
134
+ u.globalViewMatrix = gl.getUniformLocation(
135
+ this.program,
136
+ "uModelViewMatrix"
137
+ );
138
+ u.useInstances = gl.getUniformLocation(this.program, "useInstances");
139
+ u.uSampler = gl.getUniformLocation(this.program, "uSampler");
140
+ u.color = gl.getUniformLocation(this.program, "uColor");
141
+ u.uOpacity = gl.getUniformLocation(this.program, "uOpacity");
142
+ u.uTime = gl.getUniformLocation(this.program, "uTime");
143
+ }
144
+
145
+ /**
146
+ * @method set
147
+ * @description Sets (or schedules) a custom uniform value. Numbers, arrays
148
+ * (vec2/3/4), and functions returning those are supported. A function uniform
149
+ * receives the Drawable currently being rendered.
150
+ * @param {string} name - Uniform name
151
+ * @param {number|number[]|Function} value
152
+ * @returns {Material} - this
153
+ */
154
+ set(name, value) {
155
+ this.uniforms[name] = value;
156
+ return this;
157
+ }
158
+
159
+ /** @private */
160
+ _loc(name) {
161
+ if (!this._locCache.has(name)) {
162
+ this._locCache.set(name, this.gl.getUniformLocation(this.program, name));
163
+ }
164
+ return this._locCache.get(name);
165
+ }
166
+
167
+ /**
168
+ * @method applyCustomUniforms
169
+ * @description Uploads all user-declared uniforms. Called by Drawable each draw
170
+ * after the program is bound. Inferred by value shape. Function uniforms are
171
+ * called with the rendering Drawable so shared materials can read per-object data.
172
+ * @param {Drawable} [drawable] - The drawable currently rendering
173
+ */
174
+ applyCustomUniforms(drawable) {
175
+ const gl = this.gl;
176
+ for (const name in this.uniforms) {
177
+ let value = this.uniforms[name];
178
+ if (typeof value === "function") value = value(drawable);
179
+ const loc = this._loc(name);
180
+ if (loc == null) continue;
181
+ if (typeof value === "number") {
182
+ gl.uniform1f(loc, value);
183
+ } else if (Array.isArray(value) || value instanceof Float32Array) {
184
+ switch (value.length) {
185
+ case 2:
186
+ gl.uniform2fv(loc, value);
187
+ break;
188
+ case 3:
189
+ gl.uniform3fv(loc, value);
190
+ break;
191
+ case 4:
192
+ gl.uniform4fv(loc, value);
193
+ break;
194
+ default:
195
+ gl.uniform1fv(loc, value);
196
+ }
197
+ }
198
+ }
199
+ }
200
+ }
201
+
202
+ export default Material;
@@ -0,0 +1,133 @@
1
+ /**
2
+ * @class MathUtils
3
+ * @description Common math helpers for games: interpolation, clamping, angle
4
+ * conversion, random ranges, and lightweight 2D vector operations that work on
5
+ * any `{ x, y }` object (including planck Vec2 and Emerald Vector2).
6
+ */
7
+ class MathUtils {
8
+ /**
9
+ * Clamps a value to the [min, max] range.
10
+ */
11
+ static clamp(value, min, max) {
12
+ return value < min ? min : value > max ? max : value;
13
+ }
14
+
15
+ /**
16
+ * Linearly interpolates between a and b by t (t is not clamped).
17
+ */
18
+ static lerp(a, b, t) {
19
+ return a + (b - a) * t;
20
+ }
21
+
22
+ /**
23
+ * Inverse lerp: returns the t for which lerp(a, b, t) === value.
24
+ */
25
+ static inverseLerp(a, b, value) {
26
+ return a === b ? 0 : (value - a) / (b - a);
27
+ }
28
+
29
+ /**
30
+ * Remaps a value from one range to another.
31
+ */
32
+ static map(value, inMin, inMax, outMin, outMax) {
33
+ return MathUtils.lerp(
34
+ outMin,
35
+ outMax,
36
+ MathUtils.inverseLerp(inMin, inMax, value)
37
+ );
38
+ }
39
+
40
+ /**
41
+ * Converts degrees to radians.
42
+ */
43
+ static degToRad(degrees) {
44
+ return (degrees * Math.PI) / 180;
45
+ }
46
+
47
+ /**
48
+ * Converts radians to degrees.
49
+ */
50
+ static radToDeg(radians) {
51
+ return (radians * 180) / Math.PI;
52
+ }
53
+
54
+ /**
55
+ * Returns a random float in [min, max).
56
+ */
57
+ static randomRange(min, max) {
58
+ return min + Math.random() * (max - min);
59
+ }
60
+
61
+ /**
62
+ * Returns a random integer in [min, max] (inclusive).
63
+ */
64
+ static randomInt(min, max) {
65
+ return Math.floor(min + Math.random() * (max - min + 1));
66
+ }
67
+
68
+ /**
69
+ * Returns a random element of an array (or undefined if empty).
70
+ */
71
+ static randomChoice(array) {
72
+ return array.length
73
+ ? array[Math.floor(Math.random() * array.length)]
74
+ : undefined;
75
+ }
76
+
77
+ /**
78
+ * Euclidean distance between two `{ x, y }` points.
79
+ */
80
+ static distance(a, b) {
81
+ const dx = a.x - b.x;
82
+ const dy = a.y - b.y;
83
+ return Math.sqrt(dx * dx + dy * dy);
84
+ }
85
+
86
+ /**
87
+ * Squared distance between two points (cheaper than distance for comparisons).
88
+ */
89
+ static distanceSquared(a, b) {
90
+ const dx = a.x - b.x;
91
+ const dy = a.y - b.y;
92
+ return dx * dx + dy * dy;
93
+ }
94
+
95
+ /**
96
+ * Vector length (magnitude) of an `{ x, y }`.
97
+ */
98
+ static length(v) {
99
+ return Math.sqrt(v.x * v.x + v.y * v.y);
100
+ }
101
+
102
+ /**
103
+ * Returns a normalized copy of `{ x, y }` as a plain object. Zero-length
104
+ * vectors return { x: 0, y: 0 }.
105
+ */
106
+ static normalize(v) {
107
+ const len = MathUtils.length(v);
108
+ return len === 0 ? { x: 0, y: 0 } : { x: v.x / len, y: v.y / len };
109
+ }
110
+
111
+ /**
112
+ * Dot product of two `{ x, y }` vectors.
113
+ */
114
+ static dot(a, b) {
115
+ return a.x * b.x + a.y * b.y;
116
+ }
117
+
118
+ /**
119
+ * Angle in radians from a to b.
120
+ */
121
+ static angleBetween(a, b) {
122
+ return Math.atan2(b.y - a.y, b.x - a.x);
123
+ }
124
+
125
+ /**
126
+ * Linearly interpolates between two `{ x, y }` points, returning a plain object.
127
+ */
128
+ static lerpVector(a, b, t) {
129
+ return { x: MathUtils.lerp(a.x, b.x, t), y: MathUtils.lerp(a.y, b.y, t) };
130
+ }
131
+ }
132
+
133
+ export default MathUtils;