Questions about BouncyBubbles example

Hello,

I am trying to fully understand the Java BouncyBubbles example.

Here’s the code:

int numBalls = 12;
float spring = 0.05;
float gravity = 0.03;
float friction = -0.9;
Ball[] balls = new Ball[numBalls];

void setup() {
  size(640, 360);
  for (int i = 0; i < numBalls; i++) {
    balls[i] = new Ball(random(width), random(height), random(30, 70), i, balls);
  }
  noStroke();
  fill(255, 204);
}

void draw() {
  background(0);
  for (Ball ball : balls) {
    ball.collide();
    ball.move();
    ball.display();  
  }
}

class Ball {
  
  float x, y;
  float diameter;
  float vx = 0;
  float vy = 0;
  int id;
  Ball[] others;
 
  Ball(float xin, float yin, float din, int idin, Ball[] oin) {
    x = xin;
    y = yin;
    diameter = din;
    id = idin;
    others = oin;
  } 
  
  void collide() {
    for (int i = id + 1; i < numBalls; i++) {
      float dx = others[i].x - x;
      float dy = others[i].y - y;
      float distance = sqrt(dx*dx + dy*dy);
      float minDist = others[i].diameter/2 + diameter/2;
      if (distance < minDist) { 
        float angle = atan2(dy, dx);
        float targetX = x + cos(angle) * minDist;
        float targetY = y + sin(angle) * minDist;
        float ax = (targetX - others[i].x) * spring;
        float ay = (targetY - others[i].y) * spring;
        vx -= ax;
        vy -= ay;
        others[i].vx += ax;
        others[i].vy += ay;
      }
    }   
  }
  
  void move() {
    vy += gravity;
    x += vx;
    y += vy;
    if (x + diameter/2 > width) {
      x = width - diameter/2;
      vx *= friction; 
    }
    else if (x - diameter/2 < 0) {
      x = diameter/2;
      vx *= friction;
    }
    if (y + diameter/2 > height) {
      y = height - diameter/2;
      vy *= friction; 
    } 
    else if (y - diameter/2 < 0) {
      y = diameter/2;
      vy *= friction;
    }
  }
  
  void display() {
    ellipse(x, y, diameter, diameter);
  }
}

I don’t understand why in setup the creation of balls seem to refer to itself with the last parameter:
balls[i] = new Ball(random(width), random(height), random(30, 70), i, **balls**);

Also, the link between others,oin and Ball is not clear as well:

  Ball[] others;
 
  Ball(float xin, float yin, float din, int idin, Ball[] oin) {
    x = xin;
    y = yin;
    diameter = din;
    id = idin;
    others = oin;
  }

Then, this for routine is strange: for (Ball ball : balls). Why neither semicolons nor comparison but a colon?

Thank you for helping.

// balls is a list of objects of class Ball
// for (Ball ball : balls)
// means loop through all objects in list balls and give me each as :
// ball of class Ball

// more easy example:
String[] words = new String[] {"abc","def","ghi"};

for ( String word : words ) println(word);

/*
abc
def
ghi
*/

“:”==“in”
pls. speak:

for each word in words

1 Like

You can have a look here, we were speaking about it: Help a newbie with polymorphic particles

1 Like

Got it!

What about the other question?

i also just read it and, what can i say:
you and me need another year of hard work before we would be able
to come up with that kind of idea / structured coding,
so let us forget how that is be done by the “genius” and start at the beginning:
WHY?

a class is a powerful thing what has grown over the decades

  • -a- you have basics like int float…
  • -b- you have array of that basics or even , but these are all same type
  • -c- to come over that limitation there has been
    something like struct / records, a definition of a mix of variables of different type
    ( much like a data line in a excel table / the header line explains what they mean )
    what now is the first step of a class
  • -d- more, add to the public “record” you can have local variables
  • -e- and that makes the today class: IT can have methods

but over all a class describes ONE object ( with public and private properties ++)
that is the

class Ball

and one object would be a “ball of type Ball”

Ball ball

or you can make a list / array of items of that type Ball

Ball balls

and that would be all independent from each other,
and the class Ball don’t even know that there are others
unless you make ( from the outside ) a loop over all “balls”
to check on something, like the distance of each / to each other.

But if you now not want do that check loop from the outside,
you might try to do that inside, as a method of the class,
what is impossible unless the class has a link to the others.
( and by the way, that is insofar a easy example as it refs to “its” array of this class,
it might be that you want to check on objects of a other class “bricks of Brick” )

and that link to the array is what you see in the Ball definition

Ball oin

used in the

Ball.collide()

method.

so, sorry, i am good with it, just to know something like this can be done.
i go back to make my own easy/beginner examples

1 Like

Things became a bit less complex when I understood that ball was just the name of an iterator such as i in usual for loops and it has nothing to do with balls apart from the purpose of the sketch.

The loop could has been coded like this:

  for (Ball dadido : balls) {
    dadido.collide();
    dadido.move();
    dadido.display();  
  }

yes, that’s why you write

for ( int i

right, a loop local variable

but regarding your:

sorry: homework? try

int numBalls = 3;
//.. and after
      float minDist = others[i].diameter/2 + diameter/2;
      println("i:"+i+" id: "+id+" minDist: "+minDist);

is that looping clear?

This is now clear but still it’s strange to have this part of code below, because it seems one needs to provide a Ball object to define a Ball object. So it seems there’s a self-reference.

  Ball(float xin, float yin, float din, int idin, Ball[] oin) {
    x = xin;
    y = yin;
    diameter = din;
    id = idin;
    others = oin;
  }

no, not NEED, just WANT to use the data of a “external” array
funny that it is a array of its own class type
again, a class Ball does not know if/that you made a object ball or a array balls
of its or any kind.

Does it mean that the class Ball and the object Ball are not the same thing despite the same name?

Yes, it’s a way to avoid checking twice if a collision occurs between the two same balls. When you check the collision between the first ball and the others, there is a maximum number (2) of collisions to check, but the more you progress into the array of balls the number of collisions to check is reduced because actually these collisions have already been checked but from the opposite point of view, the other ball possibly involved.

1 Like

try it and you will get a ERROR
a class is a description
and a object is a (higher) variable of a type ( int, float, class Ball … )

add there is a naming convention for class Big letter, variable small letter

Try what? I don’t get it.

“Ball” can not be used 2 times, as name of a class and as name of a variable/object
so use class “Ball” and object “ball” or “balls”

but possibly the whole naming thing is bad?

String string;
String[] strings;

who would use that?
possibly better:

class Ball;
Ball my_ball;
Ball[] my_array_of_balls;
The idea is that every `Ball` object you are creating get the list of all the other `Ball` objects that you have created before: that is the oin variable so it is not a self-reference.

In the code, every time you create a Ball object, you add it the the balls array and you also give that list to the constructor of the Ball object.

The first time, the balls array is empty and you create the first Ball object: let’s call it Ball01. Ball01 is now created and its others array is empty (since the balls one was).

Now let’s create the second one. The balls array contain 1 Ball object: Ball01. Ball02 is now created and its others array contain Ball01.

And so on and so on. This way the others array of Ball03 will have Ball01 and Ball02 inside.

The idea is that after, when you want to collide you can just loop through all your Ball in the balls array without having to check for double collisions. You ca simply call the collide method that will check collision only with the Ball in others so only with the Ball created before.

1 Like

That was my basic understanding. However if the instance’s (?) name is different, the class/objet is the same and seems to refer to itself. The class includes an array with objects ot its own kind and which have not been defined yet?

class Ball {
  ...
  Ball[] others;

And how can the description of the object Ball include an array of Ball???
Ball(float xin, float yin, float din, int idin, Ball[] oin)

I must be missing somehing, huh?

jb4x your explanation arrived while I was typing my last message. It’s still not crystal clear but it helps a lot. Thank you.

yes, imagine how smart the compiler must be

1 Like

Yes, that’s a bit beyond common sense.

I’m writing a piece of code to illustrate. Hope it will make it crystal clear :slight_smile:

1 Like