How can i get the ball to bounce properly

Hello! Im trying to get the ball to bounce off the center circle and the edges of the canvas. I've been successful with the edges but i'm having some issues with the circle in the center. Cant figure out how to get the ball to bounce off naturally then right back to where it was. I see that examples that are somewhat similar to this use vectors. I do not want to use vectors because i am very new to programming and haven't been taught how to use them. I would like to figure this out using trig but don't know how to approach it

GIF: https://gyazo.com/ffe4cffa5decbbb162c5ef06dfa5c1bb

code: https://pastebin.com/DFHYA1wM

Answers

  • please don't post duplicates

  • Answer ✓
       if (dist(ballX,ballY,centerX,centerY) < (DIAM/2) + (BALL_DIAMETER/2)) {
           ballSpeedX = -ballSpeedX;
           ballSpeedY = -ballSpeedY;
       }
    

    so you're just reversing BOTH directions if the small ball hits the circle. this isn't what you want.

    you need to treat it as if it's hit a wall at a tangent to the circle at the point of contact. here's a tutorial:

    http://ericleong.me/research/circle-circle/#static-circle-collision

  • I couldn't do it

    I also think there are minor errors on the tutorial page of eric

    final int DIAM = 200;
    final int BALL_DIAMETER = 15;
    
    float centerX, centerY;
    
    float ballX, ballY;
    float ballSpeedX = 3, ballSpeedY = 2;
    
    // -------------------------------------------------------------------
    
    void setup() {
      size( 500, 500 );
      ballX = 120.0;
      ballY = 40.0;
    
      centerX = width/2;
      centerY = height/2;
    }
    
    void draw() {
    
      background( 128 );
    
      fill(#ff5954);
      ellipse(centerX, centerY, DIAM, DIAM);
    
      fill(255);
      ellipse( ballX, ballY, BALL_DIAMETER, BALL_DIAMETER );
    
      moveBall();
    }
    
    // -------------------------------------------------------------------
    
    void moveBall() {
      changeSpeedOnWall();
      changeSpeedOnCenterCircle(); 
    
      ballX = ballX + ballSpeedX;
      ballY = ballY + ballSpeedY;
    }
    
    
    void changeSpeedOnWall() {
      if ( ballX < BALL_DIAMETER/2 ) {
        ballSpeedX = abs(ballSpeedX);//always pos
      }
    
      if ( ballX > width-BALL_DIAMETER/2 ) {
        ballSpeedX = -abs(ballSpeedX);//always neg
      }
    
      // -----
    
      if ( ballY < BALL_DIAMETER/2 ) {
        ballSpeedY = abs(ballSpeedY);//always pos
      }
    
      if (ballY > height-BALL_DIAMETER/2 ) {
        ballSpeedY = -abs(ballSpeedY);//always neg
      }
    }//func
    
    void changeSpeedOnCenterCircle() {
    
      PVector circle1= new PVector(ballX, ballY);
      PVector circle2= new PVector(centerX, centerY);
    
      PVector d = closestpointonline(circle1.x, circle1.y, 
        circle1.x + ballSpeedX, circle1.y + ballSpeedY, circle2.x, circle2.y); 
    
      double closestdistsq = Math.pow( circle2.x - d.x, 2) + Math.pow(circle2.y - d.y, 2 ) ; 
      if (closestdistsq <= Math.pow(BALL_DIAMETER/2 + DIAM/2, 2)) { 
        // a collision has occurred
    
        double backdist = Math.sqrt(Math.pow(BALL_DIAMETER/2 + DIAM/2, 2) - closestdistsq); 
        double movementvectorlength = Math.sqrt(Math.pow(ballSpeedX, 2) + Math.pow(ballSpeedX, 2)); 
        double c_x = d.x - backdist * (ballSpeedX / movementvectorlength); 
        double c_y = d.y - backdist * (ballSpeedY / movementvectorlength);
    
        double collisiondist = Math.sqrt(Math.pow(circle2.x - c_x, 2) + Math.pow(circle2.y - c_y, 2)); 
        double n_x = (circle2.x - c_x) / collisiondist; 
        double n_y = (circle2.y - c_y) / collisiondist;
    
        double circle1mass=12; 
        double circle2mass=1000;
    
        double p = 2 * (ballSpeedX * n_x + ballSpeedY * n_y) / 
          (circle1mass + circle2mass);
    
        double w_x = ballSpeedX - p * circle1mass * n_x - p * circle2mass * n_x; 
        double w_y = ballSpeedY - p * circle1mass * n_y - p * circle2mass * n_y;
    
        ballSpeedX=(float)w_x;
        ballSpeedY=(float)w_y;
      } else { 
        // no collision has occurred
      }//else 
      //
    }
    
    PVector closestpointonline(float lx1, float ly1, 
      float lx2, float ly2, 
      float x0, float y0) { 
      float A1 = ly2 - ly1; 
      float B1 = lx1 - lx2; 
      double C1 = (ly2 - ly1)*lx1 + (lx1 - lx2)*ly1; 
      double C2 = -B1*x0 + A1*y0; 
      double det = A1*A1 - -B1*B1; 
      double cx = 0; 
      double cy = 0; 
      if (det != 0) { 
        cx = (float)((A1*C1 - B1*C2)/det); 
        cy = (float)((A1*C2 - -B1*C1)/det);
      } else { 
        cx = x0; 
        cy = y0;
      } 
      return new PVector((float)(cx), (float)(cy));
    }
    
  • Watch your integer division with BALL DIAMETER / 2

  • thanks!

    i think it occurs in 10 places

Sign In or Register to comment.