Matter.js disable collision between different composites

2.4k views Asked by At

I am trying to use collision filtering as described in the "Matter.js body documentation". However, for my project I need to disable collisions between different Composite objects. So only bodies that are in the same composite should collide. I plan on having more then 32 Composites (32 is the maximum amount of collision categories provided by Matter.js). How would I achieve this?

// module aliases
var Engine = Matter.Engine,
    Render = Matter.Render,
    World = Matter.World,
    Bodies = Matter.Bodies,
    Body = Matter.Body,
    Vector = Matter.Vector,
    Composite = Matter.Composite,
    Constraint = Matter.Constraint,
    MouseConstraint = Matter.MouseConstraint;

// create an engine
var engine = Engine.create();

// create a renderer
var container = document.getElementById("container");
var canvas = document.getElementById("maincanvas");

var render = Render.create({
    element: container,
    canvas: canvas,
    engine: engine,
    options: {
        height: 400,
        width: 400,
        wireframes: false
    }
});

// This makes collision much easier to test
engine.world.gravity = {x:0, y:0};

// Add a mouseconstraint to test
var mc = MouseConstraint.create(engine, {
    element: render.canvas
});
Composite.add(engine.world, mc);

var bodies1 = []
var bodies2 = []
var xpos = 30
var ypos = 30
for (var i = 0; i < 5; i++){
    bodies1.push(Bodies.circle(xpos, ypos, 10, {
        collisionFilter: {
            group:-1
        },
        render: {
            fillStyle: "blue"
        }
    })
    );
    xpos += 30;
}
for (var i = 0; i < 5; i++){
    bodies2.push(Bodies.circle(xpos, ypos, 10, {
        collisionFilter: {
            group:-1
        },
        render: {
            fillStyle: "red"
        }
    })
    );
    xpos += 30;
}

var composite1 = Composite.create();
Composite.add(composite1, bodies1);
var composite2 = Composite.create();
Composite.add(composite2, bodies2);

Composite.add(engine.world, [composite1, composite2]);

Engine.run(engine);
Render.run(render);

This way I am able to disable collision between the composites, but this also disables collision 'inside' the composite. I could do this with the collisionFilter.category system but how would that work with more then 32 composites?

1

There are 1 answers

0
liabru On BEST ANSWER

There's no support for collision filtering at the composite level, you'll need to handle it at the body level. To make this easier to manage, just create some composite helper functions e.g. compositeSetCollisionFilter(composite, filter) and iterate over Composite.allBodies(composite).

Regarding the limit of 32 categories, this is due to a bitwise implementation (for performance supposedly, though I doubt it matters much in reality). I've raised an issue on the project about reconsidering this.

For now there's a way to have more though if you replace Matter.Detector.canCollide(filterA, filterB) with your own function that can compare two body.collisionFilter objects. With this you can use what ever scheme you like for body.collisionFilter objects.