Example
// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com

// Example 10-3: Bouncing ball with intersection

// Two ball variables
Ball ball1;
Ball ball2;

void setup() {
  size(400,400);
  smooth();
  
  // Initialize balls
  ball1 = new Ball(64);
  ball2 = new Ball(32);
}

void draw() {
  background(255);
  // Move and display balls
  ball1.move();
  ball2.move();
  
  if (ball1.intersect(ball2)) { // New! An object can have a function that takes another object as an argument. This is one way to have objects communicate. In this case they are checking to see if they intersect.
    ball1.highlight();
    ball2.highlight();
  }
  
  ball1.display();
  ball2.display();
}

// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com

// Example 10-3: Bouncing ball with intersection

class Ball {
  
  float r; // radius
  float x,y;
  float xspeed,yspeed;
  color c = color(100,50);
  
  // Constructor
  Ball(float tempR) {
    r = tempR;
    x = random(width);
    y = random(height);
    xspeed = random( -5,5);
    yspeed = random( -5,5);
  }
  
  void move() {
    x += xspeed; // Increment x
    y += yspeed; // Increment y
    
    // Check horizontal edges
    if (x > width || x < 0) {
      xspeed *= - 1;
    }
    
    // Check vertical edges
    if (y > height || y < 0) {
      yspeed *= - 1;
    }
  }
  
  // Whenever the balls are touching, this highlight() function is called 
  // and the color is darkened.
  void highlight() { 
    c = color(0,150);
  }
  
  // Draw the ball
  void display() {
    stroke(0);
    fill(c);
    ellipse(x,y,r*2,r*2);
     // After the ball is displayed, the color is reset back to a darker gray.
    c = color(100,50);
  }
  
  // A function that returns true or false based on whether two circles intersect
  // If distance is less than the sum of radii the circles touch
  boolean intersect(Ball b) {
    
    // Objects can be passed into functions as arguments too! 
    float distance = dist(x,y,b.x,b.y); // Calculate distance
    
    // Compare distance to sum of radii
    if (distance < r + b.r) {
      return true;
    } else {
      return false;
    }
  }
}
  • Alexis

    hey- when I try to put ellipse(x, y, r, r); as opposed to ellipse(x, y, r*2, r*2); in the display portion of the Ball class, the intersect function becomes less accurate somehow, and the balls highlight when they are close but not actually touching…why is that?

  • shiffman

    Processing expects a diameter when drawing a circle, but the intersect math is based on a radius.  Diameter = radius * 2

  • John Q. Smith

    The code that makes the balls highlight is not directly tied to the display code, they just happen to be the same size.

    you would have to change
    // Compare distance to sum of radii
    if (distance < r + b.r) {

    to something like

    // Compare distance to sum of radii
    if (distance < r/2 + b.r/2) {

    in order for the intersect function to take the smaller drawing size into account.

    Of course, if you do this you should change all the r's (short for radius) into d's (short for diameter) and fix the comments so anyone looking at your code doesn't get confused.

  • Daman Singh

    How would i convert this to work with squares or rectangles?
    Im trying to make a game but i cant figure out how to set up the .intersect to work with a square

  • shiffman

    you can use a series of conditional statements to determine if the bounds of one rectangle are within another. Here’s a start: http://stackoverflow.com/questions/2752349/fast-rectangle-to-rectangle-intersection

  • Daman Singh

    it kind of helps but i have no idea how to use that in my code… I have around 4 random rectangles and 1 that the player “drags”. The idea is to not touch the random squares. I have everything in a class of its own. ( class rect1, class rect2 and so on). How would i implement that into my code? Here it is: (The classes are all in their own tabs but i dont know how to show that here)

    button restart;

    float score;

    int msec, sec;

    boolean start;

    void setup() {

    size(600, 600);

    smooth();

    redSquare = new player(275, 275, 60, 60);

    squareOne = new square();

    squareTwo = new square2();

    rectangleOne = new rectangle();

    rectangleTwo = new rectangle2();

    outline = new blackSquare();

    restart = new button();

    }

    void draw() {

    background(255);

    if (!start) {

    sec = floor((millis()-msec)*.001);

    if (sec == 4) start = true;

    }

    else {

    //do stuff here when the coundown finishes

    score = millis();

    outline.display();

    squareOne.display();

    squareOne.move();

    squareTwo.display();

    squareTwo.move();

    redSquare.rollover(mouseX, mouseY);

    redSquare.drag(mouseX, mouseY);

    redSquare.display();

    rectangleOne.display();

    rectangleOne.move();

    rectangleTwo.display();

    rectangleTwo.move();

    if (mouseX = 550)

    {

    noLoop();

    youLose();

    restart.display();

    }

    if (mouseY = 550)

    {

    noLoop();

    youLose();

    restart.display();

    }

    }

    if (sec == 3) { //after three seconds one second remains …

    fill(0);

    rect(260, 80, 48, 160);

    rect(260, 288, 48, 160);

    }

    if (sec == 2) {

    fill(0);

    rect(100, 32, 160, 48);

    rect(100, 240, 160, 48);

    rect(52, 288, 48, 160);

    rect(100, 448, 160, 48);

    rect(260, 80, 48, 160);

    }

    if (sec == 1) {

    fill(0);

    rect(100, 32, 160, 48);

    rect(100, 240, 160, 48);

    rect(100, 448, 160, 48);

    rect(260, 80, 48, 160);

    rect(260, 288, 48, 160);

    }

    }

    void mousePressed() {

    redSquare.clicked(mouseX, mouseY);

    }

    void mouseReleased() {

    redSquare.stopDragging();

    }

    void youLose() {

    fill(155, 155, 155);

    stroke(155, 155, 155);

    text(“You lose”, 300, 300);

    }

    class button {

    button() {

    float x;

    float y;

    }

    void display() {

    fill(255);

    rect(300, 300, 100, 50);

    fill(255, 0, 255);

    text(“Try again?”, 320, 325);

    }

    }

    class square{

    float x;

    float y;

    float xspeed, yspeed;

    color c;

    square() { // A constructor.

    c = color(0,0,255);

    x = random(0,100);

    y = random(0,100);

    xspeed = random(-3,3);

    yspeed = random(-3,3);

    }

    void move() {

    x += xspeed; // Increment x

    y += yspeed; // Increment y

    // Check horizontal edges

    if (x > width || x height || y width || x height || y width || x height || y width || x height || y x && mx y && my x && mx y && my < y + h) {

    rollover = true;

    } else {

    rollover = false;

    }

    }

    void stopDragging() {

    dragging = false;

    }

    void drag(int mx, int my) {

    if (dragging) {

    x = mx + offsetX;

    y = my + offsetY;

    }

    }

    }