melonjs 20.7.0 → 20.9.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 (332) hide show
  1. package/README.md +7 -3
  2. package/build/application/application.d.ts +66 -8
  3. package/build/application/application.d.ts.map +1 -1
  4. package/build/application/defaultApplicationSettings.d.ts +6 -0
  5. package/build/application/defaultApplicationSettings.d.ts.map +1 -1
  6. package/build/application/header.d.ts.map +1 -1
  7. package/build/application/resize.d.ts +25 -0
  8. package/build/application/resize.d.ts.map +1 -1
  9. package/build/application/scaleMethods.d.ts +13 -3
  10. package/build/application/scaleMethods.d.ts.map +1 -1
  11. package/build/application/settings.d.ts +144 -5
  12. package/build/application/settings.d.ts.map +1 -1
  13. package/build/audio/audio.d.ts +29 -5
  14. package/build/audio/audio.d.ts.map +1 -1
  15. package/build/audio/autopause.d.ts +36 -0
  16. package/build/audio/autopause.d.ts.map +1 -0
  17. package/build/audio/backend/engine.d.ts +10 -1
  18. package/build/audio/backend/engine.d.ts.map +1 -1
  19. package/build/audio/backend/sound.d.ts +0 -1
  20. package/build/audio/backend/sound.d.ts.map +1 -1
  21. package/build/audio/backend/spatial.d.ts.map +1 -1
  22. package/build/audio/context.d.ts +35 -0
  23. package/build/audio/context.d.ts.map +1 -0
  24. package/build/audio/playback.d.ts.map +1 -1
  25. package/build/audio/procedural.d.ts.map +1 -1
  26. package/build/audio/spatial.d.ts +87 -0
  27. package/build/audio/spatial.d.ts.map +1 -0
  28. package/build/audio/state.d.ts +1 -0
  29. package/build/audio/state.d.ts.map +1 -1
  30. package/build/audio/types.d.ts +46 -6
  31. package/build/audio/types.d.ts.map +1 -1
  32. package/build/camera/camera2d.d.ts.map +1 -1
  33. package/build/camera/camera3d.d.ts +95 -8
  34. package/build/camera/camera3d.d.ts.map +1 -1
  35. package/build/camera/effects/fade_effect.d.ts.map +1 -1
  36. package/build/camera/effects/mask_effect.d.ts.map +1 -1
  37. package/build/camera/effects/shake_effect.d.ts.map +1 -1
  38. package/build/geometries/box3d.d.ts +25 -7
  39. package/build/geometries/box3d.d.ts.map +1 -1
  40. package/build/geometries/ellipse.d.ts +15 -1
  41. package/build/geometries/ellipse.d.ts.map +1 -1
  42. package/build/geometries/line.d.ts +1 -1
  43. package/build/geometries/line.d.ts.map +1 -1
  44. package/build/geometries/point.d.ts +1 -1
  45. package/build/geometries/point.d.ts.map +1 -1
  46. package/build/geometries/polygon.d.ts +15 -1
  47. package/build/geometries/polygon.d.ts.map +1 -1
  48. package/build/geometries/rectangle.d.ts +1 -1
  49. package/build/geometries/rectangle.d.ts.map +1 -1
  50. package/build/geometries/roundrect.d.ts +1 -1
  51. package/build/geometries/roundrect.d.ts.map +1 -1
  52. package/build/geometries/sphere.d.ts +36 -7
  53. package/build/geometries/sphere.d.ts.map +1 -1
  54. package/build/index.d.ts +16 -3
  55. package/build/index.d.ts.map +1 -1
  56. package/build/index.js +38172 -33633
  57. package/build/index.js.map +4 -4
  58. package/build/input/gamepad.d.ts +129 -3
  59. package/build/input/gamepad.d.ts.map +1 -1
  60. package/build/input/pointerevent.d.ts +8 -0
  61. package/build/input/pointerevent.d.ts.map +1 -1
  62. package/build/level/gltf/GLTFModel.d.ts +20 -33
  63. package/build/level/gltf/GLTFModel.d.ts.map +1 -1
  64. package/build/level/gltf/GLTFScene.d.ts +40 -1
  65. package/build/level/gltf/GLTFScene.d.ts.map +1 -1
  66. package/build/level/level.d.ts +35 -0
  67. package/build/level/level.d.ts.map +1 -1
  68. package/build/level/tiled/TMXLayer.d.ts +5 -2
  69. package/build/level/tiled/TMXLayer.d.ts.map +1 -1
  70. package/build/level/tiled/TMXObject.d.ts +0 -1
  71. package/build/level/tiled/TMXObjectFactory.d.ts +3 -2
  72. package/build/level/tiled/TMXObjectFactory.d.ts.map +1 -1
  73. package/build/level/tiled/TMXTile.d.ts +2 -1
  74. package/build/level/tiled/TMXTile.d.ts.map +1 -1
  75. package/build/level/tiled/TMXTileMap.d.ts +7 -4
  76. package/build/level/tiled/TMXTileMap.d.ts.map +1 -1
  77. package/build/level/tiled/TMXTileset.d.ts +1 -1
  78. package/build/level/tiled/TMXTileset.d.ts.map +1 -1
  79. package/build/level/tiled/TMXTilesetGroup.d.ts +5 -0
  80. package/build/level/tiled/TMXTilesetGroup.d.ts.map +1 -1
  81. package/build/level/tiled/factories/shape.d.ts +0 -1
  82. package/build/level/tiled/renderer/TMXHexagonalRenderer.d.ts +6 -5
  83. package/build/level/tiled/renderer/TMXHexagonalRenderer.d.ts.map +1 -1
  84. package/build/level/tiled/renderer/TMXIsometricRenderer.d.ts +5 -0
  85. package/build/level/tiled/renderer/TMXIsometricRenderer.d.ts.map +1 -1
  86. package/build/level/tiled/renderer/TMXObliqueRenderer.d.ts +5 -7
  87. package/build/level/tiled/renderer/TMXObliqueRenderer.d.ts.map +1 -1
  88. package/build/level/tiled/renderer/TMXOrthogonalRenderer.d.ts +5 -0
  89. package/build/level/tiled/renderer/TMXOrthogonalRenderer.d.ts.map +1 -1
  90. package/build/level/tiled/renderer/TMXRenderer.d.ts +19 -4
  91. package/build/level/tiled/renderer/TMXRenderer.d.ts.map +1 -1
  92. package/build/level/tiled/renderer/autodetect.d.ts +0 -4
  93. package/build/level/tiled/renderer/autodetect.d.ts.map +1 -1
  94. package/build/loader/cache.d.ts +220 -0
  95. package/build/loader/cache.d.ts.map +1 -1
  96. package/build/loader/loader.d.ts +20 -340
  97. package/build/loader/loader.d.ts.map +1 -1
  98. package/build/loader/loadingscreen.d.ts +1 -2
  99. package/build/loader/loadingscreen.d.ts.map +1 -1
  100. package/build/loader/parsers/gltf.d.ts +115 -0
  101. package/build/loader/parsers/gltf.d.ts.map +1 -1
  102. package/build/loader/parsers/shader.d.ts +0 -2
  103. package/build/math/color.d.ts +28 -5
  104. package/build/math/color.d.ts.map +1 -1
  105. package/build/math/matrix2d.d.ts +1 -1
  106. package/build/math/matrix2d.d.ts.map +1 -1
  107. package/build/math/matrix3d.d.ts +1 -1
  108. package/build/math/matrix3d.d.ts.map +1 -1
  109. package/build/math/observableVector2d.d.ts +14 -2
  110. package/build/math/observableVector2d.d.ts.map +1 -1
  111. package/build/math/observableVector3d.d.ts +15 -1
  112. package/build/math/observableVector3d.d.ts.map +1 -1
  113. package/build/math/vector2d.d.ts +31 -1
  114. package/build/math/vector2d.d.ts.map +1 -1
  115. package/build/math/vector3d.d.ts +38 -1
  116. package/build/math/vector3d.d.ts.map +1 -1
  117. package/build/math/vertex.d.ts.map +1 -1
  118. package/build/particles/emitter.d.ts.map +1 -1
  119. package/build/particles/particle.d.ts +29 -2
  120. package/build/particles/particle.d.ts.map +1 -1
  121. package/build/particles/settings.d.ts +104 -0
  122. package/build/particles/settings.d.ts.map +1 -1
  123. package/build/physics/adapter.d.ts +9 -1
  124. package/build/physics/adapter.d.ts.map +1 -1
  125. package/build/physics/bounds.d.ts +1 -1
  126. package/build/physics/bounds.d.ts.map +1 -1
  127. package/build/physics/broadphase/octree.d.ts +24 -0
  128. package/build/physics/broadphase/octree.d.ts.map +1 -1
  129. package/build/physics/broadphase/quadtree.d.ts +31 -0
  130. package/build/physics/broadphase/quadtree.d.ts.map +1 -1
  131. package/build/physics/builtin/body.d.ts +17 -2
  132. package/build/physics/builtin/body.d.ts.map +1 -1
  133. package/build/physics/builtin/builtin-adapter.d.ts.map +1 -1
  134. package/build/physics/builtin/detector.d.ts +0 -1
  135. package/build/physics/builtin/detector.d.ts.map +1 -1
  136. package/build/physics/builtin/sat.d.ts +0 -7
  137. package/build/physics/builtin/sat3d.d.ts +46 -0
  138. package/build/physics/builtin/sat3d.d.ts.map +1 -1
  139. package/build/physics/response.d.ts +45 -62
  140. package/build/physics/response.d.ts.map +1 -1
  141. package/build/pool.d.ts +4 -0
  142. package/build/pool.d.ts.map +1 -1
  143. package/build/renderable/collectable.d.ts +6 -1
  144. package/build/renderable/collectable.d.ts.map +1 -1
  145. package/build/renderable/colorlayer.d.ts +17 -4
  146. package/build/renderable/colorlayer.d.ts.map +1 -1
  147. package/build/renderable/container.d.ts +23 -17
  148. package/build/renderable/container.d.ts.map +1 -1
  149. package/build/renderable/entity/entity.d.ts +12 -16
  150. package/build/renderable/entity/entity.d.ts.map +1 -1
  151. package/build/renderable/frameAnimation.d.ts +1 -1
  152. package/build/renderable/groundshadow.d.ts +1 -0
  153. package/build/renderable/groundshadow.d.ts.map +1 -1
  154. package/build/renderable/imagelayer.d.ts +12 -5
  155. package/build/renderable/imagelayer.d.ts.map +1 -1
  156. package/build/renderable/instanced_mesh.d.ts +56 -7
  157. package/build/renderable/instanced_mesh.d.ts.map +1 -1
  158. package/build/renderable/mesh.d.ts +369 -4
  159. package/build/renderable/mesh.d.ts.map +1 -1
  160. package/build/renderable/nineslicesprite.d.ts +3 -13
  161. package/build/renderable/nineslicesprite.d.ts.map +1 -1
  162. package/build/renderable/renderable.d.ts +129 -28
  163. package/build/renderable/renderable.d.ts.map +1 -1
  164. package/build/renderable/sprite.d.ts +7 -20
  165. package/build/renderable/sprite.d.ts.map +1 -1
  166. package/build/renderable/sprite3d.d.ts +31 -16
  167. package/build/renderable/sprite3d.d.ts.map +1 -1
  168. package/build/renderable/text/bitmaptext.d.ts +76 -5
  169. package/build/renderable/text/bitmaptext.d.ts.map +1 -1
  170. package/build/renderable/text/bitmaptextdata.d.ts +1 -5
  171. package/build/renderable/text/bitmaptextdata.d.ts.map +1 -1
  172. package/build/renderable/text/glypheffect.d.ts +44 -0
  173. package/build/renderable/text/glypheffect.d.ts.map +1 -0
  174. package/build/renderable/text/text.d.ts +22 -3
  175. package/build/renderable/text/text.d.ts.map +1 -1
  176. package/build/renderable/text/textmetrics.d.ts +2 -0
  177. package/build/renderable/text/textmetrics.d.ts.map +1 -1
  178. package/build/renderable/trail.d.ts +0 -1
  179. package/build/renderable/trail.d.ts.map +1 -1
  180. package/build/renderable/trail3d.d.ts +174 -0
  181. package/build/renderable/trail3d.d.ts.map +1 -0
  182. package/build/renderable/trigger.d.ts +28 -5
  183. package/build/renderable/trigger.d.ts.map +1 -1
  184. package/build/renderable/ui/panelpaint.d.ts +5 -0
  185. package/build/renderable/ui/panelpaint.d.ts.map +1 -0
  186. package/build/renderable/ui/progressbar.d.ts +192 -0
  187. package/build/renderable/ui/progressbar.d.ts.map +1 -0
  188. package/build/renderable/ui/uibaseelement.d.ts +48 -3
  189. package/build/renderable/ui/uibaseelement.d.ts.map +1 -1
  190. package/build/renderable/ui/uipanel.d.ts +245 -0
  191. package/build/renderable/ui/uipanel.d.ts.map +1 -0
  192. package/build/renderable/ui/uispriteelement.d.ts +19 -3
  193. package/build/renderable/ui/uispriteelement.d.ts.map +1 -1
  194. package/build/renderable/ui/uitextbutton.d.ts +30 -1
  195. package/build/renderable/ui/uitextbutton.d.ts.map +1 -1
  196. package/build/state/state.d.ts.map +1 -1
  197. package/build/system/bootstrap.d.ts.map +1 -1
  198. package/build/system/legacy_pool.d.ts +24 -4
  199. package/build/system/legacy_pool.d.ts.map +1 -1
  200. package/build/system/pool.d.ts +15 -8
  201. package/build/system/pool.d.ts.map +1 -1
  202. package/build/tweens/tween.d.ts +50 -3
  203. package/build/tweens/tween.d.ts.map +1 -1
  204. package/build/video/canvas/canvas_renderer.d.ts +34 -23
  205. package/build/video/canvas/canvas_renderer.d.ts.map +1 -1
  206. package/build/video/effects/blendEffect.d.ts +0 -1
  207. package/build/video/effects/bloom.d.ts +72 -0
  208. package/build/video/effects/bloom.d.ts.map +1 -0
  209. package/build/video/effects/blur.d.ts +3 -2
  210. package/build/video/effects/blur.d.ts.map +1 -1
  211. package/build/video/effects/chromaticAberration.d.ts +3 -2
  212. package/build/video/effects/chromaticAberration.d.ts.map +1 -1
  213. package/build/video/effects/colorMatrix.d.ts +3 -2
  214. package/build/video/effects/colorMatrix.d.ts.map +1 -1
  215. package/build/video/effects/desaturate.d.ts +10 -2
  216. package/build/video/effects/desaturate.d.ts.map +1 -1
  217. package/build/video/effects/dissolve.d.ts +3 -2
  218. package/build/video/effects/dissolve.d.ts.map +1 -1
  219. package/build/video/effects/dropShadow.d.ts +3 -2
  220. package/build/video/effects/dropShadow.d.ts.map +1 -1
  221. package/build/video/effects/flash.d.ts +3 -2
  222. package/build/video/effects/flash.d.ts.map +1 -1
  223. package/build/video/effects/glow.d.ts +3 -2
  224. package/build/video/effects/glow.d.ts.map +1 -1
  225. package/build/video/effects/hologram.d.ts +3 -2
  226. package/build/video/effects/hologram.d.ts.map +1 -1
  227. package/build/video/effects/invert.d.ts +10 -2
  228. package/build/video/effects/invert.d.ts.map +1 -1
  229. package/build/video/effects/outline.d.ts +3 -2
  230. package/build/video/effects/outline.d.ts.map +1 -1
  231. package/build/video/effects/pixelate.d.ts +3 -2
  232. package/build/video/effects/pixelate.d.ts.map +1 -1
  233. package/build/video/effects/radialGradient.d.ts +8 -3
  234. package/build/video/effects/radialGradient.d.ts.map +1 -1
  235. package/build/video/effects/scanline.d.ts +3 -2
  236. package/build/video/effects/scanline.d.ts.map +1 -1
  237. package/build/video/effects/sepia.d.ts +10 -2
  238. package/build/video/effects/sepia.d.ts.map +1 -1
  239. package/build/video/effects/shadereffect.d.ts +10 -4
  240. package/build/video/effects/shadereffect.d.ts.map +1 -1
  241. package/build/video/effects/shine.d.ts +3 -2
  242. package/build/video/effects/shine.d.ts.map +1 -1
  243. package/build/video/effects/tintPulse.d.ts +3 -7
  244. package/build/video/effects/tintPulse.d.ts.map +1 -1
  245. package/build/video/effects/tonemap.d.ts +121 -0
  246. package/build/video/effects/tonemap.d.ts.map +1 -0
  247. package/build/video/effects/vignette.d.ts +3 -2
  248. package/build/video/effects/vignette.d.ts.map +1 -1
  249. package/build/video/effects/wave.d.ts +3 -7
  250. package/build/video/effects/wave.d.ts.map +1 -1
  251. package/build/video/gpu/batcher.d.ts +8 -2
  252. package/build/video/gpu/batcher.d.ts.map +1 -1
  253. package/build/video/gpu/vertexformat.d.ts +26 -0
  254. package/build/video/gpu/vertexformat.d.ts.map +1 -1
  255. package/build/video/gradient.d.ts +1 -1
  256. package/build/video/gradient.d.ts.map +1 -1
  257. package/build/video/renderer.d.ts +111 -7
  258. package/build/video/renderer.d.ts.map +1 -1
  259. package/build/video/renderstate.d.ts +2 -0
  260. package/build/video/renderstate.d.ts.map +1 -1
  261. package/build/video/rendertarget/canvasrendertarget.d.ts +3 -4
  262. package/build/video/rendertarget/canvasrendertarget.d.ts.map +1 -1
  263. package/build/video/rendertarget/render_target_pool.d.ts +0 -1
  264. package/build/video/rendertarget/rendertarget.d.ts +12 -5
  265. package/build/video/rendertarget/rendertarget.d.ts.map +1 -1
  266. package/build/video/rendertarget/webglrendertarget.d.ts +0 -1
  267. package/build/video/rendertarget/webglrendertarget.d.ts.map +1 -1
  268. package/build/video/rendertarget/webgpurendertarget.d.ts +24 -14
  269. package/build/video/rendertarget/webgpurendertarget.d.ts.map +1 -1
  270. package/build/video/texture/atlas.d.ts +2 -1
  271. package/build/video/texture/atlas.d.ts.map +1 -1
  272. package/build/video/texture/cache.d.ts +1 -3
  273. package/build/video/texture/frametexture.d.ts +0 -1
  274. package/build/video/texture/frametexture.d.ts.map +1 -1
  275. package/build/video/texture/noise_texture2d.d.ts +1 -0
  276. package/build/video/texture/noise_texture2d.d.ts.map +1 -1
  277. package/build/video/texture/texture2d.d.ts +6 -0
  278. package/build/video/texture/texture2d.d.ts.map +1 -1
  279. package/build/video/utils/autodetect.d.ts +0 -2
  280. package/build/video/webgl/batchers/batcher.d.ts +0 -9
  281. package/build/video/webgl/batchers/batcher.d.ts.map +1 -1
  282. package/build/video/webgl/batchers/lit_quad_batcher.d.ts +2 -0
  283. package/build/video/webgl/batchers/lit_quad_batcher.d.ts.map +1 -1
  284. package/build/video/webgl/batchers/material_batcher.d.ts +4 -2
  285. package/build/video/webgl/batchers/material_batcher.d.ts.map +1 -1
  286. package/build/video/webgl/batchers/mesh_batcher.d.ts +0 -3
  287. package/build/video/webgl/batchers/mesh_batcher.d.ts.map +1 -1
  288. package/build/video/webgl/batchers/quad_batcher.d.ts +4 -0
  289. package/build/video/webgl/batchers/quad_batcher.d.ts.map +1 -1
  290. package/build/video/webgl/buffer/index.d.ts +0 -1
  291. package/build/video/webgl/buffer/retained_geometry.d.ts +0 -1
  292. package/build/video/webgl/glshader.d.ts +5 -3
  293. package/build/video/webgl/glshader.d.ts.map +1 -1
  294. package/build/video/webgl/renderers/tmxlayer/orthogonal.d.ts +0 -4
  295. package/build/video/webgl/texture/store.d.ts +0 -1
  296. package/build/video/webgl/webgl_renderer.d.ts +63 -24
  297. package/build/video/webgl/webgl_renderer.d.ts.map +1 -1
  298. package/build/video/webgpu/batchers/mesh_batcher.d.ts +0 -3
  299. package/build/video/webgpu/batchers/mesh_batcher.d.ts.map +1 -1
  300. package/build/video/webgpu/batchers/quad_batcher.d.ts +0 -2
  301. package/build/video/webgpu/batchers/quad_batcher.d.ts.map +1 -1
  302. package/build/video/webgpu/batchers/webgpu_batcher.d.ts +0 -2
  303. package/build/video/webgpu/batchers/webgpu_batcher.d.ts.map +1 -1
  304. package/build/video/webgpu/pipeline/cache.d.ts.map +1 -1
  305. package/build/video/webgpu/renderers/tmxlayer/orthogonal.d.ts +0 -2
  306. package/build/video/webgpu/texture/frametexture.d.ts +0 -2
  307. package/build/video/webgpu/texture/frametexture.d.ts.map +1 -1
  308. package/build/video/webgpu/texture/store.d.ts +0 -1
  309. package/build/video/webgpu/webgpu_renderer.d.ts +7 -75
  310. package/build/video/webgpu/webgpu_renderer.d.ts.map +1 -1
  311. package/package.json +2 -2
  312. package/skills/AGENTS.md +1 -1
  313. package/skills/melonjs/SKILL.md +2 -0
  314. package/skills/melonjs-3d/SKILL.md +454 -22
  315. package/skills/melonjs-3d-assets/SKILL.md +111 -10
  316. package/skills/melonjs-audio/SKILL.md +229 -8
  317. package/skills/melonjs-camera-and-drawing/SKILL.md +127 -1
  318. package/skills/melonjs-display-and-scaling/SKILL.md +273 -0
  319. package/skills/melonjs-effects-and-shaders/SKILL.md +341 -29
  320. package/skills/melonjs-events/SKILL.md +8 -6
  321. package/skills/melonjs-input/SKILL.md +147 -7
  322. package/skills/melonjs-math/SKILL.md +313 -0
  323. package/skills/melonjs-particles-and-trails/SKILL.md +189 -13
  324. package/skills/melonjs-performance/SKILL.md +131 -23
  325. package/skills/melonjs-physics/SKILL.md +103 -28
  326. package/skills/melonjs-renderables/SKILL.md +8 -2
  327. package/skills/melonjs-scenes-and-state/SKILL.md +134 -3
  328. package/skills/melonjs-sprites-and-animation/SKILL.md +9 -4
  329. package/skills/melonjs-tilemaps/SKILL.md +40 -12
  330. package/skills/melonjs-ui-and-text/SKILL.md +546 -7
  331. package/build/level/gltf/srgb.d.ts +0 -20
  332. package/build/level/gltf/srgb.d.ts.map +0 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: melonjs-input
3
- description: "Use this skill for keyboard, pointer, mouse, touch and gamepad input in melonJS. Covers the bindKey action indirection, registerPointerEvent on regions, the isKinematic requirement that silently blocks pointer events, world vs screen pointer coordinates, and gamepad mapping onto the same actions. Triggers on: input, bindKey, isKeyPressed, KEY, registerPointerEvent, releasePointerEvent, pointerdown, pointerup, POINTERMOVE, gamepad, bindGamepad, triggerKeyEvent, click, touch, drag."
3
+ description: "Use this skill for keyboard, pointer, mouse, touch and gamepad input in melonJS. Covers the bindKey action indirection, registerPointerEvent on regions, the isKinematic requirement that silently blocks pointer events, which of several overlapping objects receives an event and how to consume it, world vs screen pointer coordinates, and gamepad mapping onto the same actions. Triggers on: input, bindKey, isKeyPressed, KEY, registerPointerEvent, releasePointerEvent, pointerdown, pointerup, pointermove, POINTERMOVE, gamepad, bindGamepad, triggerKeyEvent, KEYDOWN, KEYUP, press any key, splash screen, click, touch, drag, hit test, event propagation, stop propagating, overlapping, which object gets the click."
4
4
  license: MIT
5
5
  ---
6
6
 
@@ -29,6 +29,31 @@ wrong for jump or fire. A locked action stays consumed until the key is released
29
29
  or you call `input.unlockKey("jump")`. Use `input.keyStatus(action)` when you
30
30
  want the raw held/not-held state regardless of locking.
31
31
 
32
+ ### A poll can miss a press entirely
33
+
34
+ `isKeyPressed` is sampled once per frame, and `keyup` decrements the key's
35
+ counter the moment it arrives — locked or not. A press that goes down and up
36
+ between two frames therefore leaves the counter back at zero and is never
37
+ seen. At 60fps that is anything under ~16ms: rare from a human finger, routine
38
+ from a synthetic event, and more likely the slower the frame rate.
39
+
40
+ For a screen where a missed press is a dead end — a splash, a "press any key",
41
+ a notice to acknowledge — listen for the event instead, which cannot be missed:
42
+
43
+ ```js
44
+ import { event } from "melonjs";
45
+
46
+ // action is the bound action name, or undefined for an unbound key
47
+ const onKey = (action) => { if (action === "menuSelect") continue(); };
48
+ event.on(event.KEYDOWN, onKey); // in onResetEvent
49
+ event.off(event.KEYDOWN, onKey); // in onDestroyEvent — it does not self-remove
50
+ ```
51
+
52
+ `KEYDOWN` fires for *every* key, bound or not, so matching on `action` is what
53
+ narrows it; it also repeats while the key is held, so guard anything that must
54
+ happen once. Keep polling for movement and for a menu cursor, where one step
55
+ per press and a key held across a state change are the things that matter.
56
+
32
57
  The full signature is `bindKey(keyCode, action, lock?, preventDefault?)`;
33
58
  `preventDefault` defaults to `input.preventDefault` (itself `true`). Pass the
34
59
  fourth argument per binding, or change the global default with
@@ -64,9 +89,11 @@ subclasses with no body are the ones that catch people.
64
89
  Register in `onActivateEvent` and release in `onDeactivateEvent`, not in the
65
90
  constructor — pooled objects are reused and would otherwise accumulate handlers.
66
91
 
67
- `app.viewport` works as a whole-screen region when you want global clicks: the
68
- dispatcher appends it to the candidate list on every event, so it is reachable
69
- even when nothing else is under the pointer.
92
+ `app.viewport` works as a whole-screen region when you want global clicks. Note
93
+ it is asked **before** everything else, not as a fallback after nothing matched:
94
+ the dispatcher appends it to the candidate list and walks that list from the
95
+ end. So a viewport handler must not return `false` unless it really means to
96
+ swallow every pointer event in the game.
70
97
 
71
98
  The accepted event names are exactly `"pointerdown"`, `"pointerup"`,
72
99
  `"pointermove"`, `"pointercancel"`, `"pointerenter"`, `"pointerover"`,
@@ -76,6 +103,44 @@ throw `invalid event type`. melonJS maps the canonical name onto whichever
76
103
  mouse/touch events the device actually supports, so you always register the
77
104
  pointer name.
78
105
 
106
+ ## Which object gets the event
107
+
108
+ The dispatcher collects the regions near the pointer from the broadphase,
109
+ bounds-checks each one, orders them **the way they are drawn** and asks the
110
+ topmost first, walking down until something consumes.
111
+
112
+ A handler consumes by returning `false`. This is the DOM sense and it reads
113
+ backwards: `false` means handled, and anything else, `undefined` included, lets
114
+ the walk carry on to whatever is underneath.
115
+
116
+ ```js
117
+ input.registerPointerEvent("pointerdown", this, () => {
118
+ this.fire();
119
+ return false; // nothing under this gets the click
120
+ });
121
+ ```
122
+
123
+ Three things decide the order, and only the first is obvious:
124
+
125
+ - **`pos.z`, among siblings of one container.** Higher is on top.
126
+ - **Across containers, the common ancestor decides.** `pos.z` is
127
+ container-local, since `autoDepth` numbers each container's children from 1,
128
+ so a button at `z = 8` inside one panel does not outrank a second panel at
129
+ `z = 2`. The pair is resolved by walking both up to their shared parent and
130
+ comparing the two siblings there, which is exactly how drawing resolves it.
131
+ Raise a whole panel with `ancestor.moveToTop(panel)`, not by inflating a
132
+ child's `z`.
133
+ - **A child is asked before the container holding it**, since it draws over it.
134
+
135
+ Equal `z` between siblings falls back to child order, lower index on top. Two
136
+ callbacks registered on the **same** region for the same event run
137
+ last-registered-first.
138
+
139
+ Consuming a **move** also takes the pointer away from the regions below: each
140
+ one still holding it gets its `pointerleave`, because it is covered now and
141
+ being inside its own bounds no longer decides. Consuming a press, a release or a
142
+ wheel does not, since none of those says where the pointer is.
143
+
79
144
  ## World coordinates versus screen coordinates
80
145
 
81
146
  The pointer carries several, and picking the wrong one produces a feedback loop:
@@ -132,11 +197,80 @@ input.bindGamepad(0,
132
197
  ```
133
198
 
134
199
  **Order matters:** `bindGamepad` throws `no action defined for keycode N` if the
135
- keycode has not already been passed to `bindKey`. Axes use the same call with a
136
- threshold: `{ type: "axes", code: input.GAMEPAD.AXES.LX, threshold: -0.5 }`.
137
- `unbindGamepad(index, button)`, `setGamepadDeadzone(value)` and
200
+ keycode has not already been passed to `bindKey`.
201
+
202
+ Axes use the same call with a threshold, and bind **one half of the axis each**
203
+ — the sign selects which half:
204
+
205
+ ```js
206
+ input.bindGamepad(0, { type: "axes", code: input.GAMEPAD.AXES.LX, threshold: -0.15 }, input.KEY.LEFT);
207
+ input.bindGamepad(0, { type: "axes", code: input.GAMEPAD.AXES.LX, threshold: 0.15 }, input.KEY.RIGHT);
208
+ ```
209
+
210
+ **`threshold` is added to the deadzone, it does not replace it.** The test is
211
+ `abs(value) >= deadzone + abs(threshold)`, so with the default deadzone of 0.1
212
+ a threshold of `0.5` does not fire until 0.6 of full travel, and `0.15` fires at
213
+ 0.25. Pick the number you want the stick to break at and subtract the deadzone.
214
+ Raising `setGamepadDeadzone` moves every axis binding with it.
215
+
216
+ `unbindGamepad(index, button, type?)`, `setGamepadDeadzone(value)` and
138
217
  `setGamepadMapping(id, mapping)` complete the surface.
139
218
 
219
+ ### Which index to bind
220
+
221
+ Bindings are per pad **index**, and the index is plug order, not identity —
222
+ nothing reports which pad is "the" controller. Slot 0 is a guess: a wheel, a
223
+ spare pad or a keyboard-shaped device left plugged in can hold it for a whole
224
+ session while the player presses buttons on slot 1.
225
+
226
+ So a one-player game binds **every slot it will accept** to the same actions,
227
+ and lets `activeGamepad()` say which one is in use when something has to go
228
+ back the other way:
229
+
230
+ ```js
231
+ for (let pad = 0; pad < 4; pad++) {
232
+ input.bindGamepad(pad, { type: "buttons", code: input.GAMEPAD.BUTTONS.FACE_1 }, input.KEY.X);
233
+ }
234
+ input.activeGamepad(); // the last pad to produce a bound input, else the
235
+ // first connected one, else -1
236
+ ```
237
+
238
+ Binding spare slots costs nothing: the poll skips a bound index with no pad in
239
+ it. `activeGamepad()` follows **bound inputs only**, which is what makes it an
240
+ answer about the player rather than about electrical noise — a worn stick at
241
+ rest reports movement for ever and would otherwise claim to be the active pad.
242
+
243
+ ### Rumble
244
+
245
+ ```js
246
+ input.vibrateGamepad(input.activeGamepad(), {
247
+ duration: 120, strongMagnitude: 0.6, weakMagnitude: 0.9,
248
+ });
249
+ input.stopGamepadVibration(index); // cut a long effect short
250
+ input.hasGamepadVibration(index); // for an options-screen toggle
251
+ ```
252
+
253
+ Safe to call blind: no pad, no motors, or no Gamepad API at all resolves
254
+ `false` and does nothing, so game code never branches on support. Magnitudes
255
+ default to **full** — the underlying web API defaults every parameter to zero,
256
+ which makes a bare `playEffect` a silent no-op. A second call preempts the
257
+ first on the same pad, so a rapid series of hits reads as a rapid series of
258
+ hits rather than as a queue. For a SUSTAINED rumble issue one effect with a
259
+ long `duration` instead of calling every frame.
260
+
261
+ Hot-plugging needs no polling of your own — the engine listens for the browser's
262
+ own events and republishes them:
263
+
264
+ ```js
265
+ import { event } from "melonjs";
266
+
267
+ event.on(event.GAMEPAD_CONNECTED, (gamepad) => { /* gamepad.id, .index */ });
268
+ event.on(event.GAMEPAD_DISCONNECTED, (gamepad) => { /* pause, show a prompt */ });
269
+ ```
270
+
271
+ Bindings survive a disconnect: they are attached to the index, not to the
272
+ device, so a pad unplugged and plugged back into the same slot keeps working.
273
+
140
274
  ## Virtual controls
141
275
 
142
276
  On-screen buttons synthesise key events, again reaching the same actions:
@@ -159,6 +293,12 @@ input.triggerKeyEvent(input.KEY.LEFT, false); // release
159
293
  | jump fires every frame while held | `bindKey` without its third `lock` argument |
160
294
  | `invalid event type` thrown at registration | non-pointer name (`"click"`, `"mousedown"`, …) passed to `registerPointerEvent` |
161
295
  | `no action defined for keycode N` | `bindGamepad` called before `bindKey` for that keycode |
296
+ | stick has to be pushed well past its `threshold` before it registers | `threshold` is ADDED to the deadzone, not used instead of it |
297
+ | one half of a stick does nothing | each half is a separate `bindGamepad`, chosen by the sign of `threshold` |
298
+ | a widget under an overlapping panel still reacts | the panel consumes nothing — return `false` from its `onClick` and `onOver` |
299
+ | a widget stays highlighted after the pointer moves onto a panel over it | the panel consumes no `pointermove`, so nothing takes the pointer off the widget |
300
+ | a child's big `z` does not put it in front of another container | `pos.z` is container-local — use `ancestor.moveToTop()` on the container |
301
+ | every click in the game stops working | a handler on `app.viewport` returning `false`, which is asked first |
162
302
 
163
303
  ## Related skills
164
304
 
@@ -0,0 +1,313 @@
1
+ ---
2
+ name: melonjs-math
3
+ description: "Use this skill for vector and matrix maths in melonJS — Vector2d, Vector3d, their observable variants, Matrix2d, Matrix3d, and the math utility functions. Covers which methods mutate and which allocate, the vector pool and when clone() is the wrong tool, interpolation with lerp, slerp, damp and moveTowards, and the argument defaults that silently drop a component. Triggers on: Vector2d, Vector3d, ObservableVector2d, ObservableVector3d, Matrix2d, Matrix3d, vector, vector maths, dot, cross, normalize, length, distance, angle, lerp, slerp, damp, moveTowards, project, clamp, degToRad, radToDeg, clone, vector pool, vector3dPool, setMuted, setCallback, my vector is wrong, z is zero, scale ignores z., moveTowards ignores z, projectN, currentTransform, setTransform, matrix, transform matrix, column-major, val, Float32Array, basis matrix, orientation matrix."
4
+ license: MIT
5
+ ---
6
+
7
+ # Vectors, matrices and maths
8
+
9
+ ## The one rule that explains most surprises
10
+
11
+ **Methods mutate `this` and return it. They do not return a new vector.**
12
+
13
+ ```js
14
+ const a = new Vector3d(1, 0, 0);
15
+ const b = new Vector3d(0, 1, 0);
16
+
17
+ a.cross(b); // a IS NOW the cross product; the original a is gone
18
+ a.add(b).normalize().scale(3, 3, 3); // chains, all in place
19
+ ```
20
+
21
+ That is what makes the API allocation-free, and it is the opposite of what a
22
+ functional style expects. If you need to keep the original, copy into
23
+ something you own first:
24
+
25
+ ```js
26
+ out.copy(a).cross(b); // a untouched, nothing allocated
27
+ ```
28
+
29
+ **The exceptions are named.** A handful of methods return a NEW vector, and
30
+ each has a `*Self` sibling that does not:
31
+
32
+ | allocates a new vector | mutates in place |
33
+ |---|---|
34
+ | `negate()` | `negateSelf()` |
35
+ | `floor()` | `floorSelf()` |
36
+ | `ceil()` | `ceilSelf()` |
37
+ | `clamp(low, high)` | `clampSelf(low, high)` |
38
+ | `clone()` | `copy(v)` |
39
+
40
+ So `v.negate()` in a per-frame loop allocates every frame and `v.negateSelf()`
41
+ does not. The names are the only clue; nothing in the call site shows it.
42
+
43
+ ## `clone()` comes from a pool, and only pays off if you give it back
44
+
45
+ `clone()` is `vector3dPool.get(...)`. A pool is fast when instances come back:
46
+ `get()` takes a free one and resets it. Nothing comes back on its own, so a
47
+ clone that is simply dropped makes `get()` miss, construct, and write two
48
+ registry entries.
49
+
50
+ Measured, 3M operations:
51
+
52
+ | | |
53
+ |---|---|
54
+ | `out.copy(a).cross(b)` | 39ms |
55
+ | `new Vector3d(ax, ay, az).cross(b)` | 37ms |
56
+ | `a.clone().cross(b)` | **2919ms** |
57
+
58
+ So:
59
+
60
+ - **Transient value inside a function?** Use a module-level scratch vector, or
61
+ `new Vector3d()`. Not `clone()`.
62
+ - **Keeping it, then done with it?** `clone()` and `vector3dPool.release(v)`
63
+ when finished. Releasing is what makes the pool a pool.
64
+ - **Writing a helper that returns a vector?** Take an optional `out`:
65
+
66
+ ```js
67
+ const cross = (a, b, out = new Vector3d()) => out.copy(a).cross(b);
68
+ ```
69
+
70
+ That is the engine's own convention, and it lets a hot caller supply scratch
71
+ while a casual one ignores it.
72
+
73
+ **A returned value can never be shared scratch.** The next call overwrites
74
+ something the caller is still holding, and nothing fails loudly:
75
+
76
+ ```js
77
+ const _t = new Vector3d();
78
+ const bad = (v) => _t.copy(v).normalize(); // WRONG: two calls alias
79
+ ```
80
+
81
+ ## Argument defaults that drop a component
82
+
83
+ Three signatures quietly discard what you did not pass. All three are
84
+ reachable by writing the obvious thing.
85
+
86
+ **`scale(x, y = x, z = 1)`** — `z` defaults to **1**, not to `x`. A uniform
87
+ scale has to say so three times:
88
+
89
+ ```js
90
+ v.scale(2); // (1,2,3) -> (2,4,3) z UNTOUCHED
91
+ v.scale(2, 2, 2); // (1,2,3) -> (2,4,6) what you meant
92
+ ```
93
+
94
+ **`set(x, y, z = 0)`** — setting two components **zeroes the third**:
95
+
96
+ ```js
97
+ v.set(10, 20); // z is now 0, whatever it was
98
+ ```
99
+
100
+ **`Vector3d.pos` on a renderable is typed `Vector2d`.** `Renderable.pos` is an
101
+ `ObservableVector3d` at run time but is declared through `Polygon` as a
102
+ `Vector2d`, so `.z`, `.setMuted` and `.setCallback` need a cast from
103
+ TypeScript. See issue #1510.
104
+
105
+ ## `cross` is two different functions
106
+
107
+ ```js
108
+ v3.cross(other); // Vector3d: MUTATES v3, returns this
109
+ v2.cross(other); // Vector2d: returns a NUMBER, mutates nothing
110
+ ```
111
+
112
+ The 2D one is the z component of the 3D cross, which is the useful scalar for
113
+ "which side is this on". Same name, different shape, different return.
114
+
115
+ ## Interpolation: four of them, and they are not interchangeable
116
+
117
+ ```js
118
+ a.lerp(b, t); // straight line, t in 0..1
119
+ a.slerp(b, t); // along the ARC, constant angular rate
120
+ a.damp(b, lambda, dt); // frame-rate independent ease toward b
121
+ a.moveTowards(b, step); // fixed distance per call, never overshoots
122
+ ```
123
+
124
+ **`moveTowards` is X/Y ONLY, on `Vector3d` as well as `Vector2d`.** It is the
125
+ one of the four that is not 3D: it measures the distance from `dx` and `dy`,
126
+ steps along `atan2(dy, dx)`, and leaves `z` exactly where it was. The source
127
+ says so in a comment and the JSDoc says "on the x and y axis", but the name
128
+ gives no hint, and in a list like the one above it reads as the sibling of the
129
+ other three. Anything moving in three dimensions wants `damp` or an explicit
130
+ step; reach for `moveTowards` only when the motion really is planar.
131
+
132
+ **`lerp` between two directions is uneven**: it slows at the ends, runs fast
133
+ through the middle, and shortens the vector as it passes halfway. Anything
134
+ whose direction matters more than its components wants `slerp` — a camera
135
+ swinging to look somewhere, a turret tracking, a body moving over a sphere.
136
+ `slerp` carries length linearly, so two unit vectors give a unit vector and
137
+ nothing needs normalising afterwards.
138
+
139
+ **`damp` is the one to use for "ease toward a target every frame"**, because
140
+ `lerp(current, target, 0.1)` per frame is frame-rate dependent: it converges
141
+ twice as fast at 120fps as at 60.
142
+
143
+ ## `project` scales THIS, and `projectN` is the one without the divide
144
+
145
+ `a.project(b)` does not return the component of `a` along `b`. It scales **a**
146
+ by `a.b / |b|^2` and returns `a`, so the result points along `a`, not along
147
+ `b`. Worth knowing before you reach for it expecting the textbook projection.
148
+
149
+ `projectN(v)` is the same thing for a `v` that is already unit, so it skips
150
+ the `/ v.length2()`:
151
+
152
+ ```js
153
+ a.project(b); // a scaled by (a.b / |b|^2)
154
+ a.projectN(b); // a scaled by (a.b) -- only correct when |b| = 1
155
+ ```
156
+
157
+ Handing `projectN` a target that is NOT unit does not normalise anything, it
158
+ just scales by the raw dot product. That is the price of it being cheaper, and
159
+ it is the caller's job to meet the contract.
160
+
161
+ Until 20.9 both 3D classes got this wrong: `Vector3d.projectN` and
162
+ `ObservableVector3d.projectN` were copies of `project`, division and all,
163
+ under `projectN`'s name and its "slightly more efficient" doc comment. Nothing
164
+ in the engine called either one and nothing tested them, which is how it
165
+ survived. Both are fixed and all four classes are now pinned by tests.
166
+
167
+ ## `length()` is `sqrt(x*x + y*y + z*z)`
168
+
169
+ Fast and correct to 1 ULP for anything a game holds. It is NOT robust at
170
+ extremes: components above ~1e154 overflow to `Infinity` and below ~1e-162
171
+ underflow to `0`, because the squares are formed before the root. `Math.hypot`
172
+ avoids that and costs 35 to 65% more. The engine takes the speed, which is the
173
+ right trade for coordinates between 1e-3 and 1e6; nothing in a game is 148
174
+ orders of magnitude from unit scale.
175
+
176
+ `length2()` skips the square root. Use it for comparisons:
177
+
178
+ ```js
179
+ if (a.distance(b) < r) { } // a square root you did not need
180
+ if (a.sub(b).length2() < r * r) { } // same answer, cheaper
181
+ ```
182
+
183
+ ## Observable vectors
184
+
185
+ `ObservableVector2d` / `ObservableVector3d` call a callback on every write,
186
+ which is how a renderable knows its bounds went stale.
187
+
188
+ ```js
189
+ v.setCallback(() => { ... });
190
+ v.setMuted(true); // write without firing it
191
+ ```
192
+
193
+ **`setMuted` is what you want when writing several components**, so a
194
+ half-updated vector does not fire a callback that reads the other half.
195
+ `set()` already does this internally: it disables the callback, writes all
196
+ three, fires once, and re-enables.
197
+
198
+ Note the observable `set(x = 0, y = 0, z = 0)` defaults EVERY argument, so
199
+ `set(10, 20)` zeroes z exactly as the plain vector does.
200
+
201
+ ## Matrices
202
+
203
+ `Matrix2d` is 3x3 for 2D affine transforms; `Matrix3d` is 4x4. Both mutate and
204
+ chain, same as vectors, and both come from pools.
205
+
206
+ ```js
207
+ m.identity().translate(x, y).rotate(angle).scale(sx, sy);
208
+ ```
209
+
210
+ **Order is the reverse of how it reads.** These post-multiply, so the call
211
+ made LAST reaches the vertex FIRST. To rotate a thing about its own centre,
212
+ translate to the centre last.
213
+
214
+ ### Every renderable already HAS one
215
+
216
+ `Renderable.currentTransform` is a `Matrix3d`. If you are orienting something
217
+ on screen, the matrix exists: write into it rather than building a parallel
218
+ structure and copying.
219
+
220
+ ```js
221
+ // the whole transform of a renderable, written in place
222
+ mesh.currentTransform.identity().translate(x, y, z).rotate(angle, axis);
223
+ ```
224
+
225
+ ### The sixteen numbers are `val`, column-major
226
+
227
+ Composing with `translate`/`rotate`/`scale` is one way to fill a matrix. The
228
+ other is to write the numbers, which is what you want when the orientation
229
+ comes from a basis you have already computed — three orthonormal vectors, a
230
+ surface frame, a camera basis.
231
+
232
+ `val` is a `Float32Array(16)` in **column-major** order, the OpenGL
233
+ convention: each basis vector occupies a stride-4 run, and the translation is
234
+ the last column.
235
+
236
+ | | X column | Y column | Z column | translation |
237
+ |---|---|---|---|---|
238
+ | indices | `0,1,2` | `4,5,6` | `8,9,10` | `12,13,14` |
239
+
240
+ ```js
241
+ // an orientation from three axes, straight into the renderable's own matrix
242
+ const m = mesh.currentTransform.val;
243
+ m[0] = right.x; m[1] = right.y; m[2] = right.z; m[3] = 0;
244
+ m[4] = up.x; m[5] = up.y; m[6] = up.z; m[7] = 0;
245
+ m[8] = fwd.x; m[9] = fwd.y; m[10] = fwd.z; m[11] = 0;
246
+ m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
247
+ ```
248
+
249
+ A helper that builds one should take the destination, the same way the engine
250
+ takes an `out`, so it writes once into the matrix that will be used:
251
+
252
+ ```js
253
+ const orient = (frame, out) => { /* writes out.val */ return out; };
254
+ orient(frame, mesh.currentTransform);
255
+ ```
256
+
257
+ ### Getting numbers IN from somewhere else
258
+
259
+ `setTransform(...)` takes the sixteen as arguments, and `copy(m)` takes
260
+ another matrix:
261
+
262
+ ```js
263
+ m.setTransform(a, b, c, d, e, f, g, h, i, j, k, l, p, q, r, s);
264
+ m.copy(other); // Float32Array.set under the hood
265
+ ```
266
+
267
+ Both are fine occasionally. In a per-frame loop, prefer writing `val` or
268
+ `copy()` over spreading sixteen arguments, and note that **one matrix built
269
+ once and applied to many renderables** is a `copy()` per renderable, not a
270
+ rebuild per renderable.
271
+
272
+ **`val` is `Float32Array`, so it holds float32.** Numbers you put in are
273
+ rounded to single precision. That is where they were always heading, since
274
+ this is what reaches the GPU, but it means a value read back out is not
275
+ bit-identical to the double you wrote.
276
+
277
+ ## Utilities
278
+
279
+ ```js
280
+ import { math } from "melonjs";
281
+
282
+ math.clamp(v, lo, hi);
283
+ math.lerp(a, b, t); // scalars
284
+ math.damp(a, b, lambda, dt); // frame-rate independent
285
+ math.degToRad(deg); math.radToDeg(rad);
286
+ math.random(lo, hi); // integer
287
+ math.randomFloat(lo, hi);
288
+ math.weightedRandom(lo, hi); // integer, biased toward LO
289
+ math.round(n, decimals);
290
+ math.pow(n); // n squared
291
+ math.DEG_TO_RAD math.RAD_TO_DEG math.TAU math.ETA math.EPSILON
292
+ ```
293
+
294
+ ## Symptoms
295
+
296
+ | symptom | cause |
297
+ |---|---|
298
+ | z unchanged after scaling | `scale(s)` leaves z alone; pass `scale(s, s, s)` |
299
+ | z became 0 for no reason | `set(x, y)` defaults z to 0 |
300
+ | the original vector changed | the method mutates; `copy()` into something first |
301
+ | memory climbs in a loop | `clone()` or `negate()`/`floor()`/`ceil()` per frame |
302
+ | two helper results are the same object | a shared scratch vector was returned |
303
+ | `.z` is a type error | `Renderable.pos` is declared `Vector2d` (#1510) |
304
+ | rotation eases oddly between directions | `lerp` on directions; use `slerp` |
305
+ | you built your own 16-number array | `Renderable.currentTransform` is already a `Matrix3d`; write its `val` |
306
+ | a value read back from a matrix differs | `val` is `Float32Array`; it holds float32 |
307
+ | easing differs at 120fps | per-frame `lerp`; use `damp` |
308
+
309
+ ## Related skills
310
+
311
+ - `melonjs-3d` — `Camera3d`, meshes, and where these vectors are used in 3D
312
+ - `melonjs-physics` — bodies, velocities and collision response
313
+ - `melonjs-performance` — pooling in general, and what release() is for