Releases: melonjs/melonJS
Releases · melonjs/melonJS
v19.3.0
What's New in melonJS 19.3.0
New Features
- Normal-map sprite lighting (closes #1416) —
Sprite.normalMapaccepts a paired normal-map image (or auto-detected fromTextureAtlas({ normalMap })). Sprites with a normal map render through a dedicatedLitQuadBatcherwhose fragment shader runs a Lambertian light loop over the activeLight2dinstances — up to 8 concurrent lights, configurableStage.ambientLightingColor, quadratic attenuation. The lit batcher only kicks in when bothnormalMapand active lights are present, so unlit scenes pay zero overhead. Light2dis now a first-class worldRenderable— add viaapp.world.addChild(light)(or any container, so the light follows parent transforms). Auto-registers with the active stage's lighting set viaonActivateEvent/onDeactivateEvent. The legacyStage.lights.set()API still works (entries are auto-adopted into the world tree on stage reset).- Lights now render inside the camera's post-effect FBO bracket (closes #1398) — vignette, scanlines, ColorMatrix, and any other camera shader effect now wrap the lighting output. The
Stage.draw()lighting block has been removed; rendering happens via the world tree walk and a publicStage.drawLighting(renderer, camera)pass invoked by each camera (subclassable for custom lighting). - Procedural Light2d (closes #1430) — new
Renderer.drawLight(light)API replaces the per-light offscreen-canvas pipeline. WebGL renders lights as quads through a sharedRadialGradientEffectshader; per-light color and intensity flow through the vertextintattribute, so N lights = 1 program switch + 1 flush. Canvas caches a smallGradientconfig per light (rebuilt only on radii / color / intensity change) and shares oneCanvasRenderTargetacross every gradient.Light2dis now pure data — no canvas, no shader knowledge. Light2d.illuminationOnly(defaultfalse) — whentrue, the light's own gradient isn't drawn but it still feeds the cutout pass and the lit-sprite shader. Useful for SpriteIlluminator-style demos where the light is a logical source, not a visible glow.Light2d.lightHeight(defaultmax(radiusX, radiusY) * 0.075) — Z component of the light direction in the lit shader'sdot(normal, lightDir). Low values graze across the surface (dramatic detail); high values produce more uniform brightness.Light2d.setRadii(rx, ry)— updates both radii and the underlying bbox sogetBounds()andgetVisibleArea()track the new size. Fixes a latent bug where mutatingradiusX/Yafter construction left the rendered light stale while the cutout pass moved.RadialGradientEffect— generic procedural radial gradient shader (video/webgl/effects/radialGradient.js). Solid color at center fading linearly to transparent at the host quad's edge. Accepts{ color, intensity }plussetColor/setIntensitysetters.RenderState.peekScissor()— inspect the scissor box that the nextrestore()would install, without mutating state. Returns a live reference into the internal stack (read-only). Used byWebGLRenderer.restore()to flush only when the scissor actually changes.- Three new examples —
Normal Map(three procedurally-generated 3D orbs reacting to a moving cursor light),SpriteIlluminator(port of CodeAndWeb's cocos2d-x dynamic-lighting demo), andClipping(nested + animatedContainer.clipping).
Changed
- Breaking:
Light2dis now centered on itspos(anchorPoint = (0.5, 0.5)), matchingSpriteandEllipse(x, y, w, h)conventions. Constructorx/yandlight.pos.x/ydenote the light's center, not the bounding-box top-left. Transforms applied vialight.scale(...)orlight.rotate(...)now pivot around the visual center. Existingnew Light2d(x, y, r)callers passing top-left coords need to add radius:new Light2d(x + r, y + r, r). Code usinglight.centerOn(x, y)is unaffected. Bounds.addFramenow short-circuits the 4-corner walk when the matrix is identity (or omitted) — beneficial forWebGLRenderer.clipRect/enableScissorand any other call site that doesn't pre-filter.
Bug Fixes
- Multi-light support — lifted the historical "Canvas mode only supports one light per stage" limitation. Multiple
Light2dinstances now render correctly under both Canvas and WebGL. Root cause was in the underlyingsetMask(shape, true)implementation on both renderers: chained calls did not accumulate cutouts. Canvas now adds the outer rect once per mask sequence (made tractable by the evenodd groundwork from #1369); WebGL switched to anINCR-based stencil protocol so each shape adds independently. Containerclipping under nested transforms (closes #1349) — a clipping container nested inside a translated, scaled, or rotated parent was mis-positioned.Container.drawnow applies its own translate before callingclipRectand passes container-local(0, 0, width, height); WebGLclipRecttransforms the four input corners throughcurrentTransformand uses the AABB as the screen-space scissor box (so scale and rotation are honored). Canvas'scontext.rectwas already matrix-aware.- WebGL flush ordering on scissor change — pending
PrimitiveBatchervertices now drain when asave()/restore()pair changes the scissor box. PreviouslyWebGLRenderer.restore()reverted the GL scissor without flushing, so vertices queued inside a deeper clip could survive pastrestore()and flush later under a more permissive scissor. CanvasRenderer.setMask(shape)X/Y swap — with aRect,Bounds, orRoundRectmask, args were being passed in the wrong order tocontext.rect/context.roundRect. Masks at off-diagonal positions clipped at the wrong location. Latent because nothing in core or examples used those shape types as masks.Stage.drawLightingcutout alignment — ambient-overlay cutouts now align with each light's rendered gradient when the camera is scrolled or the light is parented to a translated container.getVisibleArea()returns world-space coords, butdrawLightingruns after the world container'stranslate(-cameraPos)has been popped — so cutouts were landing at world coords inside a camera-local FBO. Fix re-applies the camera's world-to-screen translate insidedrawLighting.- WebGL vertex attribute leak between batchers — each batcher owns its own attribute layout (e.g.
LitQuadBatcher5 attrs at stride 28 vsPrimitiveBatcher3 at stride 20). On batcher switch the previous batcher's enabled attribute locations stayed live with their old stride/offset and could throwINVALID_OPERATIONon the next draw.Batcher.unbind()now disables them on every switch. - WebGL
gl.useProgramleak aftersetLightUniforms—Camera2d.draw()calledsetLightUniforms(...)every frame even when the scene had zero lights, leaving the GL program pointed at the lit shader. The next sprite draw (4-attribute vertex data) was being fed to the lit shader (5 attributes), rendering as garbage. Fixed by restoring the active batcher's program after the upload. - WebGL stale custom shader past
setBatcher— the previous fast path returned early when the active batcher matched and no shader was provided, so a custom shader bound by a prior call could keep rendering subsequent batches through the wrong program.setBatchernow always reconciles the active shader. QuadBatcher.blitTexturetexture-unit cache desync —blitTexturedid not synccurrentTextureUnit/boundTextures[0]with the GL state it mutated. After a blit ran with a non-zero unit, subsequentbindTexture2Dcalls could short-circuit on the stale cached unit and bind the new texture on the wrong unit, corrupting the next sprite batch.- Stale Light2d gradient on radius / color / intensity change — pre-#1430 the gradient was baked once at construction. The new
drawLightpath auto-invalidates: the Canvas cache rebuilds when any ofradiusX/radiusY/color/intensitydiffer; WebGL readslight.color/light.intensitylive each call.
Install
npm install melonjs@19.3.0
v19.2.0
What's New in melonJS 19.2.0
New Features
state.freeze(duration, music?)+Application.pause/resume/freeze— hit-stop / hit-pause primitive that pauses the stage for a fixed duration then auto-resumes. Returns aPromise<void>that resolves on unfreeze. Reentrant calls extend (don't stack); window blur cancels the freeze. Convenience proxies onApplicationfor the same.- Multi-pass post-effect chaining —
Renderable.postEffectsarray withaddPostEffect()/getPostEffect()/removePostEffect()/clearPostEffects(). Effects run in sequence via FBO ping-pong; single-effect renderables use a zero-overhead fast path. - FBO-based camera post-processing pipeline — assign a
ShaderEffectto any camera'sshaderproperty for full-screen post-effects. Multi-camera independent (e.g. main + minimap with different effects). - Camera effects system — extensible
CameraEffectbase class with lifecycle. ExtractedShakeEffect, unifiedFadeEffect(in/out direction), and newMaskEffectfor shape-based level transitions (Ellipse / Polygon shrink/reveal). Camera2d.colorMatrix— built-inColorMatrixfor color grading (brightness / contrast / saturate / hueRotate / sepia / invertColors). Always applied as the final post-pass; zero overhead when identity.ColorMatrixclass +ColorMatrixEffect— chainable color adjustments.SepiaEffect,InvertEffect,DesaturateEffectnow share a single GLSL shader via the matrix.VignetteEffect— built-in shader effect to darken screen edges with configurable strength and size.RenderTargetabstract base (designed for future WebGPU support) with concreteWebGLRenderTarget(FBO) andCanvasRenderTarget(canvas) implementations. NewRenderTargetPoolreplaces the WebGL-specific FBO pool.ParticleEmitter.autoDestroyOnComplete(defaultfalse) — emitter removes itself from its parent once all particles have died. Solves the leak in fire-and-forgetburstParticles()use cases. CompaniononCompletecallback fires on completion.ParticleEmitter.accurateBounds(defaultfalse) — opt-in per-frame bounds refresh for debug visualization or collision. Default off saves significant matrix work at high particle counts.ParticleEmitterSettingsis now an exported TypeScript interface — constructor andreset()acceptPartial<ParticleEmitterSettings>for compile-time validation.Text.visibleCharacters/visibleRatio— progressive text reveal / typewriter effects onTextandBitmapText. AnimatevisibleRatiowith a Tween for character-by-character display.Tween.repeatDelay(ms)— adds a delay before each repeat cycle.- Renderer-agnostic state methods —
setViewport(),clearRenderTarget(),enableScissor(),disableScissor(),setBlendEnabled()(no-ops on Canvas, real on WebGL). Eliminates direct GL calls from the post-effect pipeline. Trigger.transition— accepts"fade"(default) or"mask"for shape-based level transitions; newcolorsetting replaces legacyfadeproperty (backward compatible).Matrix3d.transform()— accepts either 16 values (full 4x4) or 6 values (2D affine, promoted to 4x4). Mirrors theMatrix2d.transform()API.
Changed
Renderable.shaderis now a backward-compatible getter/setter forpostEffects[0](deprecated in favour ofaddPostEffect()/clearPostEffects()).Camera.shake() / fadeIn() / fadeOut()are now convenience wrappers that createShakeEffect/FadeEffectinstances — same signatures, fully backward compatible. Multiple shakes can coexist.Triggerinternally usesFadeEffect/MaskEffectinstead ofviewport.fadeIn()/viewport.fadeOut().ParticleEmitter.reset()now clamps reversed range pairs (minLife > maxLife,min/maxStartScale,min/maxEndScale,min/maxRotation) by loweringmintomax. Catches the common footgun of overriding only one half of a range.Particlehot-path performance — closed-form transform construction folded into a singlesetTransform()call,_halfW/_halfHcached on reset,_deltaInvcached on the emitter, frame-skip bookkeeping gated behindframesToSkip > 0. ~240k matrix ops/sec saved at 1000 particles, 60fps.
Bug Fixes
- WebGL1 stencil masking (
setMask/MaskEffect) now works correctly inpreferWebGL1: truemode.WebGLRenderTargetwas relying ongl.DEPTH_STENCIL/gl.DEPTH_STENCIL_ATTACHMENTbeing exposed on the WebGL1 context, which some browser/driver combinations leaveundefined. Now uses spec-defined numeric fallbacks (0x84F9 / 0x821A) and validates completeness viagl.checkFramebufferStatus()with a depth-only fallback path. ImageLayer.mask,shader/postEffects,flipX()/flipY()now apply correctly.ImageLayer.preDraw()was a stripped-down copy ofRenderable.preDraw()that handled only alpha / tint / blend mode. Coordinate-sensitive setup (flip, stencil mask) is now applied indraw()after the per-camera zoom transforms, so it stays correctly aligned at anyviewport.zoomand across multi-camera setups.state.freeze()no longer leaves the game in inconsistent states when interacting with manual pause/resume or window blur:- The freeze timer's auto-resume now respects whether the game was already paused when freeze started — won't unpause a manually-paused game on expiry
- Calling
state.resume()orstate.stop()mid-freeze cancels the timer and resolves the freeze promise immediately - Window
BLURcancels the freeze (the visual "moment" is over by the time the user returns; regularpauseOnBlurstill keeps the game paused while away)
ParticleEmitterconstructor was using bitwise|instead of logical||for thewidth/heightfallback, silently rounding any provided value to the next odd number (e.g.width: 16 → 17,width: 32 → 33).Particlehitbox now tracks the visual — anchor + transform + bounds are kept consistent (rotation pivots on the visual center, bounds match the visual extent). Previously the hitbox was offset by(w/2, h/2)and lagged one frame behind the visual.- Canvas
setMask(shape, true)now usesevenoddclipping for proper inverted mask support (was usingdestination-atopcomposite which didn't clip subsequent draws). - Ellipse
clone()now uses the ellipse pool — consistent withPolygon.clone(). - WebGL
WebGLRenderTargetconstructor andresize()now explicitly useTEXTURE0to avoid corrupting the multi-texture batcher's texture unit bindings. - WebGL post-effect pipeline now explicitly sets viewport on every FBO bind and saves/restores the projection matrix, fixing rendering issues after canvas resize.
Install
npm install melonjs@19.2.0
v19.1.0
What's New in melonJS 19.1.0
New Features
- Multi-texture batching — up to 16 textures drawn in a single batch/draw call, eliminating GPU flushes on texture changes. Automatically falls back to single-texture mode when a custom
ShaderEffectis active. ~80% fewer draw calls on the platformer example (14 vs ~70 flushes/frame), with an estimated 30-50% FPS improvement on low-end mobile devices. highPrecisionShaderapplication setting — whenfalse, caps shader precision atmediumpfor better performance on mobile GPUs that supporthighpbut run faster atmediump. Defaulttrue(auto-detect highest precision).
Bug Fixes
getSupportedCompressedTextureFormats()no longer crashes when the GL context is unavailable- Examples updated for 19.0 API changes (Text standalone draw removal, Application pattern)
Install
npm install melonjs@19.1.0
v19.0.0
What's New in melonJS 19.0.0
New Features
- 3D mesh rendering —
Meshclass for textured 3D triangle meshes with OBJ/MTL model loading,drawMesh()on both WebGL and Canvas renderers,Matrix3d.perspective()for perspective projection, mesh-to-canvas/ImageBitmap export and convex hull collision shapes - 15 built-in ShaderEffect presets —
FlashEffect,OutlineEffect,GlowEffect,DesaturateEffect,PixelateEffect,BlurEffect,ChromaticAberrationEffect,DissolveEffect,DropShadowEffect,ScanlineEffect(with CRT curvature/vignette),TintPulseEffect,WaveEffect,InvertEffect,SepiaEffect,HologramEffect. All extendShaderEffectwith configurable uniforms. - Trail renderable — fading, tapering ribbons behind moving objects with auto-follow or manual point mode, color gradient, width curve, opacity, and blend mode support. Works on both WebGL and Canvas.
- Gradient color sampling —
Gradient.getColorAt(position, out)interpolates colors at any position along a gradient with float-space interpolation and lazy-parsed Color cache - Math utilities —
lerpArray(values, position)for interpolating across evenly-spaced value arrays;computeVertexNormal(points, index, out)for perpendicular normals at polyline vertices - Vertex utilities —
normalizeVertices(),projectVertices(),convexHull()for 3D vertex operations
Changed
- BREAKING:
Renderable.currentTransformis now aMatrix3d(wasMatrix2d) — code accessingcurrentTransform.valindices must update: translation at[12],[13](was[6],[7]) - BREAKING:
Matrix3d.scale(x, y, z)defaultzchanged from0to1— prevents accidental Z-axis flattening - BREAKING:
Text.draw()andBitmapText.draw()no longer accepttext,x,yparameters — standalone draw removed (deprecated since 10.6.0) - BREAKING:
Tweenuses event-based lifecycle instead of adding togame.world. Public API unchanged. - BREAKING:
depthTestapplication setting removed — GPU depth sorting is incompatible with 2D alpha blending. Depth testing remains available for 3D mesh rendering only. - BREAKING:
UITextButtonsettingsbackgroundColor/hoverColorremoved — usehoverOffColor/hoverOnColor - Container
sortOngetter/setter with cached comparator function customShaderproperty moved to baseRendererclassexactOptionalPropertyTypesre-enabled for stricter TypeScript checking
Performance
- Color hex conversion — pre-computed 256-entry lookup table replaces per-call nibble extraction + string concat
- Color.toHex/toHex8 — read glArray directly, bypassing getter overhead
- Gradient.getColorAt — float-space interpolation via
toArray()/setFloat(), avoids int↔float round trips - Trail rendering — zero-allocation draw loop with pre-allocated normals, hoisted divisions, single-splice point expiry
Bug Fixes
Rect.setSize()now callsupdateBounds()— fixes pointer event regression from July 2024 TS conversion- WebGL depth buffer correctly used for 3D mesh rendering
- Canvas backface culling corrected for Y-flipped screen space
- Canvas triangle seam expansion (0.5px) for anti-aliasing gaps
Dependencies
- vite 8.0.3 → 8.0.8
- esbuild 0.27.4 → 0.28.0
- typescript-eslint 8.58.1 → 8.58.2
- react 19.2.4 → 19.2.5, react-dom 19.2.4 → 19.2.5
- typedoc 0.28.18 → 0.28.19
- vite-plugin-glsl 1.5.6 → 1.6.0
v18.3.0
What's New in melonJS 18.3.0
New Features
- Bezier curve drawing —
bezierCurveTo(),quadraticCurveTo(), andarcTo()path methods, matching the Canvas 2D API. WebGL renderer tessellates via Path2D. - Gradient fills —
createLinearGradient()andcreateRadialGradient()methods for both Canvas and WebGL renderers, usable with all fill methods - Dashed lines —
setLineDash()andgetLineDash()for stroke operations on both renderers - Tiled object factory registry — extensible
registerTiledObjectFactory()andregisterTiledObjectClass()APIs for plugins to register custom Tiled object handlers without modifying engine code
Changed
- Application as entry point —
new Application(width, height, options)auto-callsboot(), making it a standalone entry point.video.init()is deprecated. - Game singleton decoupled — internal modules no longer import from the barrel
index.js;gamesingleton usessetDefaultGamepattern - Stage lifecycle —
onResetEvent(app, ...args)andonDestroyEvent(app)now receive the Application instance as first parameter - Container defaults — dimensions default to
Infinity(no intrinsic size, no clipping), removing dependency ongame.viewport - EventEmitter — native context parameter support on
on()/once(), eliminating.bind()closure overhead
Bug Fixes
- BitmapText bounding box — width uses last glyph visual extent; height uses actual glyph extents instead of
capHeight; baseline shifts use real glyph metrics for all baselines; y offset starts at first visible pixel - BitmapText multiline baseline — shift applied once for entire text block instead of per-line (which caused accumulating offsets)
- Camera2d — floating containers with
Infinitybounds (e.g., HUD) are now always visible, fixing a regression where HUD elements stopped rendering - Sprite flicker — time-based flickering (~15 flashes/sec) replaces per-draw-call toggle that broke with multi-camera setups
- Path2D — fix
quadraticCurveTo/bezierCurveTostartPoint reference bug and adaptive segment count - Application — fix settings mutation, white flash on load, pool cleanup errors
- WebGLRenderer — fix
setBlendModepremultipliedAlpha tracking - Text — fix multiline textBaseline y offset, power-of-two texture sizes
Performance
- BitmapText — precompute
glyphMinTop/glyphMaxBottomonce in font parsing; cachemeasureTextresults insetText/resize
v18.2.2
What's Changed
melonJS Team
- Chore: fix missing README on the npm release (58a534d)
- Copy root README into melonjs package during dist (6ef58cd)
- Bump spine-plugin to 2.0.1 (501de1f)
Full Changelog: 18.2.1...18.2.2
v18.2.1
What's Changed
melonJS Team
- Fix loading screen logo persisting after preload completes (3f0be6f)
Full Changelog: 18.2.0...18.2.1
v18.2.0
What's New in melonJS 18.2.0
New Features
- Multi-camera support — stages can now have multiple cameras for split-screen, minimaps, and multi-viewport layouts
- Extensible batcher system — custom
Batchersubclasses with configurablemaxVertices, indexed drawing (settings.indexed), and custom projection uniform names (settings.projectionUniform) - Tiled 1.8–1.12 full support — oblique maps, capsule shapes, list properties, embedded base64 images, tile sub-rectangles,
tilerendersize/fillmode, layer blend modes, per-object opacity/visibility,repeatx/repeaty,parallaxoriginx/parallaxoriginy, class-type properties,isCollectionflag - RoundRect as collision shape — can now be used for SAT collision via polygon-approximated rounded corners
- Expanded blend modes — Canvas: overlay, darken, lighten, color-dodge, color-burn, hard-light, soft-light, difference, exclusion; WebGL2: darken, lighten via
gl.MIN/gl.MAX
Changed
- TypeScript — converted plugin, camera, particles emitter, state, audio, application, input, UI, and pointer modules to TypeScript
- CDN URLs — README now uses
cdn.jsdelivr.netinstead ofesm.run(which is still in beta)
Bug Fixes
- WebGLRenderer —
setBatcher()now rebinds the shared vertex buffer when switching batchers, allowing custom batchers with their own GL buffers - WebGLRenderer —
setBlendMode()now accepts apremultipliedAlphaparameter for correct blending with non-premultiplied textures - Renderer — add base
setBlendMode()andGPURendererproperty to fix TypeScript casts - Plugin —
plugin.register()now usespluginClass.namefor reliable name derivation - TMXTileset — fix animation key using first frame tile ID instead of the tile's own ID
- CanvasRenderer — replace bezier ellipse approximation with native
context.ellipse()(with polyfill) - Plugin — fix
plugin.get()throwingTypeErrorwhen searching by name with no match - Events — fix duplicate
BLURentry (was missingFOCUS) - UIBaseElement — fix
isDraggableJSDoc andreleaseddefault - Application — fix constructor
optionsnot being optional, fixgetUriFragment()unsafe cast - CanvasRenderer —
setProjection()now properly applies the projection matrix as a canvas 2D transform
Spine Plugin
@melonjs/spine-pluginmigrated into the monorepo — customSpineBatcherwith two-color tinting, indexed drawing, expanded example with 17 official Spine characters
v18.1.0
What's New in melonJS 18.1.0
New Features
ShaderEffectclass — simplified custom shader API that only requires a fragmentapply(color, uv)function. Vertex shader, uniforms, and texture sampling boilerplate are handled automatically. Silently disabled in Canvas mode.create-melonjsCLI — scaffold a new game project in seconds withnpm create melonjs my-game- Inline source code viewer — examples now have a "Show Code" button to view syntax-highlighted source alongside the running game
- API docs landing page — new home page with quick start, feature overview, and common tasks
- API docs categories — sidebar organized into 14 categories (Rendering, Physics, Input, etc.)
Changed
- Physics — collision response is now mass-proportional; overlap and velocity correction are split based on relative mass
- Entity — deprecated in favor of Sprite/Renderable + Body (#1008)
- Loader — modernized with Promise-based asset loading for improved parallel performance;
onload/onProgress/onErrordeprecated in favor of events - TMX — refactored TMXUtils into reusable
decode.tsandxml.tsmodules - Compositor → Batcher —
Compositor,QuadCompositor,PrimitiveCompositorrenamed toBatcher,QuadBatcher,PrimitiveBatcher(old names still work with deprecation warnings)
Bug Fixes
- Texture cache overflow — flush and rebatch when GPU texture units are exhausted instead of throwing (#1280)
setAntiAlias— now controls GL texture filtering (GL_NEARESTvsGL_LINEAR) on all bound textures (#1279)createPatternleak — clean up previous GPU texture when repeat mode changes (#1278)- Custom shader support — properly flush and restore default shader per draw call, fix
setUniformusing wrong GL program, reset sampler uniform on shader switch - TMX — fix hexagonal
pixelToTileCoordsmutation, canvas memory leak, collision shape dimensions, XML parsing crash, GC pressure from vector allocations - Sprite — fix body-renderable misalignment with trimmed atlas frames, visual vibration on flip, jumping on rotated frames (#1201, #1214)
- Path2D — fix SVG arc parsing and ellipse rotation (#1198)
- WebGLRenderer — fix polygon corruption from vertex mutation, scissor restore,
drawVerticesvertex count, resizesetAntiAliascorruption - Z-ordering — fix reset during collision response
Performance
- TMX loading — ~20-40% faster via tileset caching, pre-allocated decode buffers, and fast path for base64 data
- WebGL rendering —
fillRect,fillEllipse,fillArc,fillRoundRect,fillPolygonnow generate geometry directly, bypassing path2D and earcut - WebGL batching — quad rendering uses
gl.drawElementswith index buffer (33% less vertex data), redundant sampler calls eliminated, zero-allocation save/restore stacks - Collision — index-based pool access instead of array push/pop in SAT detection
- Container — O(n) accumulator pattern in
getChildByProp/getChildByTypeinstead of O(n²)
Developer Experience
- 74 JSDoc typo and grammar fixes across 32 files
- Coin glow shader example in the platformer demo
- Updated typescript-boilerplate and plugin-template for melonJS 18
- Archived es6-boilerplate with redirect notice
Full Changelog: 18.0.0...18.1.0
v18.0.0
What's New in melonJS 18.0.0
New Features
- Color constructor — now also accepts another Color object as parameter
- Renderer — new
backgroundColorproperty for clearing background between frames - Pool system — new type-safe
createPool()API with improved performance;destroyrenamed torelease
Changed
- Build system — replaced rollup with esbuild (@hornta)
- Documentation — replaced webdoc with typedoc (@hornta)
- Test framework — replaced mocha and puppeteer with vitest in browser mode (@hornta)
- TypeScript — extensive conversion across the codebase: color, math, geometry, platform, DOM, keyboard, timer, application settings, pool, and more (@hornta)
- Monorepo — migrated to pnpm workspaces with turbo (@hornta)
- Renderable —
anchorPointnow uses the lighterObservablePointclass instead ofObservableVector2d - Math — namespace
Mathis now deprecated and renamed tomathfor consistency - Deprecated API removal — all classes and methods deprecated since version 15 and lower have been removed (see Upgrade Guide)
Bug Fixes
- Body — fix
setCollisionType()not accepting numeric values; fixsetVertices()fallback creating Point instead of Polygon - Camera — fix
moveTo()upper bound clamping; fixfocusOn()double-counting position - Container — fix
addChildAt()rejecting valid index; fixgetNextChild()returning wrong child; fixremoveChildNow()crash when not attached to root - Physics — fix collision response velocity projection; fix shapes tunneling through polyline junctions; fix persistence for child bodies during reset (@Vareniel); fix
step()crash with undefined ancestor - Renderable — fix Light2D color blending in Canvas mode (@Vareniel)
- CanvasRenderTarget — fix arguments passed to
convertToBlob()(@hornta) - TypeScript — fix missing
OffscreenCanvastype for TextureAtlas constructor - Video — fix implicit global reference to HTMLVideoElement
- Docs — fix
floatingdefault shown for UI elements (@SergioChan)
Performance
- Collision — pre-built SAT function dispatch lookup table; reduced hot path overhead
- Container — cache camera references outside per-child update loop
- Physics — reduced iteration overhead in
world.step() - QuadTree — reduced array allocations in
retrieve()andinsert() - Observable vectors — rewritten for better performance
- Color — faster
clone()method - Pool — optimized implementation
New Contributors
- @SergioChan made their first contribution
Full Changelog: 17.4.0...18.0.0