
// SimpleAttractors.java
// Jeff Traer-Bernstein
// Robert Sedgewick and Kevin Wayne
// Slightly reformatted by Andrew Davison, Nov. 2022

/* n particles are attracted to the mouse; 
   the particles are randomly rearranged when the
   user clicks the mouse.

   Usage:
     > compile SimpleAttractors.java
     > run SimpleAttractors <no. particles>
   e.g.
     > run SimpleAttractors 20
*/



public class SimpleAttractors
{

  public static void main(String[] args)
  {
    if (args.length != 1) {
      System.out.println("Usage: run SimpleAttractors <no. particles>");
      return;
    }
    int n = Integer.parseInt(args[0]);

    double[] rx = new double[n];
    double[] ry = new double[n];
    double[] vx = new double[n];
    double[] vy = new double[n];

    double dt = 0.5;
    double mass = 1.0;
    double drag = 0.05; // try changing this to 0.1 or 0.01 or even 0...

    double attractionStrength = 0.01;

    // initialize the drawing area
    StdDraw.setPenColor(StdDraw.BLUE);
    StdDraw.enableDoubleBuffering();
    StdDraw.setScale(-1, +1);

    while (true) {
      // if mouse is pressed add some random velocity to all particles
      if (StdDraw.isMousePressed())
        for (int i = 0; i < n; i++) {
          vx[i] = 0.2 * Math.random() - 0.1;
          vy[i] = 0.2 * Math.random() - 0.1;
        }

      // clear all the forces
      double[] fx = new double[n];
      double[] fy = new double[n];

      // add attraction forces for attraction to the mouse
      for (int i = 0; i < n; i++) {
        double dx = StdDraw.mouseX() - rx[i];
        double dy = StdDraw.mouseY() - ry[i];
        fx[i] += attractionStrength * dx;
        fy[i] += attractionStrength * dy;
      }

      // add drag forces to all particles
      // drag is proportional to velocity in the opposite direction
      for (int i = 0; i < n; i++) {
        fx[i] += -drag * vx[i];
        fy[i] += -drag * vy[i];
      }

      // update positions
      // euler step
      for (int i = 0; i < n; i++) {
        vx[i] += fx[i] * dt / mass;
        vy[i] += fy[i] * dt / mass;
        rx[i] += vx[i] * dt;
        ry[i] += vy[i] * dt;
      }

      StdDraw.clear();

      // draw a filled circle for each particle
      for (int i = 0; i < n; i++)
        StdDraw.filledCircle(rx[i], ry[i], 0.01);

      StdDraw.show();
      StdDraw.pause(10);
    }
  } /* main */

} // end of SimpleAttractors class
