Catching Balls Game Collision Problem

Hello,

I’m trying to make a game with a stick figure with a basket that you can move with the right and left arrow key to catch balls falling from the top. So far I have the figure that moves and one ball falling and I want the ball to disappear when it hits the basket first before I add code to add new balls, but I can’t get it to work. I treated the basket as a straight line so I used http://www.jeffreythompson.org/collision-detection/line-circle.php as reference because I really have no clue how to do it, but the ball just falls on the ground. I think there’s a boolean error but I’ve been working on this part for a day now and can’t get it right. I have 2 classes in different tabs and one main:

Figure f;
Ball ball;
int gamescreen = 0;

void setup() {
  size(800, 800);
  f = new Figure(width/2, 26, 70, height-143);
  ball = new Ball(random(0+15, width-15), 0-15, 30);
}


void draw() {
  if (gamescreen == 0) {
   startScreen(); 
  }
  else if (gamescreen == 1) {
    gamescreen();
    f.update();
    ball.ballObject();
    
  }
  else if (gamescreen == 2) {
    gameOverScreen();
  }
  
}


void keyPressed() {
  if (key == CODED) {
    if (keyCode == RIGHT)
    {
      f.right = true;
    }
    else if (keyCode == LEFT)
    { 
      f.left = true;
    }
  }
}

void keyReleased() {
  if (key == CODED) {
    if (keyCode == RIGHT)
    {
      f.right = false;
    }
    if (keyCode == LEFT)
    { 
      f.left = false;
    }
  }
}


void startScreen() {
  background(0);
  textSize(40);
  fill(255);
  textAlign(CENTER, CENTER);
  text("CLICK TO START GAME", width/2, height/2);
}

void gamescreen() {
  background(0);
}


void gameOverScreen() {
  background(0);
  textSize(40);
  fill(255);
  textAlign(CENTER, CENTER);
  text("GAME OVER", width/2, height/2);
}

void mousePressed() {
  if (gamescreen == 0) {
    startGame();
  }
}


void startGame() {
  gamescreen = 1;
  }
  
  // LINE/CIRCLE
boolean arcBall(float x, float yArc, float x2, float a, float b, float ballRadius) {

  // is either end INSIDE the circle?
  // if so, return true immediately
  boolean inside1 = pointCircle(f.x, f.yArc, a, b, ballRadius);
  boolean inside2 = pointCircle(f.x2, f.yArc, a, b , ballRadius);
  if (inside1 || inside2) return false;
  

  // get length of the line
  float distX = f.x - f.x2;
  float distY = f.yArc - f.yArc;
  float len = sqrt( (distX*distX) + (distY*distY) );

  // get dot product of the line and circle
  float dot = ( ((a-f.x)*(f.x2-f.x)) + ((b-f.yArc)*(f.yArc-f.yArc)) ) / pow(len,2);

  // find the closest point on the line
  float closestX = f.x + (dot * (f.x2-f.x));
  float closestY = f.yArc + (dot * (f.yArc-f.yArc));

  // is this point actually on the line segment?
  // if so keep going, but if not, return false
  boolean onSegment = linePoint(f.x, f.yArc, f.x2, closestX,closestY);
  if (!onSegment) return true;

  // get distance to closest point
  distX = closestX - a;
  distY = closestY - b;
  float distance = sqrt( (distX*distX) + (distY*distY) );

  if (distance <= ballRadius) {
    return false;
  }
  return true;
}


// POINT/CIRCLE
boolean pointCircle(float px, float py, float a, float b, float ballRadius) {

  // get distance between the point and circle's center
  // using the Pythagorean Theorem
  float distX = px - a;
  float distY = py - b;
  float distance = sqrt( (distX*distX) + (distY*distY) );

  // if the distance is less than the circle's
  // radius the point is inside!
  if (distance <= ballRadius) {
    return false;
  }
  return true;
}


// LINE/POINT
boolean linePoint(float x, float yArc, float x2, float px, float py) {

  // get distance from the point to the two ends of the line
  float d1 = dist(px,py, f.x, f.yArc);
  float d2 = dist(px,py, f.x2, f.yArc);

  // get the length of the line
  float lineLen = dist(f.x, f.yArc, f.x2, f.yArc);

  // since floats are so minutely accurate, add
  // a little buffer zone that will give collision
  float buffer = 0.1;    // higher # = less accurate

  // if the two distances are equal to the line's
  // length, the point is on the line!
  // note we use the buffer here to give a range,
  // rather than one #
  if (d1+d2 >= lineLen-buffer && d1+d2 <= lineLen+buffer) {
    return false;
  }
  return true;
}





class Ball {
  float a;
  float b;
  float ballSize;
  float ballRadius = ballSize/2;
  boolean falling = true;
  boolean collision = false;
  
  Ball(float tA, float tB, float tBallSize) {
    a = tA;
    b = tB;
    ballSize = tBallSize;
    ballRadius = tBallSize/2;
  }
  
  void ballObject() { 
    boolean collision = arcBall(f.x, f.yArc, f.x2, a, b, ballRadius);
    if (!collision) fill(255);
    noStroke();
    ellipse(a, b, ballRadius*2, ballRadius*2);
    if (falling) {
      b += 3;
    }
  }
}

class Figure {
 float x;
 boolean left, right;
 float headSize;
 float arcSize;
 float yArc;
 float x2 = x + arcSize;
 
 Figure(float tX, float tHeadSize, float tArcSize, float tYarc)
 {
   x = tX;
   headSize = tHeadSize;
   arcSize = tArcSize;
   yArc = tYarc;
 }

void update() {
  this.human();
  this.basket();
  this.moving();

}

void human() {
  fill(255);
  noStroke();
  ellipse(x, height-100, headSize, headSize); 
  strokeWeight(4);
  stroke(255);
  line(x, height-85, x, height-40); //Körper
  line(x, height-40, x-10, height-10); //Bein1
  line(x, height-40, x+10, height-10); //Bein2
  line(x, height-70, x-25, height-120); //Arm1
  line(x, height-70, x+25, height-120); //Arm2

}

void basket() {
  fill(255);
  arc(x, yArc, arcSize, 50, 0, PI);
}


void moving() {
 if (left) {
  x -= 4; 
 }
 if (right) {
   x += 4;
 }
}

}

Thanks!!

I didn’t check your previous collision code, to be honest, but I just went on and treated the basket as a rectangle and a ball as a point, and made a function that works just fine.

boolean collisionCheck(Ball ball){
  if(
    abs(x-ball.a) < arcSize/2 &&  //true if X position of the ball is not far enough from the basket's center
    ball.b > yArc &&  //true if ball is not above the basket
    ball.b < yArc+50 //true if ball is not below the basket
    ) return true;
  
  return false;
}

Put it inside of Figure class’s code, and then call inside draw() using something like:

if( f.collisionCheck(ball) ) gamescreen = 2;