Brick Breaker Game - Problem with brick and ball interactions

I’ve been trying for a long time to make a successful brick breaker game, but I’m still stuck on how to make the ball and bricks to interact. Can someone help me figure out a way for one brick to disappear when the ball touches it? I am mainly having trouble with the “bounceBrick” function in the brickBreaker class. I also think it has to do with the brick class, but I am not sure. Here’s the code:

int rows = 6; //Number of bricks per row
int columns = 6; //Number of columns
int total = rows * columns; //Total number of bricks

brickBreaker brickBreaker;
ball ball;
paddle paddle;
brick[] bricks = new brick[total]; 

void setup() {
  size(800, 650);
  brickBreaker = new brickBreaker();
  ball = new ball();
  paddle = new paddle();
  for (int i = 0; i < rows; i++)
  {
    for (int j = 0; j < columns; j++)
    {
      bricks[i*rows + j] = new brick((i+1) *width/(rows + 1), (j+1) * 75); //places all the bricks into the array, properly labelled.
    }
  }
}


void draw() {
  background(51);
  for (int i = 0; i < total; i++) {
    bricks[i].show();
}
    ball.show();
    paddle.update();
    brickBreaker.bounce();
    brickBreaker.reset();
    brickBreaker.showText();
    brickBreaker.bounceBrick();
}

void mousePressed() {
  brickBreaker.gameStart();
}

BrickBreaker Class

class brickBreaker {
  boolean gameStart;
  int score;
  int gameScore;
  boolean hit;
  int lives;
  boolean override;
  int rows = 6; //Number of bricks per row
  int columns = 6; //Number of columns
  int total = rows * columns; //Total number of bricks

  brickBreaker() {
    gameStart = false;
    score = 0;
    gameScore = 0;
    hit = false;
    lives = 5;
    override = false;
  }

  void gameStart() {
    if (gameStart == false) {
      gameStart = !gameStart;
    }
  }

  void bounce() {
    if (gameStart) {

      ball.update();

      // If ball hits paddle, switch direction
      if (ball.x > mouseX - paddle.psize/2 && ball.x < mouseX + paddle.psize/2 && ball.y == paddle.y) {

        // Bounce
        ball.vy = ball.vy * -1;

        // Decrease paddle size
        paddle.psize -= 5;
      }
  }
}

  void reset() {
    if (ball.y > height) {
      ball.x = 400;
      ball.y = 560;
      ball.vx = 4;
      ball.vy = 4;
      lives -= 1;
      gameStart = false;
    }
    if (lives <= 0) {
      gameOver();
    }
    if (score == total) {
      win();
    }
  }

  void resetGame() {
    ball.x = 400;
    ball.y = 560;
    gameStart = false;
    paddle.psize = 150;
    paddle.y = 600;
    ball.vx = 4;
    ball.vy = 4;
    score = 0;
    gameScore = 0;
    lives = 5;
    //Setup array of all bricks on screen
    for (int i = 0; i < rows; i++)
    {
      for (int j = 0; j< columns; j++)
      {
        bricks[i*rows + j] = new brick((i+1) *width/(rows + 1), (j+1) * 80);
      }
    }
  }


  // Where Score and Lives is located
  void showText() {
    if (override == false) {
      textSize(50);     
      fill(255);          
      stroke(0);
      text(gameScore, 20, 50);
      textSize(25);
      text("Lives:", 20, 575);
      text(lives, 90, 575);
    }
  }

  void hit() {
    if (hit == true) {
    }
  }

  void gameOver() {
    override = true;
    if (override == true) {
      ball.x = -100;
      ball.vx = 0;
      ball.vy = 0;
      paddle.y = -100;
      textSize(50);
      fill(255, 0, 0);
      text("GAME OVER!!!", 250, 200);
      text("Score: ", 300, 300);
      text(gameScore, 450, 300);
      text("Click mouse to play again!", 100, 400);
      if (mousePressed) {
        override = false;
        resetGame();
      }
    }
  }

  void win() {
    override = true;
    if (override == true) {
      ball.x = -10;
      ball.vx = 0;
      ball.vy = 0;
      paddle.y = -50;
      textSize(50);
      fill(random(255), random(255), random(255));
      text("YOU WON!!!", 250, 200);
      text("Score: ", 300, 300);
      text(gameScore, 450, 300);
      text("Click mouse to play again!", 100, 400);
      if (mousePressed) {
        override = false;
        resetGame();
      }
    }
  }


  void bounceBrick() {
    for (int i = 0; i < total; i ++)
    {
      //If ball hits bottom of brick, ball moves down, increment score
      if (ball.y <= bricks[i].y + bricks[i].h/2 && ball.y > bricks[i].y && ball.x >= bricks[i].x - bricks[i].w/2 && ball.x <= bricks[i].x + bricks[i].w/2)
      {
        ball.vy *= -1;
        gameScore += 5;
        bricks[i].hit();
        hit = true;
      } 

      //If ball hits top of brick ball moves up, increment score
      if (ball.y >= bricks[i].y && ball.y <= bricks[i].y + bricks[i].h/2 && ball.x >= bricks[i].x && ball.x <= bricks[i].x + bricks[i].w) 
      {
        ball.vy *= -1;
        gameScore += 5;       
        bricks[i].hit();
        hit = true;
      }

      //if ball hits the left of the brick, ball switches to the right, and moves in same direction, increment score
      if (ball.x >= bricks[i].x && ball.x <= bricks[i].x + bricks[i].w/2 && ball.y >= bricks[i].y && ball.y <= bricks[i].y + bricks[i].h)
      {
        ball.vx *= -1;
        gameScore += 5;
        bricks[i].hit();
        hit = true;
      }

      //if ball hits the right of the brick, ball switches to the left, and moves in same direction, increment score
      if (ball.x <= bricks[i].x + bricks[i].w && ball.x >= bricks[i].x + bricks[i].w/2 && ball.y >= bricks[i].y && ball.y <= bricks[i].y + bricks[i].h)
      {
        ball.vx *= -1;
        gameScore += 5;
        bricks[i].hit();
        hit = true;
      }
    }
  }
}

Ball Class

class ball {

  float dia;
  float x;
  float y;
  float vx;
  float vy;
  color col;

  ball() {
    dia = 24;
    x = 400;
    y = 560;
    vx = 4;
    vy = 4;
    col = color(random(128, 255));
  }

  void show() {
    fill(col);
    ellipseMode(CENTER);
    ellipse(x, y, dia, dia);
  }

  void update () {
    x = x + vx;
    y = y + vy;

    if (x > width || x < 0) {
      vx = vx * -1;
    } else if (y > height || y < 0) {
      vy = vy * -1;
    }
  }
}

Paddle Class

class paddle {

  int psize;
  color pcol;
  float y;

  paddle () {
    psize = 150;
    pcol = color(random(128, 255));
    y = 600;
  }

  void update() {
    fill(pcol);
    rectMode(CENTER);
    rect(mouseX, y, psize, 10, 30);
  }
}

Brick Class

class brick {

  color bcol;
  float x;
  float y;
  float h; 
  float w;


  brick(float tempX, float tempY) {
    bcol = color(random(128, 255), random(128, 255), random(128, 255));
    x = tempX;
    y = tempY;
    w = 60;
    h = 37.5;
  }

  void show() {
    noStroke();
    fill(bcol);
    rect(x, y, w, h);
  }

  void hit() {
    if (brickBreaker.hit == true) {
      for (int i = 0; i < total; i++) {
        bcol = color(51);
        rect(x, y, w, h);
        brickBreaker.hit = false;
      }
    }
  }
}

You don‘t need to call to another class. Just add a broken boolean to the brick class. If that boolean is false, draw the brick, else don‘t.

To set that boolean to true, just use the hit method you already have.

And then just check if the brick is !broken when drawing the rect for it.

By “broken” boolean, do you mean a boolean set to false or a boolean with the name being “broken”? And if I understand correct, with this method, I have to draw each brick separately. That will be a lot of code…

Are there any tips you can give me that can help with taking out one brick at a time with an array?

if you not understand the idea to give each Brick a variable about
enable / disable draw …

you tell us HOW you want to remember if a Brick in the bricks array
is dead after collision with a ball?


please use for class big letters,
class Brick
class Ball

Ball ball;
Brick[] bricks;

and all other variables start small…

Yes, broken should be the variable name, signifying if the brick is still intact(false), or broken (true).

You have 2 options. Either draw each brick seperately in a for loop, or draw a rect that represents all bricks and overlay them with a new rect when they are broken.

I‘d highly suggest drawing each brick seperately, Else you just end up withdrawing each overlay seperately, but adding a Ton of Code that could‘ve been avoided.

Take a look here, to see how it could be done :

Example
Ball ball;
Brick[] bricks;

void setup() {
   size(screen.width, screen.height);
   
   ball = new Ball(150, 10, 10);
   
   bricks = new Brick[100];
   
   for (int x = 0; x < 10; x++) {
      for (int y = 0; y < 10; y++) {
         println("1");
         bricks[x+y*10] = new Brick(50+x*20, 50+y*10, 20, 10);
      }
   }
}

void draw() {
   background(0,0,255);
   
   for (int i = 0; i < bricks.length; i++) {
      bricks[i].display();
      bricks[i].hit(ball);
   }
   
   ball.display();
   ball.move();
   ball.checkCollission();
}
class Brick {
   PVector pos; //basically 2 floats (or 3 if you need another one)
   PVector siz;
   
   bool broken = false; // change bool to boolean (i use diff compiler, so for me it's bool)
   
   Brick(float x, float y, float w, float h) {
      pos = new PVector(x, y);
      siz = new PVector(w, h);
   }
   
   void display() {
      if (!broken) {
         rect(pos.x, pos.y, siz.x, siz.y);
      }
   }
   
   void hit(Ball b) {
      
      if (!broken && b.pos.x + b.radius/2 > pos.x && b.pos.x - b.radius/2 < pos.x + siz.x && b.pos.y + b.radius/2 > pos.y && b.pos.y - b.radius/2 < pos.y + siz.y) {
         //could add something like a counter for the bricks that need multiple hits
         broken = true;
         
//you'll have to adapt the reflection direction calculation...
         if (b.pos.x < pos.x || b.pos.x > pos.x + siz.x)
         b.reflect(-1,1);
         else if (b.pos.y < pos.y || b.pos.y > pos.y + siz.y) b.reflect(1,-1);
      }
   }
}
class Ball {
   PVector pos;
   PVector dir;
   float radius;
   
   Ball(float x, float y, float r) {
      pos = new PVector(x, y);
      dir = new PVector(random(-1,1), random(1));
      radius = r;
   }
   
   void display() {
      ellipse(pos.x, pos.y, radius, radius);
   }
   
   void move() {
      pos.add(dir);
   }
   
   void checkCollission() {
      if (pos.x - radius/2 < 0 || pos.x + radius/2 > 300)dir.x *= -1;
      if (pos.y - radius/2 < 0 || pos.y + radius/2 > 200)dir.y *= -1;
      
   }
   
   void reflect(float x, float y) {
      dir.x *= x;
      dir.y *= y;
   }
}

It‘s not the best brickbreaker, but it works (though the reflection isn‘t perfect…).