8
\$\begingroup\$

I'm new to java and I have just finished my very first game - Arkanoid. I would appreciate, if anyone could look at this and tell me some advice and tips how can I optimize my code. Thank you. :)

I have 5 classes - Breaker, BlockBreakerPanel, Ball, Paddle, Block. Look:

This is the main classs:

public class Breaker {
    private BlockBreakerPanel panel;
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Breaker b = new Breaker();
        b.show();
    }

    private void show() {
        JFrame frame = new JFrame("Block Breaker");
        frame.setSize(490, 600);
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        this.panel = new BlockBreakerPanel(this);
        frame.add(this.panel);
        frame.setVisible(true);
    }

    public BlockBreakerPanel getPanel() {
        return this.panel;
    }   
}

class BlockBreakerPanel extends JPanel implements KeyListener, ActionListener 

{

    private ArrayList<Blocks> blocks = new ArrayList<>();
    private final Paddle player;
    private final Ball ball;
    private final Breaker game;
    private boolean gameOver;
    private int score;
    private boolean start;
    
    public BlockBreakerPanel(Breaker game) {
        setBackground(Color.BLACK);
        
        for (int j = 0; j < 3; j++) {
            for (int i = 0; i < 8; i++) {
                this.blocks.add(new Blocks(i * 60 + 2, j * 40 + 5, 50, 30));
            }
        }
        
        this.player = new Paddle(game);
        this.ball = new Ball(game);
        this.gameOver = false;
        this.score = 0;
        this.start = false;
        
        Timer t = new Timer(5, this);
        t.start();
        
        addKeyListener(this);
        setFocusable(true);
        this.game = game;
    }
    
    public void addPoint() {
        this.score++;
    }
    
    public void isGameOver() {
       this.gameOver = true;
    }
    
    public ArrayList<Blocks> getBlocks() {
        return this.blocks;
    }
    public Paddle getPlayer() {
        return this.player;
    }

    public void paint(Graphics g) {
        super.paintComponent(g);
        
        this.blocks.forEach((block) -> {
            block.paint(g);
        });
        
        this.player.paint(g);       
        this.ball.paint(g);
        
        if (!this.start) {
            g.setFont(new Font("Calibri", Font.BOLD, 35));
            g.setColor(Color.WHITE);
            g.drawString("Pressed enter to start a game", 20, 300);
        }
        
        g.setFont(new Font("Calibri", Font.BOLD, 20));
        g.setColor(Color.WHITE);
        g.drawString(String.valueOf(this.score), 450, 540);
        
        if (this.gameOver) {
            g.setFont(new Font("Calibri", Font.BOLD, 80));
            g.setColor(Color.WHITE);
            g.drawString("Game Over", 60, 300);
        } else if (this.blocks.isEmpty()) {
            this.gameOver = true;
            g.setFont(new Font("Calibri", Font.BOLD, 80));
            g.setColor(Color.WHITE);
            g.drawString("You won", 80, 300);
        }
    }
    
    private void update() {
        this.ball.move();
        repaint();
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            this.start = true;
        }
        this.player.pressed(e.getKeyCode());
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (!this.gameOver && this.start) {
            this.update();            
        }   
    }
}
class Blocks {

    private final int x;
    private final int y;
    private final int width;
    private final int height;

    public Blocks(int a, int b, int w, int h) {
        this.x = a;
        this.y = b;
        this.width = w;
        this.height = h;
    }
    
    public void paint(Graphics g) {       
        g.setColor(Color.pink);
        g.drawRect(this.x, this.y, this.width, this.height);
        g.fillRect(this.x, this.y, this.width, this.height);
    }

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

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

    public int getWidth() {
        return this.width;
    }

    public int getHeight() {
        return this.height;
    }
}

public class Paddle {

    private int x;
    private final int y;
    private final int width;
    private final int height;
    private final int posun;
    private final Breaker game;

    /**
     *
     * @param game
     */
    public Paddle(Breaker game) {
        this.x = 245 - (60/2);
        this.y = 540;
        this.width = 100;
        this.height = 15;
        this.posun = 10;      
        this.game = game;
    }

    public int getWidth() {
        return this.width;
    }

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

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

    public void paint(Graphics g) {
        g.setColor(Color.CYAN);
        g.drawRect(this.x, this.y, this.width, this.height);
        g.fillRect(this.x, this.y, this.width, this.height);
    }

    void pressed(int keyCode) {
        this.collision();
        if (keyCode == KeyEvent.VK_RIGHT) {
            this.x += this.posun;
        } else if (keyCode == KeyEvent.VK_LEFT) {
            this.x -= this.posun;
        }
    }

    private void collision() {
        if ((this.x + this.width) >= 490) {
            this.x = 490 - this.width;
        } else if (this.x <= 0) {
            this.x = 0;
        }
    }

}

public class Ball {

    private final int DIAMETER = 20;
    private int x;
    private int y;
    private int dx;
    private int dy;
    private final Breaker game;
    
    /**
     *
     * @param game
     */
    public Ball(Breaker game) {
        this.x = 245 - (DIAMETER / 2);
        this.y = 500;
        this.dx = 2;
        this.dy = 2;
        this.game = game;
    }

    void paint(Graphics g) {
        g.setColor(Color.PINK);
        g.drawOval(this.x, this.y, DIAMETER, DIAMETER);
        g.fillOval(this.x, this.y, DIAMETER, DIAMETER);
    }
    
    private void checkCollision() {    
        boolean collision = false;
        if (((this.y+DIAMETER) >= this.game.getPanel().getPlayer().getY()) && ((this.x) >= this.game.getPanel().getPlayer().getX()-2) && ((this.x+DIAMETER) <= (this.game.getPanel().getPlayer().getX()+this.game.getPanel().getPlayer().getWidth()+2))) {
            collision = true;
        } else if ((this.y + DIAMETER) >= 560) {
            this.game.getPanel().isGameOver();
            return;
        }
        
        for (Blocks block : this.game.getPanel().getBlocks()) {
            if ((this.y+5 <= (block.getY() + block.getHeight())) && (this.x+5 >= block.getX()) && ((this.x+DIAMETER-5) <= block.getX()+block.getWidth())) {
                this.game.getPanel().getBlocks().remove(block);
                collision = true;
                this.game.getPanel().addPoint();
                break;
            }
        }
                
        if (collision) {
            this.dy = - this.dy;
        }
    }
    public void move() {
        if (this.x <= 0 || this.x >= (460 + DIAMETER)) {
            this.dx = -this.dx;
        } else if (this.y <= 0 || this.y >= (540 + DIAMETER)) {
            this.dy = -this.dy;
        }
        
        this.checkCollision();
               
        this.x += this.dx;
        this.y += this.dy;
    }
    
}
\$\endgroup\$
1
1
\$\begingroup\$

Nice, one of my favorite games.

What you got now is all the responsibilities of a program mixed together into same classes merrily violating the single responsibility principle. Study the MVC model. Then start by separating your game physics into their own set of classes and the graphical representation to another set. Put the key and action listeners into their own classes and create a main class that connects all the components together.

Move all the magic numbers (such as screen size) into variables so that you can change them easily. Make the object sizes relative to the screen size so that you can scale the game for different screen resolutions. Take into account that not all screens have the same width to height aspect ratio.

Avoid arbitrary abbreviations like posun. What is a posun?

\$\endgroup\$

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.