Bouncing balls collision

edited November 2017 in Questions about Code

Hello, I've tried to code a classic bouncing balls animation but I can't get to make balls properly bounce. The problem is that sometimes the balls got stuck into each others or into the edges of the canvas, beside not changing color. I figured it might has something to do width the frame rate, which somehow make the balls enter one into another passing the edge without detection and without bouncing.. maybe Im wrong, but I can't find a solution Someone can help?

here the code

Ball[] balls = new Ball[10];

void setup() {
  size(800, 600);
  for (int i = 0; i < balls.length; i++) {
    balls[i] = new Ball(random(40,60), 120);
  }
}

void draw() {
  background(0);
  for (int i = 0; i < balls.length; i++) {
    balls[i].display();
    balls[i].move();
    balls[i].edges();
    for (int o = 0; o < balls.length; o++) {
      if(o!=i){
      balls[i].overlaps(balls[o]);
      balls[o].overlaps(balls[i]);
      }
    }
  }
}

class Ball {
  float dia;
  float x;
  float y; 
  float col;
  float xspeed;
  float yspeed;
  float acc = sin(TWO_PI/400);
  float r;

  Ball (float tempD, float tempC) {
    x = random(100,700);
    y = random(100,400);
    dia = tempD;
    col = tempC;
    r = dia/2;
    xspeed = 2.0;
    yspeed = 3.0;
  }

  void display() {
    noStroke();
    fill(col);
    ellipse(x, y, dia, dia);
  }

  void move() {
    //xspeed = xspeed+acc;
    //yspeed = yspeed+acc;
    x = x + xspeed;
    y = y + yspeed;
  }

  void edges() {
    if (x > width-r || x < r) {
      xspeed = xspeed * -1;
    }
    if (y > height-r || y < r) {
      yspeed = yspeed * -1;
    }
  }

  void overlaps(Ball o) {
    float d = dist(x,y,o.x,o.y);
    if (d < r + o.r) {
      xspeed = xspeed*-1;
      yspeed = yspeed*-1;
      col = 255;
      println(d);
    } else{
      col=120;
    }
  }
}
Tagged:

Answers

  • there are various examples

    https://www.processing.org/examples/circlecollision.html

     void edges() {
        if (x > width-r || x < r) {
          xspeed = xspeed * -1;
        }
        if (y > height-r || y < r) {
          yspeed = yspeed * -1;
        }
      }
    

    when the ball is still in the recursion zone if (x > width-r still applies, it could be that ball stays there, like it stutters there because xspeed always gets turned between -1 and +1

    instead treat them separately and use abs():

     void edges() {
        if (x > width-r ) {
          xspeed = abs(xspeed) * -1; // always neg 
        }
        if( x < r) {
                 xspeed = abs(xspeed) ; // awlways pos 
        }
        .............same for y....
      }
    
  • hey Chrisir, thank you very much for your suggestion, it now perfectly works for the edges! I still can't figure how to solve the ball to ball collision. I can't say on what side the collision will be. I'm still working on it

  • Have you looked at the example??

  • Yes I did, it is way more advanced comparing to my attempt. As a first step I wanted to try to make mine work, just for a didactic purpose. For my knowledge level the other one needs a bit of time to fully understand.. thank you for your help

  • Balls getting stuck is a classic problem in bouncing balls.

    If your ball passes into an object far enough that returning does not get it out, then it vibrates there forever -- each frame flipping direction.

    if (x > width-r || x < r) {
      xspeed = xspeed * -1;
    }
    

    Resetting it to the edge of the collision object as well as switching the speed prevents it from being stuck inside.

    I believe there is a discussion of that issue in this tutorial video:

  • jeremydouglass thank you for your advice! In the video I can find a solution for the edges collision, which in my sketch now works. I have problems with balls getting stuck one into each other. I can't just invert the velocity as it is not predictable on which side the collision will be.

  • edited November 2017

    as it is not predictable on which side the collision will be.

    On which side?

    like this:

    if(x<o.x) 
           xspeed=-abs(xspeed);
    

    etc.

  • kfrajer, wow that sketch is a perfect bouncing balls solution. It is very different from mine and actually it's a bit beyond my level. I was trying to find a solution for the sketch I wrote. I feel like I would need a few strings of code.

    The problem is that when one ball collide into another stay there forever cause keeps inverting direction. on the edge is easier because you just permanently invert the direction: if x is greater than width-r than direction is -10. on the other hand I can't predict which side balls are colliding into each other, so I can just say: if you go in one direction and collide, than invert direction. This cause them to continuously change the direction. Anyway it's hard to explain by writing. Hope this was comprehensible..

  • edited November 2017 Answer ✓

    See my post.

    Use if to see which side, then use either abs(... or -abs(.....

  • yesss!!! great now it's working! took a while for me to understand though thank you very much Chrisir! This made my day :-)

    here's the code

    Ball[] balls = new Ball[10];
    
    void setup() {
      size(800, 600);
      for (int i = 0; i < balls.length; i++) {
        balls[i] = new Ball(random(40, 60), 120);
      }
    }
    
    void draw() {
      background(0);
      for (int i = 0; i < balls.length; i++) {
        balls[i].display();
        balls[i].move();
        balls[i].edges();
        for (int o = 0; o < balls.length; o++) {
          if (o!=i) {
            balls[i].overlaps(balls[o]);
            balls[o].overlaps(balls[i]);
          }
        }
      }
    }
    
    class Ball {
      float dia;
      float x;
      float y; 
      float col;
      float xspeed;
      float yspeed;
      float r;
    
      Ball (float tempD, float tempC) {
        x = random(100, 700);
        y = random(100, 400);
        dia = tempD;
        col = tempC;
        r = dia/2;
        xspeed = 5.0;
        yspeed = 3.0;
      }
    
      void display() {
        noStroke();
        fill(col);
        ellipse(x, y, dia, dia);
      }
    
      void move() {
        //xspeed = xspeed+acc;
        //yspeed = yspeed+acc;
        x = x + xspeed;
        y = y + yspeed;
      }
    
      void edges() {
        if (x > width-r ) {
          xspeed = abs(xspeed) * -1; // always neg
        }
        if ( x < r) {
          xspeed = abs(xspeed); // awlways pos
        }
        if (y > height-r ) {
          yspeed = abs(yspeed) * -1; // always neg
        }
        if ( y < r) {
          yspeed = abs(yspeed); // awlways pos
        }
      }
      void overlaps(Ball o) {
        float d = dist(x, y, o.x, o.y);
        if (d <= r + o.r) {
          if(x<o.x) {
          xspeed= -abs(xspeed);
          }
          if(x>o.x) {
          xspeed= abs(xspeed);
          }
          if(y<o.y) {
          yspeed= -abs(yspeed); 
          }
          if(y>o.y) {
          yspeed= abs(yspeed);
          }      
        }
      }
    }
    
  • Well done!

Sign In or Register to comment.