How to initialize CLASS by it's own function?

I can assign a new value to the variables.
But I can’t use constructor to initialize the variables in the object function.

int nums = 20;
Drop[] drops = new Drop[nums]; 

void setup() { 
  size(800, 800); 
  smooth();
  // initialize
  for (int i=0; i < drops.length; i++) {
    drops[i] = new Drop();
  }
} 

void draw() { 
  background(255); 

  for (int i=0; i < drops.length; i++) { 
    drops[i].display();
    drops[i].move();

    //// 1.Works well
    //if (drops[i].reachedBottom1()) {
    //  drops[i] = new Drop();
    //}

    //// 2.Works well
    //drops[i].reachedBottom2();
    
    // 3.Why didn't work?
    drops[i].reachedBottom3(drops[i]);
  }
}


class Drop { 
  float x, y;
  float speed;
  float r;

  Drop() { 
    r = random(2, 6); 
    x = random(width);
    y = -r; 
    speed = r;
  } 

  void move() { 
    y += speed;
  } 

  void display() { 
    fill(50, 100, 150); 
    noStroke(); 
    circle(x, y, 2*r);
  }

  // 1.Works well
  boolean reachedBottom1() {
    if (y > height+r) { 
      return true;
    } else {
      return false;
    }
  }

  // 2.Works well
  void reachedBottom2() {
    Drop drop = new Drop();
    if (y > height+r) {
      r = random(2, 6); 
      x = random(width);
      y = -r; 
      speed = r;
    }
  }

  // 3.Why didn't work?
  Drop reachedBottom3(Drop self) {
    Drop drop = new Drop();
    if (y > height+r) {
      return drop;
    } else {
      return self;
    }
  }
}
1 Like

The method Drop::reachedBottom3() returns a Drop object but you don’t do anything with it.

BtW, the method can be shortened to 1 return statement:

Drop reachedBottom3(final Drop self) {
  return y > height + r? new Drop() : self;
}

You need to reassign the returned Drop object back to the array:
drops[i] = drops[i].reachedBottom3(drops[i]);

However that’s pretty awkward b/c the Drop object should be able to restart by its own w/o the caller having to do anything.

Instead you should define a method that respawn() the Drop’s fields back to their constructor values.

Basically you move anything inside Drop’s constructor to that separate method and invoke it inside the constructor instead.

And within method move() check whether field y has reached the bottom and invoke respawn() if so.

Here’s the refactoring I did to your sketch. Check it out:

Another similar sketch called “Raining Cloud”:
http://Studio.ProcessingTogether.com/sp/pad/export/ro.9l84$2z--gWui

2 Likes

Thanks.
Your refactoring is so simplicity and clean. As a beginner, I learned a lot from it.

1 Like