Collision detection & collision response

I just created ball with line , and I want to make this ball hit this line with collision and response
please any suggestion!

float x = 150;
float y = 100;
float xSpeed = 9;
float ySpeed = 7;

void setup() { size(500, 500);
stroke(255);}

void draw() {
background(0);
ellipse(x, y, 100, 100);
fill( 255,255,0);
strokeWeight(10);
line(10,200,150, 10);
x += xSpeed;
y += ySpeed;
if (x < 0 || x > width) {
xSpeed *= -1; }

if (y < 0 || y > height) {
ySpeed *= -1; }

}

here a nice way to detect the collision : Collision Detection
Still , it needs extra calculation to bounce in a realistic way…

If you’re really good at math, go take a look at this wikipedia article: Line–sphere intersection - Wikipedia. If there is an intersection, reflect the balls angle off the line’s normal vector.

If not, here’s a more detailed explanation:
First, add 4 variables called lstartx, lstarty, lendx, lendy, ballr (all four of them should be floats). These describe the starting and end point of the line and the radius of the ball. When drawing the line or the ball, use these variables as arguments for the line method or ellipse methods.
Next, add a collide method that checks for collision between the ball and the line.
Say your circle is at coordinates (cx, cy) and has a radius of r. And you have a line that goes from (x1, y1) to (x2, y2). I’m gonna skip over the details, but this is how you can get a collision detection system from this:

boolean collides(float cx, float cy, float r, float x1, float y1, float x2, float y2) {
  PVector c = new PVector(cx, cy);
  PVector o = new PVector(x1, y1);
  PVector u = new PVector(x2, y2).sub(o);
  float l = u.mag();
  u.normalize();
  
  PVector oc = new PVector().add(o).sub(c);
  float uoc = oc.dot(u);
  float dis = uoc*uoc - (oc.magSq() - r*r);
  if (dis > 0) {
    float d1 = -uoc - sqrt(dis);
    float d2 = -uoc + sqrt(dis);
    float mind = 0;
    if (d2 < 0) {
      return false;
    } else {
       if (d1 > 0) {
        mind = d1;
      } else {
        mind = d2;
      }
      return mind < l;
    }
  } else {
    return false;
  }
}

That’s it for the collision detection part. Now on to collision response.
First, we need to move the ball back so it is not inside the line anymore. This means subtracting the current velocity from the ball’s porision to undo the movement that just happened. In code, it looks like this

x -= xSpeed;
y -= ySpeed;

Next, add an if statement that checks if the collide method from above is true. If it is, all we need to do is to change the angle of the ball (while mag aka its speed can stay the same). In order to do that, we need another method for calculating the reflection angle. It takes as input the ball’s x and y speed as well as the starting and end points of the line. It looks like this:

PVector reflect(float xi, float yi, float x1, float y1, float x2, float y2) {
  PVector n = new PVector(x1, y1).sub(new PVector(x2, y2)).normalize();
  PVector d = new PVector(xi, yi);
  return new PVector().add(n).mult(d.dot(n)*2).sub(d).mult(-1);
}

One more thing before we get to the final code, your edge detection code is slightly flawed. The way you implemented it, the ball could easily get stuck in the wall. The solution is to move the ball back in bounds. Additionally, we need to inset the bounds by ballr units to account for the ball’s non-zero radius.
The corrected wall detection system looks like this:

if (x < ballr) {
  x = ballr;
  xSpeed *= -1;
}
if (x > width-ballr) {
  x = width-ballr;
  xSpeed *= -1;
}
if (y < ballr) {
  y = ballr;
  ySpeed *= -1;
}
if (y > height-ballr) {
  y = height-ballr;
  ySpeed *= -1;
}

Finally, add this method to your code. All in all, it should look sth like this:

float x = 150;
float y = 100;
float xSpeed = 9;
float ySpeed = 7;
float lstartx = 50;
float lstarty = 300;
float lendx = 300;
float lendy = 250;
float ballr = 40;

void setup() { 
  size(500, 500);
  stroke(255);
}

void draw() {
  background(0);
  ellipse(x, y, 2*ballr, 2*ballr);
  fill( 255, 255, 0);
  strokeWeight(10);
  line(lstartx, lstarty, lendx, lendy);
  x += xSpeed;
  y += ySpeed;
  if (collides(x, y, ballr, lstartx, lstarty, lendx, lendy)) {
    x -= xSpeed;
    y -= ySpeed;
    PVector p = reflect(xSpeed, ySpeed, lstartx, lstarty, lendx, lendy);
    xSpeed = p.x;
    ySpeed = p.y;
  }
  if (x < ballr) {
    x = ballr;
    xSpeed *= -1;
  }
  if (x > width-ballr) {
    x = width-ballr;
    xSpeed *= -1;
  }
  if (y < ballr) {
    y = ballr;
    ySpeed *= -1;
  }
  if (y > height-ballr) {
    y = height-ballr;
    ySpeed *= -1;
  }
}

//collides method from above

//reflect method from above

I hop this could help you
Simon

Thanks Simon for the clarifying
:wink: