| Name | Modified | Size | Downloads / 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 geometryShapeCollisionContactis 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 itsonCollisionStart/onCollisionActive/onCollisionEndnever fired.onCollisionwas 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 droppedonCollisionand the wholeonCollision*lifecycle for any multi-shape body, while single-shape bodies worked normallyFadeEffect.destroy()andMaskEffect.destroy()threw"Instance is already in pool"when called twice. Reachable without doing anything unusual, sinceremovePostEffect()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.