Processing: How can I make multiple elements in a for() loop move to one location then return?

I have a grid of ellipses generated by two for() loops. What I’d like to do is have all of these ellipses ease into mouseX and mouseY when mousePressed == true, otherwise return to their position in the grid. How can I go about this? I’ve started with this template, which doesn’t work as I can’t figure out how affect the position of the ellipses, but the easing is set up.

float x;
float y;
float easeIn = 0.01;
float easeOut = 0.08;
float targetX;
float targetY;

void setup() {
  size(700, 700);
  pixelDensity(2);
  background(255);
  noStroke();
}

void draw() {
  fill(255, 255, 255, 80);
  rect(0, 0, width, height);

  for (int i = 50; i < width-50; i += 30) {
    for (int j = 50; j < height-50; j += 30) {

      fill(0, 0, 0);
      ellipse(i, j, 5, 5);

      if (mousePressed == true) {

        // go to mouseX
        targetX = mouseX; 
        // ease in
        float dx = targetX - x;
        if (abs(dx) > 1) {
          x += dx * easeIn;
        }

        //go to mouseY
        targetY = mouseY;
        // ease in
        float dy = targetY - y;
        if (abs(dy) > 1) {
          y += dy * easeIn;
        }
      } else {

        // return to grid
        targetX = i;
        // ease out
        float dx = targetX - x;
        if (abs(dx) > 1) {
          x += dx * easeOut;
        }

        // return to grid
        targetY = j;
        // ease out
        float dy = targetY - y;
        if (abs(dy) > 1) {
          y += dy * easeOut;
        }
      }
    }
  }
}

Any help would be greatly appreciated. I’m not sure in which order to do things/which elements should be contained in the loop.

Thanks!

Answer

You’re going to have to keep track of a few things for each dot: its “home” position, its current position,its speed, etc.

The easiest way to do this would be to create a class that encapsulates all of that information for a single dot. Then you’d just need an ArrayList of instances of the class, and iterate over them to update or draw them.

Here’s an example:

ArrayList<Dot> dots = new ArrayList<Dot>();

void setup() {
  size(700, 700);
  background(255);
  noStroke();

  //create your Dots
  for (int i = 50; i < width-50; i += 30) {
    for (int j = 50; j < height-50; j += 30) {
      dots.add(new Dot(i, j));
    }
  }
}

void draw() {
  background(255);

  //iterate over your Dots and move and draw each
  for (Dot dot : dots) {
    dot.stepAndRender();
  }
}

class Dot {

  //the point to return to when the mouse is not pressed
  float homeX;
  float homeY;

  //current position
  float currentX;
  float currentY;

  public Dot(float homeX, float homeY) {
    this.homeX = homeX;
    this.homeY = homeY;
    currentX = homeX;
    currentY = homeY;
  }

  void stepAndRender() {

    if (mousePressed) {
      //use a weighted average to chase the mouse
      //you could use whatever logic you want here
      currentX = (mouseX+currentX*99)/100;
      currentY = (mouseY+currentY*99)/100;
    } else {
      //use a weighted average to return home
      //you could use whatever logic you want here
      currentX = (homeX+currentX*99)/100;
      currentY = (homeY+currentY*99)/100;
    }

    //draw the ellipse
    fill(0, 0, 0);
    ellipse(currentX, currentY, 5, 5);
  }
}

Note that I’m just using a weighted average to determine the position of each ellipse, but you could change that to whatever you want. You could give each ellipse a different speed, or use your easing logic, whatever. But the idea is the same: encapsulate everything you need into a class, and then put the logic for one dot into that class.

I’d recommend getting this working for a single dot first, and then moving up to getting it working with multiple dots. Then if you have another question you can post the code for just a single dot instead of a bunch. Good luck.

Leave a Reply

Your email address will not be published. Required fields are marked *