5
\$\begingroup\$

I tried to make a Pong game in Java. It's my first game I have ever programmed, and I would be very pleased if you would take the time to advise me on what I could do better next time. Thank you so much :) .

Here is my code:

Start.java:

import java.awt.EventQueue;

public class Start {

public static void main(String[] args) {
    Runnable runner = new Runnable() {
        public void run() {
            GameFrame gameFrame = new GameFrame();
            
        }
    };
    
    EventQueue.invokeLater(runner);
}

}

GameFrame.java:

import javax.swing.JFrame;

public class GameFrame extends JFrame{

public GameFrame() {
     
    initFrame();
}

private void initFrame() {
    
    add(new GameBoard());
    
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setTitle("PongGame");
    setResizable(false);
    pack();
    setLocationRelativeTo(null);
    setVisible(true);
    
}
}

GameBoard.java:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;

public class GameBoard extends JPanel implements Runnable{

public static final int WIDTH = 900 ; 
public static final int HEIGHT = 2 * WIDTH / 3; 
private final int DELAY = 10;

private int scoreL = 0;
private int scoreR = 0;

private boolean inGame = false;

private Paddle rightPaddle, leftPaddle;
private Ball ball;

private Thread game;


public GameBoard() { 
    
    initGameBoard();
}


private void initGameBoard() {
    
    setBackground(Color.black);
    setPreferredSize(new Dimension(WIDTH, HEIGHT));
    setFocusable(true);
    addKeyListener(new KAdapter());
    
    ball = new Ball();
    
    rightPaddle =  new Paddle("right");
    leftPaddle = new Paddle("left");
    
   }



public void paintComponent(Graphics g) {
    super.paintComponent(g);
    
    Graphics2D g2d = (Graphics2D) g;

    g2d.setStroke(new BasicStroke(5.0f));
    g2d.drawLine(WIDTH/2, 0, WIDTH/2, HEIGHT);
    
    drawBall(g2d);
    drawPaddle(g2d);
    drawScore(g2d);
    
    if(!inGame) {
        drawPressSpace(g2d);
        }
    
    Toolkit.getDefaultToolkit().sync();
}



public void addNotify() {
    super.addNotify();
    
    game = new Thread(this);
    game.start();
}


private void drawPaddle(Graphics2D g2d) {

        g2d.drawImage(rightPaddle.getImage(), rightPaddle.getX(), rightPaddle.getY(), this);
        g2d.drawImage(leftPaddle.getImage(), leftPaddle.getX(), leftPaddle.getY(), this);
    
}


private void drawPressSpace(Graphics2D g2d) {
    
    String press = "Press space to begin";
    Font font = new Font("Verdana", Font.BOLD , 20);
    FontMetrics fm = getFontMetrics(font);
    g2d.setFont(font);
    g2d.setColor(Color.red);
    g2d.drawString(press, (WIDTH - fm.stringWidth(press)) / 2, (HEIGHT - fm.getHeight()) / 2);  

}

private void drawScore(Graphics2D g2d) {

    Font font = new Font("Verdana", Font.PLAIN , 50);
    FontMetrics fm = getFontMetrics(font);
    g2d.setColor(Color.gray);
    g2d.setFont(font);
    g2d.drawString(""+scoreL, 50, fm.stringWidth(""+scoreL) + 40);  
    g2d.drawString(""+scoreR, WIDTH - fm.stringWidth(""+scoreR) - 50, fm.stringWidth(""+scoreR) + 40);
    
}

private void drawBall(Graphics2D g2d) {
    g2d.drawImage(ball.getImage(), ball.getX(), ball.getY(), this);
}


public void run() {
    long beforeT, timeDiff, sleep;
    beforeT = System.currentTimeMillis();
    
    while (true) {
        
        updatePaddles();
        
        if(inGame) {
            updateBall();
        } else {
            rightPaddle.resetPos();
            leftPaddle.resetPos();
            
        }
        repaint();
        
        
        timeDiff = System.currentTimeMillis() - beforeT;
        sleep = DELAY - timeDiff;
        
        if (sleep < 2) {
            sleep = 2;
        }
        
        try {
            Thread.sleep(sleep);
            
        }catch(Exception e) {
            e.getStackTrace();
        }
        
        beforeT = System.currentTimeMillis();
        }
   }


private void updatePaddles() {
    
    rightPaddle.move();
    leftPaddle.move();
}

private void updateBall() {
    
    boolean b = checkCollision();
    
    int i = ball.move(b);
    
    if(i != 0) {
        switch(i) {
        case 1: scoreR++; break;
        case 2: scoreL++; break;
        }
        
        inGame = false;
    }
   }

private boolean checkCollision() {
    Rectangle rb = ball.getBounds();

    Rectangle rp = rightPaddle.getBounds();
        
        if(rb.intersects(rp)) {
            return true;
        }
        
        rp = leftPaddle.getBounds();
        
        if(rb.intersects(rp)) {
            return true;
        }
        
        return false;
    
   }

private class KAdapter extends KeyAdapter{
    
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        
        if(!inGame && keyCode == KeyEvent.VK_SPACE) { 
            inGame = true;
            ball.start();
            return;
        } 
        
    if(inGame) {
            
            if(rightPaddle.isKey(keyCode)) {
                rightPaddle.keyPressed(keyCode);

            } else if(leftPaddle.isKey(keyCode)) {
                leftPaddle.keyPressed(keyCode);

            }   
        }
    }
    
    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        
        if(rightPaddle.isKey(keyCode)) {
            rightPaddle.keyReleased(keyCode);

        } else if(leftPaddle.isKey(keyCode)) {
            leftPaddle.keyReleased(keyCode);

            }
        }
    }
}

Sprite.java:

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;

public class Sprite {

protected int x; 
protected int y; 
private int width;
private int height;

protected BufferedImage image;

public Sprite(int width, int height) {
    this.width = width;
    this.height = height;
    updateImage();
}

private void updateImage() { 
    
    image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    
    Graphics2D g2d = (Graphics2D) image.getGraphics();
    g2d.setColor(Color.white);
    g2d.fillRect(0, 0, width, height);
    
}

public BufferedImage getImage() {
    return this.image;
}

public int getX() {
    return this.x;
}

public int getY() {
    return this.y;
}

public Rectangle getBounds() {
    return new Rectangle(x, y, width, height);
}

}   

Paddle.java:

import java.awt.event.KeyEvent;

public class Paddle extends Sprite{

public final static int WIDTH = 20; 
public final static int HEIGHT = GameBoard.HEIGHT / 5;
private final int SPEED = 8;
private String side;
private int up; 
private int down; 
private int dy; 


public Paddle(String side) {
    super(WIDTH, HEIGHT);
    this.side = side;
    setSide();
    resetPos();     
}

private void setSide() { 
    
    if(side.equals("right")) { 
        
        up = KeyEvent.VK_UP;
        down = KeyEvent.VK_DOWN;
        x = GameBoard.WIDTH - WIDTH;
        
    } else if(side.equals("left")) { 
        
        up = KeyEvent.VK_W;
        down = KeyEvent.VK_S;
        
        x = 0;
        
    } else { 
        System.out.println("tato strana neexistuje!");
    }
    
}

public boolean isKey(int keyCode) { 
    
    return up == keyCode || down == keyCode; 
}

public void move() { 
    if(checkHeightCol()) {
        dy = 0;
    
    }
    
    y+=dy;
        
}

private boolean checkHeightCol() {
    return dy + y < 0 || dy + y > GameBoard.HEIGHT - HEIGHT;
}

public void resetPos() {
    y = (GameBoard.HEIGHT - HEIGHT) / 2;
}

public void keyPressed(int keyCode) { 
    
    if(keyCode == up) {
        dy = -SPEED;
    } 
    if (keyCode == down) {
        dy = SPEED;
    }
    
}

public void keyReleased(int keyCode) { 

    if(keyCode == up) {
        dy = 0;
    }
    if (keyCode == down) {
        dy = 0;
    }
}

}

Ball.java:

import java.util.Random;

public class Ball extends Sprite{

public static final int SIZE = 20;
private int xSpeed;
private int ySpeed;
private final int MIN_SPEED = 8;
private final int MAX_SPEED = 25;

public Ball() {
    
    super(SIZE, SIZE);
    
    restart();
    
}

public void start() {
    
    generateRandomDirection();
    

}

private void generateRandomDirection() {
    
    Random r = new Random();
    double randomY = 0.1 + (0.8 - 0.1) * r.nextDouble();
    ySpeed = (int) Math.round(randomY * MIN_SPEED);
    double randomX = Math.sqrt(MIN_SPEED * MIN_SPEED - ySpeed * ySpeed);
    xSpeed = (int) Math.round(randomX);
    
    ySpeed *= (r.nextInt() % 2 == 0) ? 1 : -1;
    xSpeed *= (r.nextInt() % 2 == 0) ? 1 : -1;
}

public void restart() {
    xSpeed = 0;
    ySpeed = 0;
    x = (GameBoard.WIDTH - SIZE) / 2;
    y = (GameBoard.HEIGHT - SIZE) / 2;
            
}

public int move(boolean paddleCollision) {
    int state = 0;

    if(x + xSpeed < 0) {
        
        restart();
        state = 1;
        
    } else if(x + xSpeed > GameBoard.WIDTH - SIZE ) {
        
        restart();
        state = 2;
        
    }else if(checkHeightCollision()) {
        ySpeed *= -1;
        
    } else if(paddleCollision) {
        xSpeed *= -1;
        
    } 
    
    x+=xSpeed;
    y+=ySpeed;
    
    return state;
}

private boolean checkHeightCollision() {
    return y + ySpeed < 0  || y + ySpeed > GameBoard.HEIGHT - SIZE;
}       
}
\$\endgroup\$
1
\$\begingroup\$

Code looks clean, some variables should maybe have a little bit better name, some comments would be nice, overall very good for your first game.

Some points:

\$\endgroup\$
1
  • \$\begingroup\$ Thank you so much for your advice. I will definitely use your tips :) . Have a nice day. \$\endgroup\$ – Stompk Apr 2 at 16:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.