Search code examples
javascriptbox2dmatter.js

Prevent matterjs bodies from escaping a predefined area


Based on the matterjs demo I also created a set of bodies that live within an area. Just like in the demo the area is defined by four static bodies that together define a box.

When wildly moving bodies with the box they somehow seem to escape by going through the walls. Is there a way to prevent this escaping form happening? Maybe an alternative way to define the box?


Solution

  • This is actually a problem with all of these of collision detection algorithms.

    What I ended up doing was adding code that knows about the box's boundaries and checks every 300 msecs if any of the bodies is outside of it. If so it uses Matter.Body.translate to put them back into the box again.

    Notice that this code does not use the game loop but rather events for its check mechanism execution trigger. It would be nicer to do this using the matterjs game loop (run the retrieval every so many ticks), but I did not realise that at the time.

    This is the code I ended up using (in my case the box is as big as the canvas itself):

    /* `allBodies` is a variable that contains all the bodies that can
     * escape. Use something like `Composite.allBodies(world)` to get 
     * them all but beware to not include the box's borders which are
     * also bodies.
     * `startCoordinates` is an object that contains the x and y
     * coordinate of the place on the canvas where we should move escaped
     * bodies to.
     */
    function initEscapedBodiesRetrieval(allBodies, startCoordinates) {
    
        function hasBodyEscaped(body) {
            var x = body.position.x;
            var y = body.position.y;
    
            return x < 0 || x > _canvasWidth || y < 0 || y > _canvasHeight;
        }
    
        setInterval(function() {
            var i, body;
    
            for (i = 0; i < allBodies.length; i++) {
                body = allBodies[i];
                if (hasBodyEscaped(body)) {
                    Matter.Body.translate(body, { x: (startCoordinates.x - body.position.x), y: (startCoordinates.y - body.position.y) });
                }
            }
        }, 300); /* We do this every 300 msecs */ 
    }