Original Post
Hey folks, nice to meet you! I'm trying to program a pong applet in Java, but not object oriented style. I've made a couple simple game clones before, but this is my first Java game and I'm having a bit of trouble. This is also my first time using threads in Java so if I'm doing something wrong let me know. Anyway, the problem is this: the game works fine at first, I can play for maybe 2 minutes without a glitch. Then suddenly it freezes. In the Java Console it stays there is a StackOverflowError, which usually means that there is some sort of recursion happening, but theres no recursion in this program. Here it is: If anyone can figure out what I've done wrong, I'd be really pleased. Theres still lots of functionality left to add to the game so try not to let that distract you. ;) Thanks a lot!
// PongApplet.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class PongApplet extends JApplet implements Runnable
{
//Constants
private static final int WIDTH = 500;
private static final int HEIGHT = 350;
private static final int TOP_PADDING = 30;
private static final int WALL_THICKNESS = 10;
private static final int PLAYAREA_TOP = TOP_PADDING + WALL_THICKNESS;
private static final int PLAYAREA_BOTTOM = HEIGHT - WALL_THICKNESS;
private static final int BAT_THICKNESS = 10;
private static final int BAT_HEIGHT = 60;
private static final double BAT_START_Y = PLAYAREA_TOP + (PLAYAREA_BOTTOM-PLAYAREA_TOP)/2 - BAT_HEIGHT/2;
private static final double BAT_SPEED = .5;
private static final int BALL_SIZE = 10;
private static final int BALL_START_X = WIDTH / 2;
private static final int BALL_START_Y = (PLAYAREA_BOTTOM - PLAYAREA_TOP) / 2;
//ball location and velocity
private double ballX = BALL_START_X;
private double ballY = BALL_START_Y;
private double xVelocity = -0.3;
private double yVelocity = 0.3;
//bat locations
private double bat1Y = BAT_START_Y;
private double bat2Y = BAT_START_Y;
//used for getting input
boolean upPressed = false;
boolean downPressed = false;
boolean resetPressed = false;
private Image buffer;
private Thread animatorThread;
public void init()
{
}
public void start()
{
buffer = createImage(WIDTH,HEIGHT);
animatorThread = new Thread(this);
animatorThread.start();
}
public void stop()
{
buffer = null;
animatorThread = null;
}
public void destroy()
{
}
public void run()
{
while(true)
{
try {
requestFocus();
addKeyListener(new KeyAdapter() {
//get input
public void keyPressed(KeyEvent e)
{
int keycode = e.getKeyCode();
if(keycode == KeyEvent.VK_UP)
upPressed = true;
if(keycode == KeyEvent.VK_DOWN)
downPressed = true;
if(keycode == KeyEvent.VK_R)
resetPressed = true;
}
public void keyReleased(KeyEvent e)
{
int keycode = e.getKeyCode();
if(keycode == KeyEvent.VK_UP)
upPressed = false;
if(keycode == KeyEvent.VK_DOWN)
downPressed = false;
if(keycode == KeyEvent.VK_R)
resetPressed = false;
}
});
if(resetPressed)
{
ballX = BALL_START_X;
ballY = BALL_START_Y;
resetPressed = false;
}
//move the left bat
if(upPressed)
bat1Y -= BAT_SPEED;
if(downPressed)
bat1Y += BAT_SPEED;
//move the right bat (until i make the AI)
if(upPressed)
bat2Y -= BAT_SPEED;
if(downPressed)
bat2Y += BAT_SPEED;
//correct the position if the bat left the play area
if(bat1Y < PLAYAREA_TOP)
bat1Y = PLAYAREA_TOP;
if(bat1Y + BAT_HEIGHT > PLAYAREA_BOTTOM)
bat1Y = PLAYAREA_BOTTOM-BAT_HEIGHT;
//calculate ball's new position
double newBallX = ballX + xVelocity;
double newBallY = ballY + yVelocity;
//bounce ball off top or bottom of play area
if(newBallY + BALL_SIZE/2 > PLAYAREA_BOTTOM ||
newBallY < PLAYAREA_TOP)
yVelocity = -yVelocity;
//test for collisions between ball and right bat
if(xVelocity > 0 && newBallX >= WIDTH-BAT_THICKNESS)
{
if(ballX <= WIDTH-BAT_THICKNESS) //bounce off front of bat
{
if(ballY > bat2Y && ballY < bat2Y+BAT_HEIGHT)
xVelocity = -xVelocity;
}
else //bounce off top or bottom of bat
{
if(ballY < bat2Y && yVelocity > 0 && newBallY > bat2Y)
yVelocity = -yVelocity;
else if(ballY > bat2Y+BAT_HEIGHT && yVelocity < 0 && newBallY < bat2Y+BAT_HEIGHT)
yVelocity = -yVelocity;
}
}
//collisions between ball and left bat
else if(xVelocity < 0 && newBallX <= BAT_THICKNESS)
{
if(ballX >= BAT_THICKNESS) //bounce off front of bat
{
if(ballY > bat1Y && ballY < bat1Y+BAT_HEIGHT)
xVelocity = -xVelocity;
}
else //bounce off top or bottom of bat
{
if(ballY < bat1Y && yVelocity > 0 && newBallY > bat1Y)
yVelocity = -yVelocity;
else if(ballY > bat1Y+BAT_HEIGHT && yVelocity < 0 && newBallY < bat1Y+BAT_HEIGHT)
yVelocity = -yVelocity;
}
}
//move ball to new position
ballX = newBallX;
ballY = newBallY;
//draw to buffer
//draw background, ball
Graphics bg = buffer.getGraphics();
bg.setColor(Color.black);
bg.fillRect(0,0,WIDTH,HEIGHT);
bg.setColor(Color.white);
bg.fillRect((int)(ballX - BALL_SIZE/2), (int)(ballY - BALL_SIZE/2), BALL_SIZE, BALL_SIZE);
//draw walls
bg.fillRect(0,PLAYAREA_TOP-WALL_THICKNESS,WIDTH,WALL_THICKNESS);
bg.fillRect(0,PLAYAREA_BOTTOM,WIDTH,WALL_THICKNESS);
//draw bats
bg.fillRect(0,(int)bat1Y,BAT_THICKNESS,BAT_HEIGHT);
bg.fillRect(WIDTH-BAT_THICKNESS,(int)bat2Y,BAT_THICKNESS,BAT_HEIGHT);
//display buffer in the applet
Graphics g = this.getGraphics();
g.drawImage(buffer,0,0,null);
//let other threads do their thing
animatorThread.yield();
} catch (Exception e){}
}
}
public void paint(Graphics g)
{
}
}