Java by Example - detecting collisions and intersections

back 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 next

The simplest method to detect collisions of two shapes is the bounding rectangle detection. Whenever the rectangles that surround the shapes intersect, a collision is detected. To accomplish this, we can use the convenient method intersects of the Rectangle class, Java provides us with: collide=r1.intersects(r2); The boolean instance variable collide receives the value of an intersection taken place, between the Rectangle objects r1 and r2. Whenever the two rectangles collide, it it reported and signaled:

//Sourcecode

import java.awt.*;
import java.applet.*;

public class Project34 extends Applet
{
    Image Buffer;
    Graphics gBuffer;
    int x, y;
    boolean mouseInside, collide;
    Rectangle r1, r2;

    public void init()
    {
        Buffer=createImage(size().width,size().height);
        gBuffer=Buffer.getGraphics();

        //create 2 rectangle objects
        r1=new Rectangle(110,115,60,50);
        //we don't know the coordinates yet, so we create it
        //with a different constructor, passing only the size.
        //The Rectangle class has several constructors, with different parameters!
        r2=new Rectangle(40,40);
    }

    public void drawStuff()
    {
        gBuffer.setColor(Color.white);
        gBuffer.fillRect(0,0,size().width,size().height);

        gBuffer.setColor(Color.red);
        gBuffer.fillRect(r1.x, r1.y, r1.width, r1.height);

        gBuffer.setColor(Color.blue);

        gBuffer.setFont(new Font("Helvetica",Font.BOLD,16));

        if(mouseInside)
            gBuffer.fillRect(r2.x, r2.y, r2.width, r2.height);
        else
            gBuffer.drawString("Move the mouse around!", 10, 20);

        gBuffer.setColor(Color.black);

        if(collide)
            gBuffer.drawString("Collision!", 10, 20);
    }

    public boolean mouseEnter(Event evt,int x,int y)
    {
        mouseInside=true;
        repaint();

        return true;
    }

    public boolean mouseExit(Event evt,int x,int y)
    {
        mouseInside=false ;
        repaint();

        return true;
    }

    public boolean mouseMove(Event evt,int x,int y)
    {
        //submit the mouse coordinates to our instance variables
        this.x=x;
        this.y=y;

        //move the blue square according to mouse position
        //we use the Rectangle method "move" here
        r2.move(x-r2.width/2, y-r2.height/2);

        //check for collision here, use the "intersects" method
        //of the Rectangle class
        collide=r1.intersects(r2);

        drawStuff();

        repaint();
        return true;
    }

    public void update(Graphics g)
    {
        paint(g);
    }

    public void paint(Graphics g)
    {
        drawStuff();
        g.drawImage (Buffer,0,0, this);
    }
}

The next applet enhances the one before, by displaying a new rectangle that represents the intersection between the two colliding rectangles. We use a third Rectangle object r3, which is computed with the Rectangle class method intersection like this: r3=r1.intersection(r2);. We just have to display the coordinates and dimensions of this new rectangle in a different color:

//Sourcecode

import java.awt.*;
import java.applet.*;

public class Project35 extends Applet
{
    Image Buffer;
    Graphics gBuffer;
    int x, y;
    boolean mouseInside, collide;
    //r3 is the intersection of r1 and r2
    Rectangle r1, r2, r3;

    public void init()
    {
        Buffer=createImage(size().width,size().height);
        gBuffer=Buffer.getGraphics();

        //create 2 rectangle objects
        r1=new Rectangle(110,115,60,50);
        //we don't know the coordinates yet, so we create it
        //with a different constructor, passing only the size
        r2=new Rectangle(40,40);
        //of r3 we don't know anything yet, so we call the empty constructor
        r3=new Rectangle();
    }

    public void drawStuff()
    {
        gBuffer.setColor(Color.white);
        gBuffer.fillRect(0,0,size().width,size().height);

        gBuffer.setColor(Color.red);
        gBuffer.fillRect(r1.x, r1.y, r1.width, r1.height);

        gBuffer.setFont(new Font("Helvetica",Font.BOLD,16));
        gBuffer.setColor(Color.blue);

        if(mouseInside)
            gBuffer.fillRect(r2.x, r2.y, r2.width, r2.height);
        else
           gBuffer.drawString("Move the mouse around!", 10, 20);

        gBuffer.setColor(Color.black);

        if(collide)
            gBuffer.drawString("Intersection!", 10, 20);

        //the intersection
        gBuffer.setColor(Color.magenta);
        gBuffer.fillRect(r3.x, r3.y, r3.width, r3.height);
    }

    public boolean mouseEnter(Event evt,int x,int y)
    {
        mouseInside=true;
        repaint();

        return true;
    }

    public boolean mouseExit(Event evt,int x,int y)
    {
        mouseInside=false ;
        repaint();

        return true;
    }

    public boolean mouseMove(Event evt,int x,int y)
    {
        //submit the mouse coordinates to our instance variables
        this.x=x;
        this.y=y;

        //move the blue square according to mouse position
        //we use the Rectangle method "move" here
        r2.move(x-r2.width/2, y-r2.height/2);

        //check for collision here, use the "intersects" method
        //of the Rectangle class
        collide=r1.intersects(r2);

        //calculate the intersection, assign it to r3
        r3=r1.intersection(r2);

        drawStuff();

        repaint();
        return true;
    }

    public void update(Graphics g)
    {
        paint(g);
    }

    public void paint(Graphics g)
    {
        drawStuff();
        g.drawImage (Buffer,0,0, this);
    }
}

To compute the distance between two points (for example in order to tell the score in a shooting game), you have to follow a different approach. A simple linear comparison between the x- and y-coordinates of two points will fail, when the two points are not aligned vertically or horizontally. We use the Theorem of Pythagoras here: Squareroot of((x1-x2)2*(y1-y2)2). That way we can tell exactly, which distance lies between two given points, regardless of their orientation on the screen. We use the Point class here, which is only a simple encapsulation for two variables, representing the x and y coordinates of a given point. To tell when the two circles collide, you just have to take the diameters into account:

//Sourcecode

import java.awt.*;
import java.applet.*;

public class Project36 extends Applet
{
    Image Buffer;
    Graphics gBuffer;
    int x, y, dist;
    boolean mouseInside;
    //middle points of the two circles
    Point p1, p2;

    public void init()
    {
        Buffer=createImage(size().width,size().height);
        gBuffer=Buffer.getGraphics();

        //center of red circle
        p1=new Point(150,150);
        //center of blue circle
        p2=new Point(0,0);
    }

    public void drawStuff()
    {
        gBuffer.setColor(Color.white);
        gBuffer.fillRect(0,0,size().width,size().height);

        gBuffer.setColor(Color.red);
        gBuffer.fillOval(p1.x-20,p1.y-20,40,40);

        gBuffer.setFont(new Font("Helvetica",Font.BOLD,16));
        gBuffer.setColor(Color.blue);

        if(mouseInside)
            gBuffer.fillOval(p2.x-20,p2.y-20,40,40);
        else
            gBuffer.drawString("Move the mouse around!", 10, 20);

        if(mouseInside)
        {
            if(dist<=40)
            {
                gBuffer.setColor(Color.red);
                gBuffer.drawString("Collision!", 10, 20);
            }

            gBuffer.setColor(Color.black);
            gBuffer.drawString("Distance: "+dist, 10, 40);
        }
    }

    public boolean mouseEnter(Event evt,int x,int y)
    {
        mouseInside=true;
        repaint();

        return true;
    }

    public boolean mouseExit(Event evt,int x,int y)
    {
        mouseInside=false;
        repaint();

        return true;
    }

    public boolean mouseMove(Event evt,int x,int y)
    {
        //submit the mouse coordinates to our instance variables
        this.x=x;
        this.y=y;

        p2.move(x,y);

        //calculate the distance of the centers (Theorem of Pythagoras)
        dist=(int)Math.sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));

        drawStuff();

        repaint();
        return true;
    }

    public void update(Graphics g)
    {
        paint(g);
    }

    public void paint(Graphics g)
    {
        drawStuff();
        g.drawImage (Buffer,0,0, this);
    }
}

back 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 next

0 - setup - getting your tools ready
1 - basic graphics functions
2 - simple methods and basic data types
3 - IF, ELSE and SWITCH: basic control structures
4 - introducing the operators
5 - methods with and without a return value
6 - using methods and basic mouse functions
7 - fonts, random numbers and timers
8 - flicker free graphics, GIF and JPEG display
9 - animation with GIF pictures, sprite animation
10 - loops, advanced color functions
11 - random colors and arrays
12 - digital clocks, HTML page parameters
13 - introducing classes and objects
14 - using the Vector class
15 - using mouseMove and mouseDrag
16 - keyboard commands and playing sound
17 - detecting collisions and intersections
18 - a Bouncing Balls applet
19 - fun with letters and words
20 - rotating lines and polygons
21 - sorting and shuffling


© 2000 by Johannes Wallroth
www.programming.de

watson@programming.de