Download Latest Version v20.4.0 source code.zip (43.8 MB)
Email in envelope

Get an email when there's a new version of melonJS

Home / 20.1.0
Name Modified Size InfoDownloads / Week
Parent folder
README.md 2026-08-23 3.6 kB
v20.1.0 source code.tar.gz 2026-08-23 42.6 MB
v20.1.0 source code.zip 2026-08-23 43.5 MB
Totals: 3 Items   86.1 MB 0

What's New

Collision events, per shape. A body built from several shapes could only ever report one contact: onCollision and the onCollision* lifecycle surface the single pair chosen for physical resolution, so a character's footprint contact masked a simultaneous hurtbox contact. The new onShapeCollisionStart / onShapeCollisionActive / onShapeCollisionEnd report every overlapping shape pair, without changing which one resolves.

:::js
onShapeCollisionStart(contact, other) {
    // shapeA / indexShapeA are always YOUR shape
    if (contact.indexShapeA === HURTBOX && contact.isTrigger) {
        this.takeHit(other, contact.normal);
    }
}

Each contact carries both shapes, both indices into body.shapes, the trigger status and the SAT data, receiver-symmetric so shapeA is always your own. Supported on all three physics backends: the builtin detector enumerates shape pairs directly, while @melonjs/planck-adapter and @melonjs/matter-adapter dispatch natively, since Box2D reports one contact per fixture pair and matter one per part, and each maps a melonJS shape onto a single collider.

Purely additive. Physical resolution picks the same pair with the same solid-over-trigger preference from 20.0, every existing handler keeps its signature, and on the builtin detector the enumeration is opt-in: declare none of these handlers and the narrowphase does exactly the work it did before.

Requested by a downstream maintainer building on the per-shape collision filtering from 20.0.

New Features

  • onShapeCollisionStart / onShapeCollisionActive / onShapeCollisionEnd (#1596) on every physics backend, reporting each overlapping shape pair with both shapes, both indices, trigger status and contact geometry
  • ShapeCollisionContact is exported, so TypeScript users can type a handler parameter directly

Bug Fixes

  • The collision lifecycle only ever fired for one pair in the entire world. createGUID() returned the literal string "-1" on every call, so every renderable added to a container shared one GUID. Collision pair identity is built from GUIDs, so with two pairs colliding anywhere at once the second was treated as already-seen and its onCollisionStart / onCollisionActive / onCollisionEnd never fired. onCollision was unaffected, which is how it went unnoticed
  • @melonjs/matter-adapter: a body with more than one shape received no collision events at all. matter reports collisions between compound parts, but only the parent body was registered against its renderable, so every dispatch failed its lookup and returned early. That silently dropped onCollision and the whole onCollision* lifecycle for any multi-shape body, while single-shape bodies worked normally
  • FadeEffect.destroy() and MaskEffect.destroy() threw "Instance is already in pool" when called twice. Reachable without doing anything unusual, since removePostEffect() destroys the effect it removes, so a caller that also destroyed it explicitly got a throw from inside the pool

Compatibility

No breaking changes. Everything is additive, and the adapter peer ranges stay >=20.0.0: they dispatch these hooks themselves, so the events work on any melonJS 20.x.

Released alongside

package version
@melonjs/planck-adapter 1.3.0
@melonjs/matter-adapter 1.2.0

Install

:::bash
npm install melonjs@20.1.0

Full details in the CHANGELOG.

Source: README.md, updated 2026-08-23