melonjs 20.10.1 → 20.12.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 (214) hide show
  1. package/README.md +4 -5
  2. package/build/application/application.d.ts.map +1 -1
  3. package/build/application/defaultApplicationSettings.d.ts +1 -0
  4. package/build/application/defaultApplicationSettings.d.ts.map +1 -1
  5. package/build/application/settings.d.ts +54 -3
  6. package/build/application/settings.d.ts.map +1 -1
  7. package/build/audio/audio.d.ts +14 -4
  8. package/build/audio/audio.d.ts.map +1 -1
  9. package/build/audio/backend/sound.d.ts.map +1 -1
  10. package/build/audio/playback.d.ts.map +1 -1
  11. package/build/audio/spatial.d.ts +13 -2
  12. package/build/audio/spatial.d.ts.map +1 -1
  13. package/build/audio/types.d.ts +44 -4
  14. package/build/audio/types.d.ts.map +1 -1
  15. package/build/camera/camera2d.d.ts +48 -4
  16. package/build/camera/camera2d.d.ts.map +1 -1
  17. package/build/camera/camera3d.d.ts.map +1 -1
  18. package/build/camera/effects/pixelate_transition_effect.d.ts +67 -0
  19. package/build/camera/effects/pixelate_transition_effect.d.ts.map +1 -0
  20. package/build/camera/effects/shake_effect.d.ts +3 -1
  21. package/build/camera/effects/shake_effect.d.ts.map +1 -1
  22. package/build/geometries/ellipse.d.ts +8 -4
  23. package/build/geometries/ellipse.d.ts.map +1 -1
  24. package/build/geometries/line.d.ts +2 -2
  25. package/build/geometries/line.d.ts.map +1 -1
  26. package/build/geometries/polygon.d.ts +3 -3
  27. package/build/geometries/polygon.d.ts.map +1 -1
  28. package/build/geometries/rectangle.d.ts +2 -2
  29. package/build/geometries/rectangle.d.ts.map +1 -1
  30. package/build/geometries/roundrect.d.ts +2 -2
  31. package/build/geometries/roundrect.d.ts.map +1 -1
  32. package/build/index.d.ts +5 -2
  33. package/build/index.d.ts.map +1 -1
  34. package/build/index.js +9944 -6234
  35. package/build/index.js.map +4 -4
  36. package/build/input/gamepad.d.ts.map +1 -1
  37. package/build/input/pointerevent.d.ts.map +1 -1
  38. package/build/lang/console.d.ts +16 -1
  39. package/build/lang/console.d.ts.map +1 -1
  40. package/build/level/tiled/TMXLayer.d.ts +1 -1
  41. package/build/level/tiled/TMXLayer.d.ts.map +1 -1
  42. package/build/level/tiled/TMXObject.d.ts +196 -1
  43. package/build/level/tiled/TMXObject.d.ts.map +1 -1
  44. package/build/level/tiled/TMXObjectFactory.d.ts +18 -5
  45. package/build/level/tiled/TMXObjectFactory.d.ts.map +1 -1
  46. package/build/level/tiled/TMXTile.d.ts.map +1 -1
  47. package/build/level/tiled/TMXTileMap.d.ts.map +1 -1
  48. package/build/level/tiled/TMXTileset.d.ts +17 -1
  49. package/build/level/tiled/TMXTileset.d.ts.map +1 -1
  50. package/build/level/tiled/TMXUtils.d.ts.map +1 -1
  51. package/build/level/tiled/factories/shape.d.ts.map +1 -1
  52. package/build/level/tiled/renderer/TMXIsometricRenderer.d.ts.map +1 -1
  53. package/build/level/tiled/renderer/TMXObliqueRenderer.d.ts.map +1 -1
  54. package/build/level/tiled/renderer/TMXOrthogonalRenderer.d.ts.map +1 -1
  55. package/build/level/tiled/renderer/TMXRenderer.d.ts.map +1 -1
  56. package/build/lighting/light2d.d.ts +30 -0
  57. package/build/lighting/light2d.d.ts.map +1 -1
  58. package/build/loader/loadingscreen.d.ts.map +1 -1
  59. package/build/math/matrix2d.d.ts +3 -2
  60. package/build/math/matrix2d.d.ts.map +1 -1
  61. package/build/math/matrix3d.d.ts +4 -1
  62. package/build/math/matrix3d.d.ts.map +1 -1
  63. package/build/particles/emitter.d.ts.map +1 -1
  64. package/build/particles/particle.d.ts.map +1 -1
  65. package/build/particles/settings.d.ts +25 -0
  66. package/build/particles/settings.d.ts.map +1 -1
  67. package/build/physics/bounds.d.ts +5 -5
  68. package/build/physics/bounds.d.ts.map +1 -1
  69. package/build/physics/builtin/body.d.ts +1 -0
  70. package/build/physics/builtin/body.d.ts.map +1 -1
  71. package/build/physics/builtin/builtin-adapter.d.ts.map +1 -1
  72. package/build/physics/builtin/detector.d.ts.map +1 -1
  73. package/build/physics/builtin/raycast.d.ts.map +1 -1
  74. package/build/physics/builtin/sat.d.ts +40 -1
  75. package/build/physics/builtin/sat.d.ts.map +1 -1
  76. package/build/renderable/animation.d.ts +16 -2
  77. package/build/renderable/animation.d.ts.map +1 -1
  78. package/build/renderable/colorlayer.d.ts.map +1 -1
  79. package/build/renderable/container.d.ts +22 -2
  80. package/build/renderable/container.d.ts.map +1 -1
  81. package/build/renderable/entity/entity.d.ts.map +1 -1
  82. package/build/renderable/frameAnimation.d.ts.map +1 -1
  83. package/build/renderable/imagelayer.d.ts.map +1 -1
  84. package/build/renderable/instanced_mesh.d.ts.map +1 -1
  85. package/build/renderable/mesh.d.ts.map +1 -1
  86. package/build/renderable/renderable.d.ts +69 -1
  87. package/build/renderable/renderable.d.ts.map +1 -1
  88. package/build/renderable/sprite.d.ts +23 -7
  89. package/build/renderable/sprite.d.ts.map +1 -1
  90. package/build/renderable/sprite3d.d.ts +5 -3
  91. package/build/renderable/sprite3d.d.ts.map +1 -1
  92. package/build/renderable/text/text.d.ts.map +1 -1
  93. package/build/renderable/trail3d.d.ts.map +1 -1
  94. package/build/renderable/ui/uipanel.d.ts +3 -3
  95. package/build/renderable/ui/uipanel.d.ts.map +1 -1
  96. package/build/state/stage.d.ts +12 -4
  97. package/build/state/stage.d.ts.map +1 -1
  98. package/build/state/state.d.ts +31 -6
  99. package/build/state/state.d.ts.map +1 -1
  100. package/build/system/legacy_pool.d.ts.map +1 -1
  101. package/build/system/timer.d.ts +1 -0
  102. package/build/system/timer.d.ts.map +1 -1
  103. package/build/utils/fetchdata.d.ts.map +1 -1
  104. package/build/video/buffer/vertex.d.ts.map +1 -1
  105. package/build/video/canvas/canvas_renderer.d.ts +8 -7
  106. package/build/video/canvas/canvas_renderer.d.ts.map +1 -1
  107. package/build/video/effects/ambientlight.d.ts +2 -0
  108. package/build/video/effects/ambientlight.d.ts.map +1 -0
  109. package/build/video/effects/bloom.d.ts +8 -9
  110. package/build/video/effects/bloom.d.ts.map +1 -1
  111. package/build/video/effects/blur.d.ts +3 -2
  112. package/build/video/effects/blur.d.ts.map +1 -1
  113. package/build/video/effects/chromaticAberration.d.ts +3 -2
  114. package/build/video/effects/chromaticAberration.d.ts.map +1 -1
  115. package/build/video/effects/dissolve.d.ts +5 -2
  116. package/build/video/effects/dissolve.d.ts.map +1 -1
  117. package/build/video/effects/dropShadow.d.ts +15 -3
  118. package/build/video/effects/dropShadow.d.ts.map +1 -1
  119. package/build/video/effects/flash.d.ts +6 -2
  120. package/build/video/effects/flash.d.ts.map +1 -1
  121. package/build/video/effects/frame.d.ts +48 -0
  122. package/build/video/effects/frame.d.ts.map +1 -0
  123. package/build/video/effects/glow.d.ts +8 -4
  124. package/build/video/effects/glow.d.ts.map +1 -1
  125. package/build/video/effects/glsl_realization.d.ts.map +1 -1
  126. package/build/video/effects/hologram.d.ts +5 -2
  127. package/build/video/effects/hologram.d.ts.map +1 -1
  128. package/build/video/effects/local_space.d.ts +19 -0
  129. package/build/video/effects/local_space.d.ts.map +1 -0
  130. package/build/video/effects/mesh_splice.d.ts.map +1 -1
  131. package/build/video/effects/outline.d.ts +8 -4
  132. package/build/video/effects/outline.d.ts.map +1 -1
  133. package/build/video/effects/pixelate.d.ts +3 -2
  134. package/build/video/effects/pixelate.d.ts.map +1 -1
  135. package/build/video/effects/radialGradient.d.ts +13 -16
  136. package/build/video/effects/radialGradient.d.ts.map +1 -1
  137. package/build/video/effects/rgba.d.ts +2 -0
  138. package/build/video/effects/rgba.d.ts.map +1 -0
  139. package/build/video/effects/scanline.d.ts.map +1 -1
  140. package/build/video/effects/shadereffect.d.ts +13 -0
  141. package/build/video/effects/shadereffect.d.ts.map +1 -1
  142. package/build/video/effects/shine.d.ts +10 -2
  143. package/build/video/effects/shine.d.ts.map +1 -1
  144. package/build/video/effects/squish.d.ts.map +1 -1
  145. package/build/video/effects/sway.d.ts +69 -0
  146. package/build/video/effects/sway.d.ts.map +1 -0
  147. package/build/video/effects/tintPulse.d.ts +5 -2
  148. package/build/video/effects/tintPulse.d.ts.map +1 -1
  149. package/build/video/effects/vignette.d.ts.map +1 -1
  150. package/build/video/effects/wave.d.ts +21 -2
  151. package/build/video/effects/wave.d.ts.map +1 -1
  152. package/build/video/effects/wgsl/parse.d.ts.map +1 -1
  153. package/build/video/effects/wgsl/scaffold.d.ts.map +1 -1
  154. package/build/video/effects/wgsl_realization.d.ts.map +1 -1
  155. package/build/video/gpu/frame.d.ts +2 -0
  156. package/build/video/gpu/frame.d.ts.map +1 -0
  157. package/build/video/renderer.d.ts +37 -12
  158. package/build/video/renderer.d.ts.map +1 -1
  159. package/build/video/rendertarget/canvasrendertarget.d.ts +14 -4
  160. package/build/video/rendertarget/canvasrendertarget.d.ts.map +1 -1
  161. package/build/video/rendertarget/rendertarget.d.ts +12 -16
  162. package/build/video/rendertarget/rendertarget.d.ts.map +1 -1
  163. package/build/video/rendertarget/webgpurendertarget.d.ts +1 -0
  164. package/build/video/rendertarget/webgpurendertarget.d.ts.map +1 -1
  165. package/build/video/texture/atlas.d.ts +47 -28
  166. package/build/video/texture/atlas.d.ts.map +1 -1
  167. package/build/video/texture/cache.d.ts.map +1 -1
  168. package/build/video/utils/pixel_snap.d.ts +44 -0
  169. package/build/video/utils/pixel_snap.d.ts.map +1 -0
  170. package/build/video/webgl/batchers/batcher.d.ts.map +1 -1
  171. package/build/video/webgl/batchers/lit_quad_batcher.d.ts.map +1 -1
  172. package/build/video/webgl/batchers/material_batcher.d.ts.map +1 -1
  173. package/build/video/webgl/batchers/mesh_batcher.d.ts.map +1 -1
  174. package/build/video/webgl/batchers/quad_batcher.d.ts +2 -1
  175. package/build/video/webgl/batchers/quad_batcher.d.ts.map +1 -1
  176. package/build/video/webgl/glshader.d.ts.map +1 -1
  177. package/build/video/webgl/renderers/tmxlayer/orthogonal.d.ts.map +1 -1
  178. package/build/video/webgl/shaders/frameclamp.d.ts +2 -0
  179. package/build/video/webgl/shaders/frameclamp.d.ts.map +1 -0
  180. package/build/video/webgl/shaders/multitexture-lit.d.ts.map +1 -1
  181. package/build/video/webgl/shaders/multitexture.d.ts.map +1 -1
  182. package/build/video/webgl/utils/uniforms.d.ts.map +1 -1
  183. package/build/video/webgl/webgl_renderer.d.ts +0 -21
  184. package/build/video/webgl/webgl_renderer.d.ts.map +1 -1
  185. package/build/video/webgpu/batchers/lit_quad_batcher.d.ts +2 -1
  186. package/build/video/webgpu/batchers/lit_quad_batcher.d.ts.map +1 -1
  187. package/build/video/webgpu/batchers/mesh_batcher.d.ts +0 -1
  188. package/build/video/webgpu/batchers/mesh_batcher.d.ts.map +1 -1
  189. package/build/video/webgpu/batchers/quad_batcher.d.ts +2 -2
  190. package/build/video/webgpu/batchers/quad_batcher.d.ts.map +1 -1
  191. package/build/video/webgpu/buffer/uniformring.d.ts.map +1 -1
  192. package/build/video/webgpu/effect_binding.d.ts.map +1 -1
  193. package/build/video/webgpu/renderers/tmxlayer/orthogonal.d.ts.map +1 -1
  194. package/build/video/webgpu/webgpu_renderer.d.ts +3 -4
  195. package/build/video/webgpu/webgpu_renderer.d.ts.map +1 -1
  196. package/package.json +21 -19
  197. package/skills/AGENTS.md +2 -1
  198. package/skills/melonjs/SKILL.md +1 -0
  199. package/skills/melonjs-audio/SKILL.md +47 -5
  200. package/skills/melonjs-camera-and-drawing/SKILL.md +63 -1
  201. package/skills/melonjs-display-and-scaling/SKILL.md +117 -7
  202. package/skills/melonjs-effects-and-shaders/SKILL.md +136 -19
  203. package/skills/melonjs-input/SKILL.md +24 -2
  204. package/skills/melonjs-lighting/SKILL.md +43 -8
  205. package/skills/melonjs-loading-assets/SKILL.md +4 -3
  206. package/skills/melonjs-math/SKILL.md +21 -1
  207. package/skills/melonjs-particles-and-trails/SKILL.md +36 -2
  208. package/skills/melonjs-performance/SKILL.md +4 -0
  209. package/skills/melonjs-plugins/SKILL.md +20 -1
  210. package/skills/melonjs-renderables/SKILL.md +46 -6
  211. package/skills/melonjs-renderer-backends/SKILL.md +2 -2
  212. package/skills/melonjs-scenes-and-state/SKILL.md +17 -2
  213. package/skills/melonjs-sprites-and-animation/SKILL.md +19 -3
  214. package/skills/melonjs-tilemaps/SKILL.md +126 -4
@@ -50,7 +50,10 @@ a transition's reveal follow once the shaders the stage queued are ready, which
50
50
  is a few milliseconds once the browser has compiled them before, and at most
51
51
  1.5s on a first visit. So build the stage in `onResetEvent`: an object a
52
52
  `STATE_CHANGE` listener adds is not waited for, and its first draw may still
53
- compile what it needs.
53
+ compile what it needs. That first frame steps the world once before drawing it,
54
+ however short it is, so everything `onResetEvent` added is in it (the same goes
55
+ for the frame after a `level.load` made while the game runs). Before 20.12 it
56
+ was drawn unstepped, and showed the stage's background alone for one frame.
54
57
 
55
58
  `state.change` **throws** `Undefined Stage for state '<id>'` if nothing was
56
59
  registered for that id, and `state.set` throws if the second argument is not a
@@ -109,6 +112,7 @@ app.world.addChild(this.HUD, 100); // explicit z — see melonjs-renderable
109
112
  ```js
110
113
  state.transition("fade", "#FFFFFF", 250);
111
114
  state.transition("mask", "#000", 500, new Ellipse(0, 0, 1, 1)); // shape required
115
+ state.transition("pixelate", "#000", 300); // blocks up to 32px; a 4th argument sets the size
112
116
  state.pause(); // freeze update, keep drawing
113
117
  state.resume();
114
118
  app.freeze(150); // brief hit-stop (proxies state.freeze)
@@ -116,7 +120,18 @@ app.freeze(150); // brief hit-stop (proxies state.fr
116
120
 
117
121
  `state.transition` is global and sticky — once set it applies to every later
118
122
  `state.change`. The `"mask"` form needs its fourth argument, an `Ellipse` or
119
- `Polygon`; without one it warns and falls back to a direct switch.
123
+ `Polygon`; without one it warns and falls back to a direct switch. The
124
+ `"pixelate"` form breaks the screen up into blocks (its fourth argument is the
125
+ largest block size in pixels). It is a shader effect, so on Canvas it does
126
+ nothing and the state changes directly.
127
+
128
+ A `state.change` asked for while a transition covers the screen (Enter pressed
129
+ twice on a menu, a timer firing as the player skips a screen) needs no guard:
130
+ the transition already under way makes it, switching to the last state asked
131
+ for with the last arguments, and a second cover never goes up. A change to a
132
+ state with no transition of its own (`state.setTransition(id, false)`) is made
133
+ at once, and the cover comes down with it. Before 20.12 the second change left
134
+ the first cover on the camera for good, the screen black over a running game.
120
135
 
121
136
  ### A Stage's own `update()` is NOT paused
122
137
 
@@ -59,6 +59,10 @@ hero.setCurrentAnimation("walk");
59
59
  hero.setCurrentAnimation("die", "idle"); // chain to idle when it ends
60
60
  hero.setCurrentAnimation("die", { loop: false }); // play once, hold the last frame
61
61
  hero.setCurrentAnimation("die", { loop: false, onComplete: fn }); // …and call fn when it does
62
+ hero.setCurrentAnimation("use", { next: "idle", onComplete: fn }); // call fn, then chain to idle
63
+ hero.setCurrentAnimation("run", { onFrame: (frame) => { // each frame playback reaches
64
+ if (frame === 3 || frame === 8) footstep();
65
+ } });
62
66
 
63
67
  if (hero.isCurrentAnimation("walk")) { /* … */ }
64
68
  ```
@@ -71,13 +75,25 @@ accepted — passing region names throws.
71
75
 
72
76
  The second argument to `setCurrentAnimation` is polymorphic. A **string** chains
73
77
  to that animation when this one ends. An **options object** takes
74
- `{ loop, next, speed, onComplete }`, and only an explicit `loop: false` stops the
75
- looping. A **bare function** is the legacy form: it fires at *every* cycle end,
78
+ `{ loop, next, speed, onComplete, onFrame }`, and only an explicit `loop: false`
79
+ stops the looping. A **bare function** is the legacy form: it fires at *every* cycle end,
76
80
  and only holds the last frame if it returns `false`. Omit the argument entirely
77
81
  and the animation loops forever.
78
82
 
83
+ `onFrame(frame)` is called with frame 0 when the animation starts, then with each
84
+ frame playback reaches, so a footstep or a hit lands on its frame without polling
85
+ `getCurrentAnimationFrame()`. A long tick reports every frame it goes past. It is
86
+ not called for a frame set with `setAnimationFrame`, nor for the frame 0 a
87
+ play-once animation would wrap to. Keep the callback in a field when you call
88
+ `setCurrentAnimation` every frame: re-selecting keeps the first one anyway.
89
+
90
+ With both `next` and `onComplete`, the callback runs first and the chained
91
+ animation starts with none of its own, so a one-off action (a pickup, an
92
+ attack) needs no manual switch back to idle.
93
+
79
94
  Re-selecting the animation that is already current is a no-op, so calling
80
- `setCurrentAnimation` every frame is safe. An unknown id throws.
95
+ `setCurrentAnimation` every frame is safe, and an `isCurrentAnimation` check
96
+ around it adds nothing. An unknown id throws.
81
97
 
82
98
  ## Texture atlases
83
99
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: melonjs-tilemaps
3
- description: "Use this skill for Tiled maps in melonJS — loading TMX/TSX levels, spawning entities from Tiled objects, collision shapes authored in Tiled, isometric and hexagonal maps, and image layers. Covers registerTiledObjectClass and the pool.register name contract, camera bounds, compressed maps needing the inflate plugin, and the level director API. Triggers on: Tiled, TMX, TSX, tilemap, level.load, level.load async, await level.load, tileset, ImageLayer, isometric, hexagonal, staggered, pool.register, Collectable, Trigger, object layer, collision layer, parallax, registerTiledObjectClass, registerTiledObjectFactory."
3
+ description: "Use this skill for Tiled maps in melonJS — loading TMX/TSX levels, spawning entities from Tiled objects, collision shapes authored in Tiled, isometric and hexagonal maps, and image layers. Covers registerTiledObjectClass and the pool.register name contract, camera bounds, compressed maps needing the inflate plugin, and the level director API. Triggers on: Tiled, TMX, TSX, tilemap, level.load, level.load async, await level.load, tileset, ImageLayer, isometric, hexagonal, staggered, pool.register, Collectable, Trigger, object layer, collision layer, parallax, registerTiledObjectClass, registerTiledObjectFactory, TMXObject, resolvedProperty, resolvedProperties, tile class, tile properties."
4
4
  license: MIT
5
5
  ---
6
6
 
@@ -72,7 +72,8 @@ object group in its own `Container` named after the group.
72
72
  ## Spawning entities from Tiled objects
73
73
 
74
74
  Objects are matched against a factory registry, in this order: the object's
75
- Tiled **class**, then its **name**, then the structural fallbacks `"text"`,
75
+ Tiled **class**, then its **name**, then, for a tile object with no class of
76
+ its own, its **tile's class**, then the structural fallbacks `"text"`,
76
77
  `"tile"` and `"shape"`.
77
78
 
78
79
  ```js
@@ -122,6 +123,53 @@ registerTiledObjectClass("Trigger", MyTrigger); // whenever you like
122
123
  The throw is for a clash between two of *your* classes under one name. For
123
124
  that case `registerTiledObjectFactory` overwrites and only warns.
124
125
 
126
+ ### Classes and properties set on tiles
127
+
128
+ In Tiled, a tile can carry a class and custom properties (tileset editor), and
129
+ every object placed from that tile shows them as its own. melonJS follows:
130
+
131
+ - **The tile's class.** A tile object with no class is built by the class
132
+ registered under its tile's class, so a designer sets "Chest" once on the
133
+ chest tile and every chest dropped in the map is a `Chest`. The object's
134
+ own class or registered name still comes first, and a tile classed like a
135
+ built-in (`Sprite`, `Trigger`, `shape`...) stays a plain tile.
136
+ - **The tile's properties.** Read them with `settings.resolvedProperty(name)`
137
+ or `settings.resolvedProperties()`, which merge the tile's properties under
138
+ the object's own, as Tiled's scripting API of the same names does. They are
139
+ **not** set on `settings` by name: only the object's own properties are,
140
+ as before, so a tile property named like a sprite setting never reaches a
141
+ plain tile sprite.
142
+
143
+ ```ts
144
+ import { registerTiledObjectClass, Sprite, type TMXObject } from "melonjs";
145
+
146
+ // the custom properties set on the object itself, by name
147
+ interface DoorSettings extends TMXObject {
148
+ locked?: boolean;
149
+ }
150
+
151
+ class Door extends Sprite {
152
+ locked: boolean;
153
+ facing: string;
154
+ constructor(x: number, y: number, settings: DoorSettings) {
155
+ super(x, y, { image: "door" });
156
+ this.locked = settings.locked ?? false;
157
+ // on the object, or else on the door tile in the tileset
158
+ this.facing = settings.resolvedProperty("facing") ?? "N";
159
+ }
160
+ }
161
+ registerTiledObjectClass("Door", Door); // and give the door tile the class "Door"
162
+ ```
163
+
164
+ `TMXObject` is the type of the `settings` a registered class (or factory)
165
+ receives: the object as read from the map, with `tile` (a `Tile`) on a tile
166
+ object. Extend it with the properties your class reads.
167
+
168
+ For a class that is not a `Sprite` itself (a `Container` holding the tile and
169
+ something else, say), `settings.tile.getRenderable()` returns the tile's sprite
170
+ as a plain tile object would get it: from a tileset image, an image collection
171
+ or an animated tile alike, with no region names to build by hand.
172
+
125
173
  melonJS pre-registers `Renderable`, `Sprite`, `NineSliceSprite`, `Text`,
126
174
  `BitmapText`, `ImageLayer`, `ColorLayer`, `Light2d`, `Collectable`, `Trigger`
127
175
  and `Entity` as Tiled classes, so `Collectable` and `Trigger` work out of the
@@ -157,7 +205,9 @@ opposite of `level.load`'s.
157
205
 
158
206
  Draw collision geometry in Tiled on an object layer and melonJS turns it into
159
207
  world shapes automatically — rectangles, polygons, polylines, ellipses and
160
- points all work.
208
+ points all work. On an isometric map they are projected with the map's tile
209
+ ratio; a circle stays an `Ellipse`, but any other ellipse comes out tilted and
210
+ becomes a `Polygon`, so code that checks a shape's type should expect either.
161
211
 
162
212
  The contract is the **layer name**: melonJS lowercases it and checks whether it
163
213
  *contains* `"collision"` (so `collision`, `Collision`, `world collision` all
@@ -171,7 +221,10 @@ An object that matches no factory and carries no text or tile data falls to the
171
221
  geometry, which the world auto-registers with the active adapter on `addChild`.
172
222
 
173
223
  For per-object physics, set the object's custom properties in Tiled; they arrive
174
- on the settings object passed to your entity's constructor.
224
+ on the settings object passed to your entity's constructor. Properties set on
225
+ the object's tile are read with `settings.resolvedProperty(name)`. One is also
226
+ applied to the object the map creates: an `int` property named
227
+ `visibilityLayer` sets which cameras draw it (see `melonjs-camera-and-drawing`).
175
228
 
176
229
  ## Map orientations
177
230
 
@@ -183,10 +236,69 @@ Isometric maps need y-sorting so objects overlap correctly:
183
236
  app.world.sortOn = "y"; // after level.load
184
237
  ```
185
238
 
239
+ The world then keeps its objects in order as they move (`autoSort`, on by
240
+ default): a character walking around passes in front of and behind the scenery
241
+ with no `sort()` call.
242
+
186
243
  `sortOn` only accepts `"x"`, `"y"`, `"z"` (the default) or `"depth"` and throws
187
244
  on anything else. `Vector2d`, `Vector3d`, their observable variants and `Polygon`
188
245
  all carry `.toIso()` / `.to2d()` for converting between screen and map space.
189
246
 
247
+ ### What the y-sort can and cannot sort
248
+
249
+ `sortOn = "y"` sorts **objects**, never tiles. A tile layer is a single
250
+ renderable drawn in one piece, so a character ends up in front of all of it or
251
+ behind all of it. Anything a character walks both in front of and behind
252
+ (walls, trees, furniture) has to be on an **object layer, as tile objects**,
253
+ and in the **same** object layer as the characters: each Tiled layer gets its
254
+ own `z`, and the y-sort compares `z` before `y`. Keep the floor on a tile layer
255
+ below them. This holds for any y-sorted map, isometric or a top-down
256
+ orthogonal one.
257
+
258
+ ```
259
+ floor tile layer the ground, drawn first
260
+ dungeon object layer walls, props, chests, doors, the hero
261
+ collision object layer the shapes (not drawn)
262
+ ```
263
+
264
+ Tile objects with no class are built for you: each one is a `Sprite` with its
265
+ default body, static, over its whole image box and typed `ENEMY_OBJECT`. A
266
+ character keeping the default `collisionMask` (every type) collides with all of
267
+ them, so when the scenery's real collision is drawn in the collision layer,
268
+ mask the character to it:
269
+
270
+ ```js
271
+ this.body.setCollisionMask(collision.types.WORLD_SHAPE);
272
+ ```
273
+
274
+ Give the objects with behaviour a Tiled class and register it, as above.
275
+
276
+ The `y` it sorts on is `pos.y`, and Tiled objects default to a `(0, 0)` anchor,
277
+ so that is the **top** of each image. Sorting by the top only matches sorting by
278
+ the feet when every image is the same height and stands on the bottom of its
279
+ box, the usual layout of an isometric pack. A shorter image sorts in front of
280
+ things it stands behind. Either pad the art to one height, or line every object
281
+ up by the bottom of its image with `sortOffset`, which changes the order and
282
+ never the position:
283
+
284
+ ```js
285
+ level.load("map1");
286
+ app.world.sortOn = "y";
287
+ for (const child of app.world.getChildren()) {
288
+ child.sortOffset = child.height; // sort by the bottom of each image
289
+ }
290
+ ```
291
+
292
+ A character you create in code follows the same convention as the scenery: by
293
+ the top of a frame as tall as the scenery's (`anchorPoint` `(0, 0)`), or by its
294
+ feet when everything sorts by the bottom.
295
+
296
+ Two equal positions keep insertion order, and the one added **last** is drawn
297
+ **behind**: a decoration placed at its wall's exact position disappears. Give
298
+ it `sortOffset = 1`. A `Container` or a particle emitter is sorted by its top
299
+ left corner (an emitter's by the top of its spawn area); give it the offset to
300
+ the point it belongs with, such as `door.pos.y - dust.pos.y`.
301
+
190
302
  ## Image layers
191
303
 
192
304
  `ImageLayer` gives parallax backgrounds with a ratio per axis, set in Tiled or in
@@ -241,7 +353,17 @@ unanimated layer into the offscreen-bake path instead.
241
353
  | `No inflate function set` at parse time | compressed layers without the tiled-inflate plugin |
242
354
  | collision shapes are not solid | the object layer's name does not contain `"collision"`, or the objects are named |
243
355
  | isometric objects overlap wrongly | `world.sortOn` not set to `"y"` |
356
+ | a character is always in front of (or behind) every wall | the walls are on a tile layer, or on another object layer than the character: each layer has its own `z`, compared before `y` |
357
+ | a small prop draws over a character standing in front of it | images of different heights: the y-sort uses `pos.y`, the top of a Tiled object's image. Pad the art, or set `sortOffset = height` on every object to sort by the bottom |
358
+ | a decoration placed at the same position as a wall disappears behind it | a tie keeps insertion order and draws the later one behind: `sortOffset = 1` |
359
+ | particles (or a container) at the foot of something draw over a character standing in front of it | they sort by the top of their spawn area (or the container's top left): set `sortOffset` to line them up with what they belong to |
360
+ | a character is stopped short of walls and props placed as tile objects | it collides with their default bodies (static, `ENEMY_OBJECT`, the whole image box); mask it to `collision.types.WORLD_SHAPE` when the collision layer holds the real shapes |
361
+ | a property set on a tile is undefined on the object's `settings` | tile properties are not copied onto `settings`: read them with `settings.resolvedProperty(name)` |
362
+ | objects placed from a classed tile come out as plain sprites | that class is not registered, it is a built-in name, or the object has a class or a registered name of its own, which come first |
244
363
  | missing tiles or a blank map | the `.tsx` or tileset image was not preloaded |
364
+ | a tileset's transparent color (`trans`) still shows (the console says it could not be applied) | the image cannot be read back: one from another origin needs CORS headers on the server and `loader.setOptions({ crossOrigin: "anonymous" })` (without them WebGL and WebGPU cannot draw it at all), and a compressed texture cannot be changed: export it with an alpha channel instead |
365
+ | changing tiles at runtime is slow on a pre-rendered layer | outside an orthogonal map whose tiles fit their cells, a changed tile re-bakes the whole layer before it next draws: keep layers you edit often off `preRender` |
366
+ | thin lines between tiles on the Canvas renderer, with smoothing on | filtering blends in the next tile of the tileset or its spacing, which a canvas cannot prevent: set `antiAlias: false`, or `preRender` the layer. WebGL and WebGPU keep each tile to itself |
245
367
  | tilemap slow on some machines | layer fell back off the shader path — check the console warning for the reason |
246
368
 
247
369
  ## Related skills