Search code examples
javascriptcanvasparticles

Particles "run away" from mouse


Im creating a simple particle experiment on canvas. Now i want them to "run away" from mouse coursor over canvas. detecting the distance from the mouse is not a problem, but how to code their behaviour?

each particle is created as following:

    var particle = {
        x: Math.floor(Math.random() * width),
        y: Math.floor(Math.random() * height),
        xVel: Math.random() * 10 - 5,
        yVel: Math.random() * 10 - 5,
    }

so i assume i should also save the direction somehow, and if the distance from pointer is < x, reverse the direction? maybe also save old speed, and decrease it slowly while moving away?

how to detect the direction?


Solution

  • Velocity (xVel, yVel, together) is a 2D vector. And so is the distance between the mouse and the particles. A vector contains both direction and magnitude. So you want a vector that is the difference between the mouse position and the particle position.

    var posRelativeToMouse = {
      x: particle.x - mousPosX,
      y: particle.y - mousPosY
    };
    

    So small numbers of x and y mean the the particle is close to the mouse, and big mean it's far away.

    Next we need to figure out how these numbers should affect the velocity of the particle. So we need 2 things.

    What direction do we push them in?

    We already have this, mostly. posRelativeToMouse is a vector that has the direction we want. We just normalize it, which means to set the length of the vector to 1. To do that, we divide each component by the current length of the vector. The length of this vector is always the distance to from the particle to the mouse.

    var distance = Math.sqrt(
      posRelativeToMouse.x * posRelativeToMouse.x +
      posRelativeToMouse.y * posRelativeToMouse.y
    );
    var forceDirection = {
      x: posRelativeToMouse.x / distance,
      y: posRelativeToMouse.y / distance,
    };
    

    How hard do we push the particles?

    This is an inverse of the distance. Close means a big push, far means a little push. So lets reuse our distance we calculated above.

    // distance past which the force is zero
    var maxDistance = 1000;
    
    // convert (0...maxDistance) range into a (1...0).
    // Close is near 1, far is near 0
    // for example:
    //   250 => 0.75
    //   100 => 0.9
    //   10  => 0.99
    var force = (maxDistance - distance) / maxDistance;
    
    // if we went below zero, set it to zero.
    if (force < 0) force = 0;
    

    Ok we have a direction, and we have the force. All that's left is to apply this to the particle velocity.

    particle.xVel += forceDirection.x * force * timeElapsedSinceLastFrame;
    particle.yVel += forceDirection.y * force * timeElapsedSinceLastFrame;
    

    And assuming you are animating your position each frame by that xVel/yVel, you should now have particles being pushed away by the mouse.