Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

Bouncing Ball Applet

Ok, so I made a simple applet that has a blue ball that bounces around an applet. When the ball encounters the bounds of the applet it bounces appropriately. However, I have a few kinks to work out that I'm a little puzzled about.
FYI, double buffering isn't one of those kinks- I'll fix that a little later since it's not that important in my opinion.

Here's the problem:
If my ball's position is incremented/decremented with an incrementation of 1, than I can easily detect when the ball collides into a wall. However, if my incrementation is, say, by a number 3 or 5, etc the ball will be detected when it encounters the bounds of the applet but will also have 'slipped' a little bit past the bounds of the applet. It 'slips' far enough to be noticeable by the user.

If I keep my increment number @ 1 than my timer that constantly calls repaint for the applet will have to have a very short delay like 10 or something for the ball to move at what I deem an appropriate speed. To remedy this I can increase my increment number but then I will run into the problem mentioned above.

Here's the code. Thanks for the input.

/*
*Ball Class
*Ball.java
*/

import java.awt.*;

public class Ball{
private int xPos;
private int yPos;
//speed at which balls coord's are incremented/decremented
private int xIncr = 3;
private int yIncr = 3;
private Color col;
final int size = 25;
//size of Applet: 300 x 400
static final int WIDTH = 300;
static final int HEIGHT = 400;

public Ball(int x, int y, Color color){
xPos = x;
yPos = y;
col = color;
}

public Ball(){
//starting position
this(150,150,Color.blue);
}

public int getXPos(){
return xPos;
}

public int getYPos(){
return yPos;
}

public void checkBounce(){
System.out.println("checkBounce");
if(xPos < 0 || xPos > WIDTH - size){
//ball hit left or right of applet
this.reverseX();
}

if(yPos < 0 || yPos > HEIGHT - size){
//ball hit top or bottom of applet
this.reverseY();
}
}

public void reverseX(){
//debugging print statement
System.out.println("reverseX");
xIncr = (-1)* xIncr;
}

public void reverseY(){
//debugging print statement
System.out.println("reverseY");
yIncr = (-1)* yIncr;
}

public void moveBall(Graphics g){
checkBounce();
g.setColor(col);
g.fillOval(xPos, yPos, size, size);
xPos += xIncr;
yPos += yIncr;
System.out.println("(" + xPos + " , " + yPos + ")");
}
}

/*
*Main class
*Main.java
*/

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Main extends JApplet implements ActionListener{
Ball ball;
Timer timer;
final int DELAY = 50;

public void init(){
//set background color
this.setBackground(Color.black);
//this.setBackground(new Color(100,0,100));
//use default constructor for test
ball = new Ball();
//constructor Timer(int millidelay, ActionListener l)
timer = new Timer(DELAY, this);
repaint();
}

public void start(){
timer.start();
}

public void stop(){
timer.stop();
}

public void destroy(){
//System.exit(0);
}

public void paint(Graphics g){
super.paint(g);
ball.moveBall(g);
}

public void actionPerformed(ActionEvent e){
if(e.getSource() == timer){
//call paint method
repaint();
}
}
}
[3866 byte] By [nescafe] at [2007-11-11 6:59:36]
# 1 Re: Bouncing Ball Applet
When the coordinates tells you that a tick drives a ball through the wall then
you should do the math for calculating its new position as if it had hit the
wall at the proper place and bounced back a little. In other worlds; the
actual impact will not be "on film" for some of these collisions. This is the
only option when you are using a fixed framerate.
sjalle at 2007-11-11 22:39:46 >