Trying to slow down ellipses in a small space

Hello everyone!

I’m trying to make it so the “fireflies” in my code, while in the cup, move slower.
So far, the fireflies bounce off the walls, and once the player presses ‘g’, a cup is grabbed, and if the cup makes contact with a firefly, the firefly goes in the cup and bounces around in there, until released when the player pressed ‘p’.
However, while the fireflies are in the cup, they bounce around really fast. I’ve been trying to make it so they slow down (or even go the speed they are while outside the cup) but I can’t seem to do it.
I’ve tried to slow them by lowering the speed they move while in the cup, however, this either just doesn’t work, or only slows them after ‘p’ is pressed. I listed below some code I’ve tried.

I appreciate all the help I could get! Thank you in advance!


ArrayList <Fireflies> firefly;
float fireflies = 15; //num of fireflies
float cx = 200; //sitting cup position x
float cy = 200; //sitting cup position y
float cupW = 100; //cup width
float cupH = 135; //cup height

boolean inCup = false;

void setup() {
  size(600, 600);
  background(0);
  firefly = new ArrayList <Fireflies>();

  for (int f = 0; f < fireflies; f++) {
    firefly.add(new Fireflies());
  }
}

void draw() {
  background(0);

  //fireflies
  for (int f = 0; f < fireflies; f++) {
    firefly.get(f).display();
  }
}

class Fireflies {

  float size = random(1, 20);
  float xpos = random(0, width);
  float ypos = random(0, height);
  float xspeed = 1;
  float yspeed = 1;
  float xdir = random(-1, 1);
  float ydir = random(-1, 1);

  Fireflies() {
  }

  void update() {
    xpos = xpos + (xspeed * xdir);
    ypos = ypos + (yspeed * ydir);
  }

  void checkInCup() {
    if (inCup == true) { //changes the position of the fireflies to inside the cup
      xpos = random(cx, cx + cupW) + (xspeed * xdir);
      ypos = random(cy, cy + cupH) + (yspeed * ydir);
            
      //I tried to slow them down by incrementing the speed in small amounts- this didn't stop them 
      //while inside the jar
      
      //xpos = random(cx, cx + cupW) + (xspeed/16* xdir/16);
      //ypos = random(cy, cy + cupH) + (yspeed/16 * ydir/16);    
    }
  }

  void checkEdges() {
    if (inCup == false) {//if not in cup, bounces off sides of wall
      if (xpos > width-size || xpos < size) {
        xdir *=  -1 ;
      }
      if (ypos > height-size || ypos < size) {
        ydir *= -1;
      } else if (inCup == true) { //if in cup, bounces off sides of cup
        if (xpos > cx-size || xpos < cx) {
          xdir *= -1;
          //I also tried to slow them down here by making xdir a smaller number
          //xdir *= -.001
          //this also didn't slow them down in the cup
        }
        if (ypos > cy-size || ypos < cy) {
          ydir *= -1;
        }
      }
    }
  }

  void display() {
    update();
    checkEdges();
    checkInCup();

    //draw fireflies
    for (int f = 0; f < 1; f++) {
      fill(100, 100, 0);
      circle(xpos, ypos, size);
    }

    //grab cup
    if (key == 'g') {
      cx = mouseX;
      cy = mouseY;
      if (xpos > cx && ypos > cy) {
        inCup = true;
        //if the x&y pos. of the fireflies collide w/ the cup's x&y,
        //the fireflies go in the cup
        //i know this collision detection is... bad but it's not my focus right now :/
      }
    }

    //put cup down
    if (key == 'p') {
      cx = 200;
      cy = 200;
      inCup = false;
    }

    //cup
    fill(0, 230, 255, 50);
    rect(cx, cy, cupW, cupH);
  }
}

there is a few points to be criticized here

(this is only my personal opinion)

Remark 1

I think this:

boolean inCup = false;

must be INSIDE the class, because it’s an individual property of each firefly and therefore cannot be
globally.

Remark 2

Check whether the firefly is really inside the cup:

    if (xpos > cupX && 
      ypos > cupY && 
      xpos < cupX+cupW &&   // you didn't have this line
      ypos < cupY+cupH) {    // you didn't have this line
      inCup = true;
    } else {
      inCup = false;       // you didn't have this line 
    }

Remark 3

In display() inside the class you have

    //draw fireflies
    for (int f = 0; f < 1; f++) {
      fill(100, 100, 0);
      circle(xpos, ypos, size);
    }

doesn’t make sense.

In the class we only look at ONE firefly.

We have just

      fill(100, 100, 0);
      circle(xpos, ypos, size);

(we do the for-loop in draw(), not here)

Remark 4

The class should be single purpose.

So you shouldn’t draw the cup inside the
class!!!

(also you display the cup every time you show a firefly, which is far too often. Just move these lines to draw())

    //grab cup
    if (key == 'g') {
      cx = mouseX;
      cy = mouseY;
      if (xpos > cx && ypos > cy) {
        inCup = true;
        //if the x&y pos. of the fireflies collide w/ the cup's x&y,
        //the fireflies go in the cup
        //i know this collision detection is... bad but it's not my focus right now :/
      }
    }

    //put cup down
    if (key == 'p') {
      cx = 200;
      cy = 200;
      inCup = false;
    }

    //cup
    fill(0, 230, 255, 50);
    rect(cx, cy, cupW, cupH);
  }

My version


// class name singular (represents ONE firefly only; list name plural: represents many fireflies
ArrayList <Firefly> fireflies;

// better name here:  
float firefliesNumber = 15; //num of fireflies

// better names here: 
float cupX = 200; //sitting cup position x
float cupY = 200; //sitting cup position y
float cupW = 100; //cup width
float cupH = 135; //cup height

void setup() {
  size(600, 600);
  background(0);

  fireflies = new ArrayList <Firefly>();

  for (int f = 0; f < firefliesNumber; f++) {
    fireflies.add(new Firefly());
  }//for
}//func 

void draw() {
  background(0);

  //grab cup
  if (key == 'g') {
    cupX = mouseX;
    cupY = mouseY;
  }

  //put cup down
  if (key == 'p') {
    cupX = 200;
    cupY = 200;
  }

  //cup
  fill(0, 230, 255, 50);
  rect(cupX, cupY, 
    cupW, cupH);

  //fireflies
  for (int f = 0; f < firefliesNumber; f++) {
    fireflies.get(f).display();
  }//for 
  //
}//func 

//====================================================================================

class Firefly {

  float size = random(1, 20);
  float xpos = random(0, width);
  float ypos = random(0, height);
  float xspeed = 1;
  float yspeed = 1;
  float xdir = random(-1, 1);
  float ydir = random(-1, 1);

  boolean inCup = false; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  Firefly() {
    // empty constructor
  }

  void update() {
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    if (! inCup) { // means == false 
      xpos = xpos + (xspeed * xdir);
      ypos = ypos + (yspeed * ydir);
    } else {
      xpos = xpos + (xspeed * xdir * 0.51); // SLOW 
      ypos = ypos + (yspeed * ydir * 0.51);
    }//else
  }//method

  void checkInCup() {
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    if (xpos > cupX && 
      ypos > cupY && 
      xpos < cupX+cupW && 
      ypos < cupY+cupH) {
      inCup = true;
    } else {
      inCup = false;
    }
  }//method

  void checkEdges() {

    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    if (! inCup) {  
      // if not in cup, bounces off sides of wall
      if (xpos > width-size || xpos < size) {
        xdir *=  -1;
      }
      if (ypos > height-size || ypos < size) {
        ydir *= -1;
      }
    }
    //--------

    else { 
      // PREVIOULY: THIS CANNOT BE REACHED EVER !!!!!!!!!!!!!!!!!!!!!!!!!
      // if in cup, bounces off sides of cup
      if (xpos < cupX+size) {
        xdir = abs (xdir);
        //I also tried to slow them down here by making xdir a smaller number
        //xdir *= -.001
        //this also didn't slow them down in the cup
      }
      if (xpos > cupX+cupW) {
        xdir = - abs (xdir);
      }

      if (ypos < cupY+size) { 
        ydir = abs (ydir);
      }
      if (ypos > cupY+cupH) {
        ydir = -1 * abs (ydir);
      }
    }
    //
  }//method

  void display() {
    // MAIN FUNCTION OF THE CLASS 
    update();
    checkEdges();
    checkInCup();

    //draw firefly
    fill(100, 100, 0);
    ellipse(xpos, ypos, size, size);
  }//method
  //
}//class
//

I concentrated on doing this.

The firefly can enter the cup when it stands still. They are then trapped.

That’s also to do.

Okay, I might start crying. This is honestly fantastic, thank you so much! I tried it all and it works great!!

For the fireflies being released, I made a temporary fix, where the user presses ‘r’ and inCup is made false.

 void checkInCup() {

   if (xpos > cupX &&
     ypos > cupY &&
     xpos < cupX+cupW &&
     ypos < cupY+cupH) {
     inCup = true;
   } else {
     inCup = false;
   }//else

   //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> here is the change!
   //release fireflies
   if (key == 'r') {
     inCup = false;
   }
   //
 }//method

I’m not sure if it belongs in the checkInCup() function, but it does achieve what I want. I also wonder if there is a way to keep the fireflies in the cup, and not have them leave as it moves? Sort of like keeping a lid on it, so the fireflies don’t escape when the cup is dragged.

Nonetheless, I truly appreciate the help. I’ve only been coding for about a year now, mostly self-taught, so I appreciate all the formatting critiques I can get. Thanks again!

1 Like

Remark

I would change your change to

    //release fireflies
    if (keyPressed && key == 'r') {
      inCup = false;
    }

so it’s not permanent (but only when you actual hold the key).

Remark

You can a make a 2nd class Cup. Just as a practice.
It would hold the cup data and some methods.

Remark

I show you a new for-loop:

This:

  for (int f = 0; f < firefliesNumber; f++) {

can be

   for (Firefly currentFirefly : fireflies) {

No .get(....) needed anymore. Nice.

(This is not possible in setup(), only in draw())

Remark

Actually in the class when saying

if (xpos < cupX+size) { etc.

we want

if (xpos < cupX+size/2) {

because size is the diameter, not the radius for ellipse() command. Check reference for ellipse() command and ellipseMode().


New version

Check this out.

You can drag and drop the cup now with the mouse (check variable drag). No g/p keys needed anymore!

During drag, the fireflies inside the cup are moved together with the cup.

Release with r.

Warm regards,

Chrisir

// class name singular (represents ONE firefly only; list name plural: represents many fireflies
ArrayList <Firefly> fireflies;

// better name here:  
float firefliesNumber = 15; //num of fireflies

// better names here: 
float cupX = 200; //sitting cup position x
float cupY = 200; //sitting cup position y
float cupW = 100; //cup width
float cupH = 135; //cup height

boolean drag = false; 
PVector offset=new PVector(0, 0);

// ----------------------------------------------------------------------------

void setup() {
  size(600, 600);
  background(0);

  fireflies = new ArrayList <Firefly>();

  for (int f = 0; f < firefliesNumber; f++) {
    fireflies.add(new Firefly());
  }//for
}//func 

void draw() {
  background(0);

  // keys
  checkKeys(); 

  //cup
  fill(0, 230, 255, 50);
  noStroke(); 
  if (drag) 
    stroke(211); 
  rect(cupX, cupY, 
    cupW, cupH);
  // reset 
  noStroke(); 

  float x1=0, y1=0; 
  if (drag) {
    // DRAG cup
    x1=mouseX-pmouseX;
    y1=mouseY-pmouseY;
    cupX = mouseX-offset.x;
    cupY = mouseY-offset.y;
  }

  //fireflies
  for (Firefly currentFirefly : fireflies) {
    if (drag&&currentFirefly.inCup) {
      currentFirefly.xpos+=x1; 
      currentFirefly.ypos+=y1;
    }
    currentFirefly.display();
  }//for 
  //
}//func 

// ----------------------------------------------------------------------------

void checkKeys() {
  //  you can delete this 
  if (! keyPressed) 
    return; 

  if (key == 'g') {
    //grab cup
    cupX = mouseX;
    cupY = mouseY;
  } else if (key == 'p') {
    //put cup down
    cupX = 200;
    cupY = 200;
  }
}

void mousePressed() {
  if (mouseX > cupX && 
    mouseY > cupY && 
    mouseX < cupX+cupW && 
    mouseY < cupY+cupH) {
    drag = true;
    offset.set(mouseX-cupX, 
      mouseY-cupY);
  }
}

void mouseReleased() {
  drag=false;
}

//==================================================================

class Firefly {

  float size = random(2, 20);

  // location 
  float xpos = random(0, width);
  float ypos = random(0, height);

  // speed (gets changed in the constructor. Here we avoid that a value is 0 or close to 0)
  float xdir = random(0.32, 1.1);
  float ydir = random(0.32, 1.1);

  boolean inCup = false;

  Firefly() {
    // constructor

    if (random(1)<0.5)
      xdir*=-1; 
    if (random(1)<0.5)
      ydir*=-1;
  }

  void update() {
    // move 
    if (! inCup) { 
      xpos = xpos + (xdir); // fast 
      ypos = ypos + (ydir);
    } else {
      xpos = xpos + (xdir * 0.31); // SLOW 
      ypos = ypos + (ydir * 0.31);
    }//else
  }//method

  void checkInCup() {
    // set inCup field 
    if (xpos > cupX && 
      ypos > cupY && 
      xpos < cupX+cupW && 
      ypos < cupY+cupH) {
      inCup = true;
    } else {
      inCup = false;
    }

    //release fireflies
    if (keyPressed && key == 'r') {
      inCup = false;
    }
    //
  }//method

  void checkEdges() {
    // 
    if (! inCup) {  
      // if not in cup, bounces off sides of wall
      if (xpos > width-size/2 ) {
        xdir =  -1 * abs(xdir);
      }
      if (xpos < size/2) {
        xdir =  abs(xdir);
      } 

      if (ypos > height-size/2) {
        ydir = -1 * abs(ydir);
      }
      if (ypos < size/2) {
        ydir = abs(ydir);
      }
    }//if

    //--------

    else { 
      // if in cup, bounces off sides of cup
      if (xpos < cupX+size/2) {
        xdir = abs (xdir);
      }
      if (xpos > cupX+cupW-size/2) {
        xdir = - abs (xdir);
      }

      if (ypos < cupY+size/2) { 
        ydir = abs (ydir);
      }
      if (ypos > cupY+cupH-size/2) {
        ydir = -1 * abs (ydir);
      }
    }
    //
  }//method

  void display() {
    // MAIN FUNCTION OF THE CLASS 
    update();
    checkEdges();
    checkInCup();

    //draw firefly
    fill(100, 100, 0);
    ellipse(xpos, ypos, size, size);
  }//method
  //
}//class
//