How to get balls to bounce off each other in p5.js?

I’m having trouble getting these balls to bounce off one another; they keep getting stuck in certain parts as well. If someone could please help me with the code, it would be much appreciated! I am relatively new to using p5, so the code might be off by a lot…

Here’s the code:


var x = [];
var y = [];
var xspd = [];
var yspd = [];
var xdir = [];
var ydir = [];
var radius = 20 ;

function  setup () {
  createCanvas(500, 300);

  for (var i = 0 ; i <  10 ; i++) {
    x[i] = random (width);
    y[i] = random (height);
    xspd[i] = random (1, 5);
    yspd[i] = random (1, 5);
    xdir[i] = 1 ;
    ydir[i] = 1 ;
  }
}

function  draw () {
  background (0);
  bounce();
  display();

}

function distance(x1, x2, y1, y2) {
  var dx = x1 - x2;
  var dy = y1 - y2;
  var d = sqrt (dx * dx + dy * dy);
  return d;
}

function bounce() {
  for (var i = 0 ; i <  10 ; i++) {
    x[i] = x[i] + xspd[i] * xdir[i];
    y[i] = y[i] + yspd[i] * ydir[i];

    if (x[i] < radius) {
      x[i] = radius;
      xdir[i] *= - 1 ;
    }  else if (x[i] >  width - radius) {
      x[i] = width - radius;
      xdir[i] *= - 1 ;
    }

    if (y[i] < radius) {
      y[i] = radius;
      ydir[i] *= - 1 ;
    }  else if (y[i] >  height - radius) {
      y[i] = height - radius;
      ydir[i] *= - 1 ;
    }

    for (var k = i +  1 ; k <  10 ; k++) {
      if (distance(x[i], y[i], x[k], y[k]) < radius + radius) {
        xdir[k] *= - 1 ;
        ydir[k] *= - 1 ;
      }
    }
  }
}

function display() {
  for (var i = 0 ; i <  10 ; i++) {
    noStroke ();
    fill (255, 204, 0 , 90);
    ellipse (x[i], y[i], radius *  2 , radius *  2);
  }
}
1 Like

I have commented on the lines I have changed.

The main problems were:

  • You were looping through all the circles after the one you were checking (so not including the ones before)
    for(var k = i +1; k <10; k++) { not for (var k = 0; k < 10; k++) {

  • You were checking the wrong distance
    radius+radius not radius

Problems this doesn’t fix:

  • The circles may be created too close together intially so they can never separate.

    • Reasign coordinates when creating them if they overlap until the circle no longer overlaps anything.
  • The circles may still be too close together even after moving in the opposite direction.

    • Move the circles so that they are only just touching on the edges before reversing their direction. (Similar to what you did with them bouncing off the walls.)
var x = [];

var y = [];

var xspd = [];

var yspd = [];

var xdir = [];

var ydir = [];

var radius = 20;

function setup() {

	createCanvas(500, 300);

	for (var i = 0; i < 10; i++) {

		x[i] = random(width);

		y[i] = random(height);

		xspd[i] = random(1, 5);

		yspd[i] = random(1, 5);

		xdir[i] = 1;

		ydir[i] = 1;

	}

}

function draw() {

	background(0);

	bounce();

	display();

}

function distance(x1, x2, y1, y2) {

	var dx = x1 - x2;

	var dy = y1 - y2;

	var d = sqrt(dx * dx + dy * dy);

	return d;

}

function bounce() {

	for (var i = 0; i < 10; i++) {

		x[i] = x[i] + xspd[i] * xdir[i];

		y[i] = y[i] + yspd[i] * ydir[i];

		if (x[i] < radius) {

			x[i] = radius;

			xdir[i] *= -1;

		} else if (x[i] > width - radius) {

			x[i] = width - radius;

			xdir[i] *= -1;

		}

		if (y[i] < radius) {

			y[i] = radius;

			ydir[i] *= -1;

		} else if (y[i] > height - radius) {

			y[i] = height - radius;

			ydir[i] *= -1;

		}

                //loop through all other circles to check
		for (var k = 0; k < 10; k++) {
                        //except the same circle
			if(k != i){

                                //use dist() function to check distance from the middle of circle (which is why the radius not diameter is used
				if (dist(x[i], y[i], x[k], y[k]) <  radius) { 


					xdir[k] *= -1;

					ydir[k] *= -1;

				}
			}

		}

	}

}

function display() {

	for (var i = 0; i < 10; i++) {

		noStroke();

		fill(255, 204, 0, 90);

		ellipse(x[i], y[i], radius * 2, radius * 2);

	}

}
2 Likes

Hi @BLy

First off, I notice that aside from the part dealing with two balls colliding with each other, your code runs fine. So, nice work on that.

Second, I’m quite sure you’re not the only one to have trouble handling the ball/ball collision reaction because it’s rather tricky! Unfortunately I couldn’t find a resource that’s specific to your problem, but take a look at this example from the p5.js website: https://p5js.org/examples/motion-bouncy-bubbles.html

I realize this example has some things you’re not trying to include, like gravity and friction for example. But, if you scroll down to the collide method, you’ll get an idea of what needs to be done. There is a fair amount of calculation there, including some trigonometry.

Sorry I don’t have more of a solution for you. But I like your project idea as a way to learn about these things, and I may try it on my own some time!

3 Likes