In this tutorial we will introduce a simple technique for detecting a collision between two objects. When the distance between two objects is less than their combined radii they are touching.
We can calculate the distance between two objects using the Pythagorean Distance Formula.
Ball.java
import java.lang.Math;
public class Ball {
private int px;
private int py;
private int speed;
private int width;
public Ball(int px, int py, int speed) {
this.px = px;
this.py = py;
this.speed = speed;
this.width = 50;
}
public int getPx(){
return this.px;
}
public int getPy(){
return this.py;
}
public void setPx(int x){
this.px = x;
}
public void setPy(int y){
this.py = y;
}
public int getWidth(){
return this.width;
}
public void moveUp(){
if((py-speed) > 0){
py-=speed;
}
else if(py > 0){
py-=py;
}
}
public void moveDown(){
if((py+width+speed) < 250){
py+=speed;
}
else if((py+width) < 250){
py+=(250-(py+width));
}
}
public void moveLeft(){
if((px-speed) > 0){
px-=speed;
}
else if(px > 0){
px-=(px);
}
}
public void moveRight(){
if((px+width+speed) < 250){
px+=speed;
}
else if((px+width) < 250){
px+=(250-(px+width));
}
}
public boolean collisionTest(Ball[] ball){
for(Ball b:ball){
int distance = (int)Math.sqrt((Math.pow(b.getPx() - this.px,2))
+ (Math.pow(b.getPy() - this.py,2)));
int radii = (b.getWidth()/2) + (this.width/2);
if(distance < radii){
return true;
}
}
return false;
}
}
There are three additions to this class since Java, Move an Object Using the Arrow Keys. The first two are simple setter methods that allow us to directly set the x and y positions of the ball. The third new method is where the collision detection takes place. This method takes an array of Ball objects as it's only parameter. An enhanced for loop is used to access each ball in the array and see if it is colliding with our main ball object. We use the Math.sqrt() and Math.pow() methods to set up the distance formula mentioned above. If the distance between any Ball object and our main ball is less than their combined radii, the method immediately returns true.
Collision.java
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Collision extends Applet{
public static final int WIDTH = 250;
public static final int HEIGHT = 250;
Graphics backBuffer;
Image frontBuffer;
Image background;
Image ball;
Image blueball;
Image yellowball;
Image redball;
Ball myBall = new Ball(100,100,5);
Ball [] obstacle = {new Ball(100,30,0),new Ball(10,170,0),new Ball(170,170,0)};
Dimension appletSize;
boolean leftKey = false;
boolean rightKey = false;
boolean upKey = false;
boolean downKey = false;
public void init(){
this.setSize(WIDTH, HEIGHT);
appletSize = getSize();
addKeyListener(new MyKeyListener());
frontBuffer = createImage(appletSize.width,appletSize.height);
backBuffer = frontBuffer.getGraphics();
background = getImage(getDocumentBase(), "wood.png");
ball = getImage(getDocumentBase(),"ball.png");
redball = getImage(getDocumentBase(),"redball.png");
blueball = getImage(getDocumentBase(),"blueball.png");
yellowball = getImage(getDocumentBase(),"yellowball.png");
Thread t = new Thread(new MainLoop());
t.start();
}
private class MyKeyListener extends KeyAdapter{
public void keyPressed(KeyEvent e){
switch (e.getKeyCode()){
case KeyEvent.VK_LEFT:
leftKey = true;
break;
case KeyEvent.VK_RIGHT:
rightKey = true;
break;
case KeyEvent.VK_UP:
upKey = true;
break;
case KeyEvent.VK_DOWN:
downKey = true;
break;
}
}
public void keyReleased(KeyEvent e){
switch (e.getKeyCode()){
case KeyEvent.VK_LEFT:
leftKey = false;
break;
case KeyEvent.VK_RIGHT:
rightKey = false;
break;
case KeyEvent.VK_UP:
upKey = false;
break;
case KeyEvent.VK_DOWN:
downKey = false;
break;
}
}
}
public class MainLoop implements Runnable{
public MainLoop(){
}
public void run(){
while(true){
int lastX = myBall.getPx();
int lastY = myBall.getPy();
if(upKey){ myBall.moveUp(); }
if(downKey){ myBall.moveDown(); }
if(leftKey){ myBall.moveLeft(); }
if(rightKey){ myBall.moveRight(); }
if(myBall.collisionTest(obstacle)){
myBall.setPx(lastX);
myBall.setPy(lastY);
}
repaint();
try {
Thread.sleep(20);
}
catch (InterruptedException ex){
}
}
}
}
public void drawScreen(Graphics display){
backBuffer.drawImage(background,0,0,null);
backBuffer.drawImage(ball, myBall.getPx(), myBall.getPy(), null);
backBuffer.drawImage(redball, obstacle[0].getPx(), obstacle[0].getPy(), null);
backBuffer.drawImage(blueball, obstacle[1].getPx(), obstacle[1].getPy(), null);
backBuffer.drawImage(yellowball, obstacle[2].getPx(), obstacle[2].getPy(), null);
backBuffer.drawString("CLICK ON SCREEN TO GAIN FOCUS THEN...",0,230);
backBuffer.drawString("press arrow keys to move ball",0,245);
display.drawImage(frontBuffer,0,0,this);
}
public void update(Graphics display){
drawScreen(display);
}
}
Comparing this class to the one we created in Java, Move an Object Using the Arrow Keys, notice that we have created three new Image objects for our new balls. They are loaded in the init() method and drawn to the screen in the drawScreen method. We have also created an array of 3 Ball objects that will hold the actual data. Down in the mainLoop, before the main ball is allowed to move, we first make a copy of it's x and y position. After the main ball has potentially moved, we check to see if it is colliding with another ball. If it is, we simply move the ball back to where it was by passing the x and y copies into the setter methods we created earlier in our Ball class. Of course this all happens before the screen is updated so we never actually see the ball jumping out of the collision.
You might also be interested in





