Search code examples
javascriptphysicsjs

How to setup interactive and non-interactive objects in PhysicsJS?


I am trying to setup a seesaw with userdragable objects. After world creation in PhysicsJS, mouse drag interaction is added by

world.add( Physics.behavior('interactive', { el: renderer.el }) );

which works fine. Subsequently, I want some added objects to be draggable (the box objects). But the lever should not be draggable, but it should interact with the boxes. So the lever should rotate according to a replaced box. The fulcurm is placed in a noninteractive way by setting its treatment property to static:

world.add( Physics.body('convex-polygon', {
        name: 'fulcrum',
        x: 250,
        y: 490,
        treatment: 'static',
        restitution: 0.0,
        vertices: [
            {x: 0, y: 0},
            {x: 30, y: -40},
            {x: 60, y: 0},
        ]
    }) );

How can objects be interacting with each other, but only some are userdragable?

A fiddle is available at: http://jsfiddle.net/YM8K8/


Solution

  • At the moment this is not supported... but it should be. I've added it as a bug on github. https://github.com/wellcaffeinated/PhysicsJS/issues/101

    In the meantime, if you want, you can create a new "interactive" behavior by copying and pasting and just change the name.

    Physics.behavior('interactive-custom', function( parent ){ ...
    

    Then in the grab function just make this small addition:

    body = self._world.findOne({ $at: new Physics.vector( pos.x, pos.y ) });
    

    Change to:

    body = self._world.findOne({ $at: new Physics.vector( pos.x, pos.y ), $in: self.getTargets() });
    

    What that does is when it's searching for the body at the mouse coordinates, it will also check to see if that body is in the set that you've applied this behavior to.

    Then instead of adding the behavior before the bodies in your fiddle, add it at the end, and do this:

    world.add( 
        Physics.behavior('interactive-custom', { el: renderer.el })
            .applyTo(world.find({ name: 'box' })) 
    );
    

    This will use world.find to find the bodies currently in the world that have the "box" name. Then it sends that array of bodies to the behavior and tells the behavior to only apply itself to those bodies.

    Here's the modified fiddle:

    http://jsfiddle.net/wellcaffeinated/YM8K8/1/