BREAKOUT Project - Help with collision detection

To remove it loop through each one and check if it is touching the ball, if it is, then you should remove it.

You can loop through the same way as above

for ( PVector p : bricks )

1 Like

If you need a tutorial on Array List’s you can check out this one:

That should be good.

And, remember, never be afraid to learn new things, it sure can be daunting at the beginning, but in the end it is well worth it.

5 Likes

yes, there are 2 ways to loop over arrayList

  for ( int i = 0 ; i < bricks.size(); i++ ) { 
    PVector p = bricks.get(i);
    rect(p.x, p.y, bw, bh);
collision
if ( p.x < xBalle && (p.x + bw) > xBalle &&   //__Ma balle rebondit sur les briques  
  p.y < yBalle && p.y +bh > yBalle && ySpeed < 0 ) { //_____ also check on UPSPEED ??
  ySpeed = - ySpeed; // Si la balle rebondit sur les briques, inverse la vitesse
  bricks.remove(i);
    }
  }
2 Likes

@BeastCoder
good video // but not too beginner friendly
also i miss the real advantages like .remove or see here?
https://processing.org/reference/StringList.html

1 Like

Ack, you are right!

I’ll try and find a more beginner friendly one, I tried to use a Coding Train one but he was doing something a little bit more complicated using classes.

1 Like

Putting everything together. Thank you very much for the help!

1 Like

Studio.ProcessingTogether.com/sp/pad/export/ro.PKnDDqu1vYo

2 Likes

Hello everyone, it’s me, again!

Since my last posts yesterday, I learned that I couldn’t use Class, Object and ArrayList so I had to redo everything.

I used an array for my “for loop” that draws my bricks. For the collision, I did the same way I did for the paddle as @BeastCoder suggested. It is functioning but I have got some problems with the collision detection.

Sometimes, the ball will hit a brick and it is the one next to it that will disappear and not the one that got hit.

Sometimes, the ball will hit a brick’ side and it won’t disappear at all.

Here is my code :

//Briques
int[] blocks = new int[50];
int bh = 30; //Hauteur 
int bw = 100; //Largeur

//Variables de ma balle
float xBalle = 650; //Position x
float yBalle = 400; //Position y
float xSpeed = 3; //Vitesse
float ySpeed = 3; //Vitesse

//Variables du paddle
int xPaddle = 600; //Position x
int yPaddle = 650; //Position y 
int Paddle = 100; 


void setup(){
  int i;
  size(1200, 800); //Taille de la fenêtre - les dimensions de la fenêtre ont été changées pour mieux s'adapter à celles de mon écran
  
  //Array pour les briques 
  for (i=0; i<50; i++) {
    blocks[i] = 1;
  }
}

void draw(){
  int i; //Boucle
  int bx; //Briques x
  int by; //Briques y
  background (0);

//Je fais bouger ma balle
  xBalle = xBalle + xSpeed; //Ajout de vitesse à ma xBalle
  if (xBalle > width || xBalle < 0){ //Ma balle ne sort pas de l'écran par les côtés
  xSpeed = xSpeed * -1; //Inverse vitesse
  }  
  yBalle = yBalle + ySpeed; //Ajout de vitesse à ma yBalle
  if (yBalle > height || yBalle < 0){ //Ma balle ne sort pas de l'écran par le haut et le bas
  ySpeed = ySpeed * -1; //Inverse vitesse
  }
  
  //Je dessine ma balle
  fill(255); 
  stroke(255); 
  ellipse (xBalle,yBalle,20,20); //Si diamètre 40, rayon 20
  
  //Je fais bouger mon paddle - keyPressed
  if (keyPressed){
    if(keyCode == RIGHT){ //bouton DROIT
    //Déplacement du paddle à droite
    xPaddle = xPaddle + 10; 
    } else if (keyCode == LEFT){ //bouton GAUCHE
    //Déplacement du paddle à gauche
    xPaddle = xPaddle - 10; 
    }
  }
  
  //Le paddle ne sort pas de l'écran par les côtés 
   if (xPaddle > width) 
   xPaddle = width;
   if (xPaddle < 0) 
   xPaddle = 0;
  
  //Je dessine mon paddle 
  fill(255); 
  stroke(255); 
  rectMode(CENTER);
  rect(xPaddle,yPaddle,200,10); 
  
  //Ma balle rebondit sur le paddle   
    if ((xPaddle - Paddle) < xBalle && (xPaddle + Paddle) > xBalle && 
    (yPaddle - 10) < yBalle && (yPaddle) > yBalle) {
    // Si la balle rebondit sur le paddle, inverse la vitesse 
    ySpeed = - ySpeed;
  }
  
  //Je dessine mes briques - boucle for 
  for (i=0; i<50; i++) {
    bx = i%10*110+10; 
    by = 40*(i/10)+10; 
    // Les briques apparaissent et sont dessinées si blocks[i]==1, elles disparaissent si blocks[i]==0
    if (blocks[i]==1) { 
      // Draw the block
      fill(255);
      stroke(0);
      rect(bx+100, by+10, bw, bh);
    }
    //Détection collision entre ma balle et les briques
    //Haut-bas des briques
    if(xBalle > (bx+10) && xBalle < (bx+90) &&
    yBalle > by && yBalle<(by+30) && blocks[i]==1){ //OK
      blocks[i]=0; //Disparition
      ySpeed = - ySpeed;
  }
    //Détection collision entre ma balle et côté 
   if (((xBalle > (bx-5) && xBalle < bx) || (xBalle > (bx+100) && xBalle < (bx+105))) &&
      yBalle > by && yBalle < (by+30) && blocks[i]==1) { //OK
      blocks[i]=0; //Disparition
      xSpeed = - xSpeed;
      }
      
    //Détection suite
    if (((xBalle > (bx-5) && xBalle < (bx+10)) || (xBalle > (bx+100) && xBalle < (bx+90))) &&
      yBalle > by && yBalle <(by+30) && blocks[i]==1) { //OK
      blocks[i]=0; //Disparition
      xSpeed = - xSpeed; 
      ySpeed = - ySpeed;
  }
  }
}

I think that the disfunctioning comes from here :

//Détection collision entre ma balle et les briques
    //Haut-bas des briques
    if(xBalle > (bx+10) && xBalle < (bx+90) &&
    yBalle > by && yBalle<(by+30) && blocks[i]==1){ //OK
      blocks[i]=0; //Disparition
      ySpeed = - ySpeed;
  }
    //Détection collision entre ma balle et côté 
   if (((xBalle > (bx-5) && xBalle < bx) || (xBalle > (bx+100) && xBalle < (bx+105))) &&
      yBalle > by && yBalle < (by+30) && blocks[i]==1) { //OK
      blocks[i]=0; //Disparition
      xSpeed = - xSpeed;
      }
      
    //Détection suite
    if (((xBalle > (bx-5) && xBalle < (bx+10)) || (xBalle > (bx+100) && xBalle < (bx+90))) &&
      yBalle > by && yBalle <(by+30) && blocks[i]==1) { //OK
      blocks[i]=0; //Disparition
      xSpeed = - xSpeed; 
      ySpeed = - ySpeed;
  }
  }

But I am not sure about it. What do you guys think?

Thanks again!

1 Like

please try to redo
paddle and brick collision without

rectMode(CENTER);

and remember then the paddle is touched by ball at px … px + pw // py - ball_r
and the bricks at bx … bx + bw // by+bh + ball_r

Alright as you said, I redid it without rectMode(CENTER);

I redid the bricks, they seem to be ok for now but I now have a problem between the paddle and the ball, the collision only happens on the edges of the paddle.

As you said, I should adapt this

if ((xPaddle - Paddle) < xBalle && (xPaddle + Paddle) > xBalle && 
    (yPaddle - 10) < yBalle && (yPaddle) > yBalle) {
    // Si la balle rebondit sur le paddle, inverse la vitesse 
    ySpeed = - ySpeed;
  }

not forgetting

and remember then the paddle is touched by ball at px … px + pw // py - ball_r

But it is not making any difference when I try to adapt the paddle. Am I doing it wrong? How should it be then?

Thank you!

sorry, as a next step i would use array for the brick positions too

int[] blocks  = new int[50];
int[] blocksx = new int[50];
int[] blocksy = new int[50];
int bh = 30; //Hauteur 
int bw = 100; //Largeur
int boff = 10;

void setup() {
  size(1200, 800);
  for (int i=0; i<50; i++) {
    blocks[i] = 1;
    blocksx[i] =  i%10*(bw + boff) + 50; 
    blocksy[i] =  floor(i/10) * ( bh + boff) + 20;
  }
}

void draw() {
  for (int i=0; i < 50; i++) {
    if (blocks[i]==1) { 
      fill(255);
      stroke(0);
      rect(blocksx[i], blocksy[i], bw, bh);
    }
  }
}

you see how easy it makes the drawing,
sure it will help with the collision

for the paddle,
you have

int Paddle = 100; 
// but
 rect(xPaddle,yPaddle,200,10); 
//
    if ((xPaddle - Paddle) < xBalle && (xPaddle + Paddle) > xBalle && 
    (yPaddle - 10) < yBalle && (yPaddle) > yBalle) {

//

you are confusing yourself with this settings
possibly also comes from some rectMode(CENTER) thinking??

1 Like

This is actually very confusing.

int Paddle = 100; 
// but
 rect(xPaddle,yPaddle,200,10); 
//
    if ((xPaddle - Paddle) < xBalle && (xPaddle + Paddle) > xBalle && 
    (yPaddle - 10) < yBalle && (yPaddle) > yBalle) {

//

I redid my code without the rectMode(CENTER) as you suggested. However, I used the rectMode(CENTER) in the first place in order to draw my paddle and my paddle isn’t working anymore.

I don’t know what to change in this code to make it work again :

int Paddle = 100; 
// but
 rect(xPaddle,yPaddle,200,10); 
//
    if ((xPaddle - Paddle) < xBalle && (xPaddle + Paddle) > xBalle && 
    (yPaddle - 10) < yBalle && (yPaddle) > yBalle) {

//```

sorry for all this rewriting, but that is how i can read it??

float Ballex = 650; //Position x
float Balley = 400; //Position y
int   Baller = 10;

int Paddlex = 600; //Position x
int Paddley = 650; //Position y 
int Paddlew = 200; 
int Paddleh = 10; 

rect(Paddlex, Paddley, Paddlew, Paddleh); 
circle(Ballex,Balley,2*Baller);

if (Paddlex  < Ballex && (Paddlex + Paddlew) > Ballex && 
  (Paddley - Baller) < Balley && Paddley > Balley) {}
//
  for (int i=0; i < 50; i++) {
    if (blocksx[i]  < Ballex && (blocksx[i] + bw) > Ballex && 
    (blocksy[i] + Baller) < Balley && blocksy[i] > Balley) {}
 }

now rectangle thinks start left top
and circle in center

1 Like

Ok you were right. The way I did it was very confusing but what you just wrote about the paddle works perfectly. Thank you!

I know that you earlier suggested a different use of array for the brick positions but I would like to keep it the way I did so that I can really perfect this method and really understand what I am doing and what I started.

I still have a little problem with collision detection. Sometimes, the ball will hit a brick’ side and it won’t disappear at all which I find quite annoying.

I think that there is a problem with the distance covered but I am not quite sure. Is there anything that seems a little bit weird here?

//Je dessine mes briques - boucle for 
  for (i=0; i<50; i++) {
    bx = i%10*110+10; 
    by = 40*(i/10)+10; 
    // Les briques apparaissent et sont dessinées si blocks[i]==1, elles disparaissent si blocks[i]==0
    if (blocks[i]==1) { 
      // Draw the block
      fill(255);
      stroke(0);
      rect(bx+40, by+10, bw, bh);
    }
    //Détection collision entre ma balle et les briques
    //Haut-bas des briques
    if(xBalle > (bx+4) && xBalle < (bx+96) &&
    yBalle > by && yBalle<(by+30) && blocks[i]==1){ //OK
      blocks[i]=0; //Disparition
      ySpeed = - ySpeed;
  }
    //Détection collision entre ma balle et côté 
   if (((xBalle > (bx-5) && xBalle < bx) || (xBalle > (bx+100) && xBalle < (bx+105))) &&
      yBalle > by && yBalle < (by+30) && blocks[i]==1) { //OK
      blocks[i]=0; //Disparition
      xSpeed = - xSpeed;
      }
      
    //Détection suite
    if (((xBalle > (bx-1) && xBalle < (bx+5)) || (xBalle > (bx+95) && xBalle < (bx+101))) &&
      yBalle > by && yBalle <(by+30) && blocks[i]==1) { //OK
      blocks[i]=0; //Disparition
      xSpeed = - xSpeed; 
      ySpeed = - ySpeed;
  }
  }

sorry, can 't read it,
what you try do here?
collision ball <–> brick from all brick sides?

but i have a idea for a easier testing:

Ballex = mouseX;
Balley = mouseY;
circle(Ballex,Balley,2*Baller);

1 Like

I used a loop to draw 50 blocks (5 rows, 10 columns). Then I said ok, if blocks[i]==1, the block will appear. If blocks[i]==0, the block will disappear.

//Je dessine mes briques - boucle for 
  for (i=0; i<50; i++) {
    bx = i%10*110+10; 
    by = 40*(i/10)+10; 
    // Les briques apparaissent et sont dessinées si blocks[i]==1, elles disparaissent si blocks[i]==0
    if (blocks[i]==1) { 
      // Draw the block
      fill(255);
      stroke(0);
      rect(bx+40, by+10, bw, bh);
    }

If the ball come close to the top, bottom or sides and hit the block, then I reverse the speed and the block also disappear.

//Détection collision entre ma balle et les briques
    //Detect collision top-bottom blocks
    if(xBalle > (bx+4) && xBalle < (bx+96) &&
    yBalle > by && yBalle<(by+30) && blocks[i]==1){ //OK
      blocks[i]=0; //Disparition
      ySpeed = - ySpeed;
  }
    //Detect collision sides
   if (((xBalle > (bx-5) && xBalle < bx) || (xBalle > (bx+100) && xBalle < (bx+105))) &&
      yBalle > by && yBalle < (by+30) && blocks[i]==1) { //OK
      blocks[i]=0; //Disparition
      xSpeed = - xSpeed;
      }
      
    if (((xBalle > (bx-1) && xBalle < (bx+5)) || (xBalle > (bx+95) && xBalle < (bx+101))) &&
      yBalle > by && yBalle <(by+30) && blocks[i]==1) { //OK
      blocks[i]=0; //Disparition
      xSpeed = - xSpeed; 
      ySpeed = - ySpeed;
  }
  }

sorry / other timezone /

-a- your ( xy ± npx ) is a result of not having clean position for each rectangle.
so i want you again to check my above ( ready code ) for the “make” bricks

-b- for ball / rect collision are many ways,
basic should be a OVER RECT
a concept you need again and again with processing
like mouse over rect ( button )…
we make a boolean function:

boolean overRect(float mx, float my, int x, int y, int w, int h) {
  return ( mx > x && mx < x + w &&  my > y && my < y + h ) ;
}

this returns true if the POINT at ( mx,my )
is over a rect(x,y,w,h)

ha, but a ball is not a point, it has a radius, what we do?
the ball hits the rect actually “earlier” by br
so we just think that the rect is BIGGER by br ON ALL SIDES
with this a hit condition would be

circle(bx,by,2*br);
rect(rx,ry,rw,rh);
//  println( overRect(bx,by,rx,ry,rw,rh) );  // point thinking
println( overRect(bx,by,rx-br,ry-br,rw+2*br,rh+2*br) ); // ball radius >> bigger rect / thinking

all this works only if you NOT use rectMode(CENTER);

complete test code
int rx=20, ry=30, rw=60, rh=40;
int bx, by, br=10;

void setup() {
  noFill();
}

void draw() {
  background(200, 200, 0);
  bx = mouseX;
  by=mouseY;
  circle(bx, by, 2*br);
  rect(rx, ry, rw, rh);
  //  println( overRect(bx,by,rx,ry,rw,rh) );  // point thinking
  println( overRect(bx, by, rx-br, ry-br, rw+2*br, rh+2*br) ); // ball radius >> bigger rect / thinking
}

boolean overRect(float mx, float my, int x, int y, int w, int h) {
  return ( mx > x && mx < x + w &&  my > y && my < y + h ) ;
}

-c-
but you want also a change of speed of the ball, depending on what side of the rect it hits?
a easy first way can be ( later make it shorter and also check on the rect edges hit… )


  for (int i=0; i < 50; i++) {
    if (blocks[i]==1) { 
      rect(rx[i], ry[i], rw, rh);
      if (  overRect(bx,by,rx[i]-br,ry[i]-br,rw+2*br,rh+2*br) ) {
        println("over block: "+i);
        blocks[i]=0; //_disable
        if ( by > ry[i] + rh )  ySpeed *= -1;  //     println("// ball come from bottom");
        if ( by < ry[i]      )  ySpeed *= -1;  //     println("// ball come from top");
        if ( bx < rx[i]      )  xSpeed *= -1;  //     println("// ball come from left");
        if ( bx > rx[i] + rw )  xSpeed *= -1;  //     println("// ball come from right");
      }
  }
}

Working great, thank you very much!

1 Like