Java by Example - detecting collisions and intersections
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);
}
}
|
|