4

While creating my own version of the Matter.js slingshot demo[source] I got stuck while trying to prevent the projectile from being draggable after it was shot.

TL;DR

Looking for some guidance to stop the projectile from being draggable after it was fired.

My attempt:

Create 3 collisionFilter categories;

  1. 0x0001: static: Ground, platform, etc
  2. 0x0002: drag: Items that interact with mouse
  3. 0x0004: nodrag: Items that cannot interact with the mouse, but does collide with everything else

This works great, everything collides with each other, and I'm only able to drag the projectile (drag), not the targets (nodrag).

So my next challenge was to toggle the projectile from drag to nodrag after it was fired. Otherwise, you can grep the projectile and use it like a Wrecking Ball.

So Just before I add a new projectile to the elastic, I've tried toggling the collisionFilter to nodrag using the following code:

Events.on(engine, 'afterUpdate', function() {

    // If Rock is outside drag-range
    if (mouseConstraint.mouse.button === -1 && (rock.position.x > dragborder_x || rock.position.y < dragborder_y)) {

        rock.collisionFilter = { category: cat.nodrag };
        ...

Problem^^

Unfortunately this prevents the projectile from colliding with everything, even the walls (static). Even the targets with nodrag collide with the walls. So I have no clue why the projectile stops colliding after switching to nodrag.


Simplified example

  • Toggle line 72 to see the problem as described above
    // Failed attempt (line 72)
    // rock.collisionFilter = { category: cat.nodrag };
    

// Statics
const vw = window.innerWidth;
const vh = window.innerHeight;
var Engine = Matter.Engine, Render = Matter.Render, Runner = Matter.Runner, Composites = Matter.Composites, Events = Matter.Events, Constraint = Matter.Constraint, MouseConstraint = Matter.MouseConstraint, Mouse = Matter.Mouse, World = Matter.World, Bodies = Matter.Bodies;
const cat = {
    static:    0x0001,
    nodrag:    0x0002,
    drag:      0x0004
};

// Create world
var engine = Engine.create();
var world = engine.world;

// Create render
var render = Render.create({
    element: document.body,
    engine: engine,
    options: {
        width: vw,
        height: vh,
        wireframes: false,
        showAngleIndicator: false
    }
});
// render.on()
Render.run(render);

// Create runner
var runner = Runner.create();
Runner.run(runner, engine);

// Body consts
const rock_x = vw * .20;
const rock_y = vh * .66;
const rockOptions = { 
    density: 0.01,
    collisionFilter: {
        category: cat.drag
    }
};
const gift = {
    render: {
        sprite: {}
    },
    collisionFilter: {
        category: cat.nodrag
    }
};

// Add Static bodies
var ground   = Bodies.rectangle(vw * .5, vh * .9, vw * .9, 42, { isStatic: true, render: { fillStyle: '#060a19' } });
var rock     = Bodies.polygon(rock_x, rock_y, 8, 15, rockOptions);
var anchor   = { x: rock_x, y: rock_y };
var elastic  = Constraint.create({ pointA: anchor, bodyB: rock, stiffness: 0.09, render: { lineWidth: 1 } });
var wall     = Composites.stack(vw * .66, 0, 2, (vh * .4) / 15, 1, 0, (x, y) => Bodies.rectangle(x, y, 15, 15, gift));
var platform = Bodies.rectangle(vw * .75, vh * .6, 210, 21, { isStatic: true, render: { fillStyle: '#060a19' }, collisionFilter: { category: cat.static } });
var pyramid  = Composites.pyramid(vw * .30, 0, 11, 11, 0, 0, (x, y) => Bodies.rectangle(x, y, 15, 15, gift));

World.add(engine.world, [ ground, pyramid, platform, wall, rock, elastic ]);

// Rock drag
const dragborder_x = rock_x + 20;
const dragborder_y = rock_y - 20;
Events.on(engine, 'afterUpdate', function() {

    // If Rock is outside drag-range
    if (mouseConstraint.mouse.button === -1 && (rock.position.x > dragborder_x || rock.position.y < dragborder_y)) {

        // Failed attempt (line 72)
        // rock.collisionFilter = { category: cat.nodrag };

        // Add new Rock
        rock = Bodies.polygon(rock_x, rock_y, 7, 15, rockOptions);
        World.add(engine.world, rock);

        // Re-bind elastic
        elastic.bodyB = rock;
    }
});

// Mouse control
var mouse = Mouse.create(render.canvas);
var mouseConstraint = MouseConstraint.create(engine, {
    mouse: mouse,
    constraint: {
        stiffness: 0.2,
        render: {
            visible: false
        }
    }
});

// Add mouse
World.add(world, mouseConstraint);
render.mouse = mouse;

// Prevent mouse-drag
mouseConstraint.collisionFilter.mask = cat.static | cat.drag;

// Run
Engine.run(engine);
Render.run(render);
<script src="https://cdn.jsdelivr.net/npm/matter-js@0.16.1/build/matter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no,minimal-ui">
0stone0
  • 34,288
  • 4
  • 39
  • 64

0 Answers0