1

I want to create an ArrayList of ball objects, which should be in a loop until there are 100 pieces.

Now my problem: I must implement a function hitTest, so that when you click on a ball it gets removed. In the same position, there should appear two balls then, which go into a different direction.

Can someone help me? I am so lost...

Here's my code so far:

Ball b; 
ArrayList<Ball> balls;

void setup() { 
  size(800, 800); 
  balls = new ArrayList<Ball>(); 
  for (int i = 0; i<100; i++) { 
    drawBall();
  }
}

void draw() { 
  background(255); 
  //b.update(); 
  for (int i= 0; i<balls.size(); i++) { 
    balls.get(i).update();
  }
}

void drawBall() { 
  Ball b = new Ball(); 
  balls.add(b);
}

class Ball { 
  private float x; 
  private float y; 
  private float ballSize; 
  private float dirX; 
  private float dirY; 
  private boolean moving = true; 
  Ball() { 
    this.x = width/2; 
    this.y = height/2; 
    this.ballSize = random(10.0, 30.0); 
    this.dirX = random(-3.0, 3.0); 
    this.dirY = random(-3.0, 3.0); 
    if (this.dirX<1.0 && this.dirX>1.0)  //1 statt -1 macht zufälliger { this.dirX = 1.0; } 
      if (this.dirY<1.0 && this.dirY>1.0) { 
        this.dirY = 1.0;
      }
  }

  public void update() { 
    stroke(255); 
    fill(random(255), random(255), random(255), random(255)); 
    ellipse( this.x, this.y, this.ballSize, this.ballSize); 
    if (this.moving == true) { 
      this.x += this.dirX; 
      this.y += this.dirY;
    } 
    if (this.x+ this.ballSize/2> width ||this.x- this.ballSize/2<0) { 
      this.dirX= dirX*-1;
    } 
    if (this.y+ this.ballSize/2> height ||this.y- this.ballSize/2<0) { 
      this.dirY= dirY*-1;
    }
  }
}
laancelot
  • 3,138
  • 2
  • 14
  • 21
Julia
  • 29
  • 2
  • Tab 1: Ball b; ArrayList balls; void setup() { size(800,800); balls = new ArrayList(); for(int i = 0; i<100; i++) { drawBall(); } } void draw() { background(255); //b.update(); for(int i= 0; i – Julia Jan 05 '21 at 23:12
  • Tab 2: `code` class Ball { private float x; private float y; private float ballSize; private float dirX; private float dirY; private boolean moving = true; Ball() { this.x = width/2; this.y = height/2; this.ballSize = random(10.0,30.0); this.dirX = random(-3.0,3.0); this.dirY = random(-3.0,3.0); if(this.dirX<1.0 && this.dirX>1.0)//1 statt -1 macht zufälliger { this.dirX = 1.0; } if(this.dirY<1.0 && this.dirY>1.0) { this.dirY = 1.0; } } – Julia Jan 05 '21 at 23:13
  • Tab 2 part 2: public void update() { stroke(255); fill(random(255),random(255),random(255), random(255)); ellipse( this.x, this.y, this.ballSize, this.ballSize); if(this.moving == true) { this.x += this.dirX; this.y += this.dirY; } if(this.x+ this.ballSize/2> width ||this.x- this.ballSize/2<0) { this.dirX= dirX*-1; } if(this.y+ this.ballSize/2> height ||this.y- this.ballSize/2<0) { this.dirY= dirY*-1; } } } – Julia Jan 05 '21 at 23:13
  • It would be great if you could move your code out of the comments and into the body of the question. Then you can format it nicely using the suggestions in https://meta.stackoverflow.com/questions/251361/how-do-i-format-my-code-blocks – Breandán Dalton Jan 05 '21 at 23:32
  • 1
    @Julia I tried to add the code from the comments in the question as it'll improve your chances of getting help A TON, but since the comments are one-liners and there are comments through your code I may have made an error. Please double-check it to make sure that it's still the same code you're working with (it compiles at least, but you have a better chance to spot a mistake than I have). – laancelot Jan 06 '21 at 00:20

1 Answers1

2

Break your problem down into smaller, simpler steps.

e.g.

when you click on a ball, it gets removed. In the same position, there should appear two balls then, which go into a different direction.

  1. when you click on a ball: you can mix the dist() function (to check if the distance between the mouse and a ball is smaller then the radius) with mouseClicked() (or mousePressed() / mouseReleased())
  2. it gets removed: you already called balls.add(). Similarly you can call balls.remove() passing the ball object or index to remove (depending on the case)
  3. same position: you need to remember (store the coordinates) of the ball that was clicked to add two balls at the same position
  4. different direction: you already do that in the Ball() constructor: you can apply the same logic on each new ball.

Here's a basic sketch to illustrate point 1, using dist():

void draw(){
  background(255);
  int ballX = 50;
  int ballY = 50;
  int ballRadius = 35;
  
  if(dist(ballX, ballY, mouseX, mouseY) < ballRadius){
    fill(0,192,0);
  }else{
    fill(192,0,0);
  }
  
  ellipse(ballX,ballY, ballRadius * 2, ballRadius * 2);
}

Paste this in a new sketch, run it and you should get the hang of using dist() in the context of your problem.

Regarding points 2,3,4 here's a modified version of your sketch with comments and a slightly different approach: instead of removing a ball to add a new one at the exact location with a different direction, simply randomise the direction. Visually it will look similar to a new ball (except the random size/colour). With the clicked ball being re-used, only a second one is added:

Ball b; 
ArrayList<Ball> balls;

void setup() { 
  size(800, 800); 
  balls = new ArrayList<Ball>(); 
  for (int i = 0; i<100; i++) { 
    drawBall();
  }
}

void draw() { 
  background(255); 
  //b.update(); 
  for (int i= 0; i<balls.size(); i++) {
    // pass the mouse coordinates to each ball to check if it's hovered or not
    balls.get(i).update(mouseX, mouseY);
  }
}

// on mouse pressed
void mousePressed(){
  for (int i= 0; i<balls.size(); i++) {
    // make current ball reusable in this loop
    Ball ball = balls.get(i); 
    // if ball is hovered
    if(ball.isHovered){
      // randomize direction of current ball
      ball.setRandomDirection();
      // add a new ball from the current location
      balls.add(ball.copy());
    }
  }
}

void drawBall() { 
  Ball b = new Ball(); 
  balls.add(b);
}

class Ball { 
  
  private float x; 
  private float y; 
  private float ballSize; 
  private float dirX; 
  private float dirY; 
  private boolean moving = true;
  private color fillColor;
  // property to keep track if the ball is hovered or not
  private boolean isHovered;
  
  Ball() { 
    this.x = width/2; 
    this.y = height/2; 
    this.ballSize = random(10.0, 30.0); 
    this.setRandomDirection();
    this.fillColor = color(random(255), random(255), random(255), random(255));
  }
  // extract random direction calls into a re-usable function (handy for click / collision)
  void setRandomDirection(){
    this.dirX = random(-3.0, 3.0); 
    this.dirY = random(-3.0, 3.0); 
    if (this.dirX<1.0 && this.dirX>1.0) { //1 statt -1 macht zufälliger { this.dirX = 1.0; } 
      if (this.dirY<1.0 && this.dirY>1.0) { 
        this.dirY = 1.0;
      }
    }
  }
  
  public void update(int x, int y) {
    // euclidean distance between this ball's coordinates a given x y position (e.g. mouse)
    isHovered = dist(this.x, this.y, x, y) < this.ballSize / 2;
    // optional: use stroke color to visually display highlighted ball
    if(isHovered){
      stroke(0);
    }else{
      stroke(255);
    }
    
    fill(fillColor); 
    ellipse( this.x, this.y, this.ballSize, this.ballSize); 
    if (this.moving == true) { 
      this.x += this.dirX; 
      this.y += this.dirY;
    } 
    if (this.x + this.ballSize / 2 > width ||
        this.x - this.ballSize / 2 < 0) { 
      this.dirX= dirX*-1;
    } 
    if (this.y + this.ballSize / 2 > height ||
        this.y - this.ballSize / 2 < 0) { 
      this.dirY= dirY*-1;
    }
  }
  // utility function: simply copies this ball's x,y position to the new one
  Ball copy(){
    Ball clone = new Ball();
    clone.x = this.x;
    clone.y = this.y;
    return clone;
  }
}

The copy() method is flexible enough that it's ease to remove one ball to add two more if that is an absolute must. For example:

// on mouse pressed
void mousePressed(){
  for (int i= 0; i<balls.size(); i++) {
    // make current ball reusable in this loop
    Ball ball = balls.get(i); 
    // if ball is hovered
    if(ball.isHovered){
      // add two new balls from the current location
      balls.add(ball.copy());
      balls.add(ball.copy());
      // remove ball
      balls.remove(i);
    }
  }
}
George Profenza
  • 50,687
  • 19
  • 144
  • 218