liabru / matter-attractors

an attractors plugin for matter.js
MIT License
149 stars 31 forks source link

Repulsion Example #14

Closed adamcoulombe closed 4 years ago

adamcoulombe commented 4 years ago

I am trying to use this plugin, but maybe Im not understanding how the function is supposed to work.

I trying to apply a repulsion so I am using the plugin like so:

  plugin: {
    attractors: [
      function(bodyA, bodyB) {
        var force = {
          x: -(bodyA.position.x - bodyB.position.x) * 1e-5,
          y: -(bodyA.position.y - bodyB.position.y) * 1e-5,
        };

        // apply force to both bodies
        Matter.Body.applyForce(bodyA, bodyA.position, Matter.Vector.neg(force));
        Matter.Body.applyForce(bodyB, bodyB.position, force);
      }
    ]
  }

but the force seems to be greater when the bodies are further from each other. why is this?

example: https://codepen.io/adamcoulombe/pen/oNjLBBM

probityrules commented 4 years ago

Your math is defining force such that greater distance equals more force: if you have both bodies at y = 0; and one's x at 0 and the other's at 1, the force is 0.00001. However, if you have the latter's at x = 1000;, the force is 0.01.

Relatedly, you will get more force for the same amount of distance diagonally than you will along the x or y axis, since you're treating both axis apart from each other.

I might recommend having something like 1 / distance to make attraction/repulsion exponentially stronger the closer the bodies are, and define distance as something like Math.sqrt(deltaX * deltaX + deltaY * deltaY);

adamcoulombe commented 4 years ago

Thanks.... I tried my best to interpret your recommendations, and it seems a little better. but I think i may still have something wrong...

  plugin: {
    attractors: [
      function(bodyA, bodyB) {
        var deltaX = bodyA.position.x - bodyB.position.x;
        var deltaY = bodyA.position.y - bodyB.position.y;
        var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
        return {
          x: 1/distance,
          y: 1/distance,
        };
      }
    ]
  }

https://codepen.io/adamcoulombe/pen/qBOaxem?editors=0010

I appreciate your help :)

probityrules commented 4 years ago

Yeah, you need to maintain the original vector's direction for the above to work. Probably something like the following to make a unit vector and then apply the correct amount of force along each axis:

    var deltaX = bodyA.position.x - bodyB.position.x;
    var deltaY = bodyA.position.y - bodyB.position.y;
    var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
    var force = 1 / distance;
    var unitX = deltaX / distance;
    var unitY = deltaY / distance;
    return {
        x: -unitX * force,
        y: -unitY * force
    };
adamcoulombe commented 4 years ago

Ah!! there we go! That's exactly what i was looking to do.

I will say it again, I really appreciate the help.

The math is a little beyond me but this lib appears to do what I was in search of.

Thank you!!