I recently created the following code, which is supposed to implement a Pong variation for one player. How can I improve or optimize my code?
Pong class:
import javax.swing.JFrame;
public class Pong extends JFrame {
private static final int HEIGHT = 500, WIDTH = 900;
public Pong() {
super("Pong");
setSize(WIDTH, HEIGHT);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
add(new PongPanel(this));
setVisible(true);
}
public static void main(String[] args) {
new Pong();
}
}
PongPanel class:
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
public class PongPanel extends JPanel {
private Racket racket;
private Ball ball;
private JLabel scoreLabel;
private int score = 0;
public PongPanel(Pong game) {
racket = new Racket(game, game.getHeight() - 100);
ball = new Ball(game);
scoreLabel = new JLabel(Integer.toString(score));
scoreLabel.setFont(new Font("sansserif", Font.PLAIN, 30));
add(scoreLabel);
Timer timer = new Timer(5, new TimerHandler());
timer.start();
addKeyListener(new KeyHandler());
setFocusable(true);
}
private void update() {
racket.updatePosition();
ball.updatePosition();
checkCollisionBallSides();
checkCollisionBallRacket();
repaint();
}
private void checkCollisionBallSides() {
if (ball.getX() < 0 || ball.getX() > getWidth() - ball.getWidth() - (getInsets().left + getInsets().right))
ball.setXA(-ball.getXA());
else if (ball.getY() < 0)
ball.setYA(-ball.getYA());
else if (ball.getY() > getHeight() - ball.getHeight()) {
JOptionPane.showMessageDialog(null, "Game Over. You scored " + score + ".", "Pong", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
private void checkCollisionBallRacket() {
if (ball.getBounds().y + ball.getHeight() == racket.getBounds().y &&
ball.getBounds().x + ball.getWidth() > racket.getBounds().x &&
racket.getBounds().x + racket.getWidth() > ball.getBounds().x) {
ball.setYA(-ball.getYA());
score++;
scoreLabel.setText(Integer.toString(score));
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
racket.paint(g);
ball.paint(g);
}
private class KeyHandler implements KeyListener {
@Override
public void keyPressed(KeyEvent e) {
racket.pressed(e);
}
@Override
public void keyReleased(KeyEvent e) {
racket.released(e);
}
@Override
public void keyTyped(KeyEvent e) {
}
}
private class TimerHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
update();
}
}
}
Racket class:
import java.awt.Graphics;
import java.awt.event.KeyEvent;
public class Racket extends Sprite {
private final Pong game;
public Racket(Pong game, int y) {
super((game.getWidth() - 60) / 2, y, 0, 0, 60, 10);
this.game = game;
}
public void pressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT)
setXA(-1);
else if (key == KeyEvent.VK_RIGHT)
setXA(1);
}
public void released(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT || key == KeyEvent.VK_RIGHT)
setXA(0);
}
public void updatePosition() {
if (getX() + getXA() >= 0 && getX() + getXA() < game.getWidth() - getWidth())
setX(getX() + getXA());
}
public void paint(Graphics g) {
g.fillRect(getX(), getY(), getWidth(), getHeight());
}
}
Ball class:
import java.awt.Graphics;
public class Ball extends Sprite {
public Ball() {
super(0, 0, 1, 1, 30, 30);
}
public void updatePosition() {
setX(getX() + getXA());
setY(getY() + getYA());
}
public void paint(Graphics g) {
g.fillOval(getX(), getY(), getWidth(), getHeight());
}
}
Sprite class:
import java.awt.Rectangle;
public class Sprite {
private int x, y, xa, ya, width, height;
public Sprite(int x, int y, int xa, int ya, int width, int height) {
this.x = x;
this.y = y;
this.xa = xa;
this.ya = ya;
this.width = width;
this.height = height;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getXA() {
return xa;
}
public int getYA() {
return ya;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public Rectangle getBounds() {
return new Rectangle(x, y, width, height);
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setXA(int xa) {
this.xa = xa;
}
public void setYA(int ya) {
this.ya = ya;
}
}
JFrameclass; it is usually better to compose your class with aJFrameinstance. See this: coderanch.com/t/491015/java/java/extends-JFrame-JFrame \$\endgroup\$