โ˜• My First Java Game ยท Episode 2 of 7 ยท See All Episodes
๐Ÿงฑ Episode 2 ยท Beginner ยท Builds on Episode 1

Smash It!
Brick Breaker

Bounce a ball off your paddle to smash a wall of bricks. You will learn 2D arrays, bounce physics, mouse-free paddle control and lives, the classic arcade formula, in pure Java.

๐Ÿ‘ถ Ages 11+ โฑ๏ธ ~2 Hours โ˜• Java โœ“ Free
๐Ÿ“ Paddle control โšช Ball physics ๐Ÿงฑ 2D arrays ๐Ÿ’ฅ Collision response โค๏ธ Lives system ๐Ÿ† Win/lose states
โญ
0 XP
Level 1
๐Ÿ”ฅ0
Your Progress 0 / 6 steps
1
๐Ÿงฐ
Project Setup & Game Window
Reuse the Episode 1 pattern: JFrame + GamePanel + Timer
Active
๐ŸŽฏ
Goal for this step

Create a fresh project with the game-loop pattern from Episode 1 ready to go.

  • 1Make a new folder BrickBreaker with Main.java and GamePanel.java.
  • 2Main.java is identical to Episode 1, JFrame, add a GamePanel, pack, show. Set the title to "Brick Breaker".
  • 3GamePanel: 700ร—520 pixels, dark background, Timer(16, this), update() + repaint() pattern.
  • 4Add the KeyListener plumbing too (addKeyListener(this), setFocusable(true)), the paddle needs arrows.
  • 5Run it and confirm an empty window appears with no errors.
GamePanel.java (skeleton)
public class GamePanel extends JPanel
        implements ActionListener, KeyListener {
    Timer timer = new Timer(16, this);

    public GamePanel() {
        setPreferredSize(new Dimension(700, 520));
        setBackground(new Color(15, 18, 32));
        addKeyListener(this);
        setFocusable(true);
        timer.start();
    }

    public void actionPerformed(ActionEvent e) { update(); repaint(); }
    void update() {}
}
๐Ÿ’ก
Notice how fast setup is the second time? That JFrame + GamePanel + Timer pattern is your reusable game template for the whole series.
โœ๏ธ
Fill in the Blanks
+15 XP
Our game template has three parts: a window, a GamePanel that extends , and a that drives the loop at ~60 FPS.
๐Ÿง 
Knowledge Check
+15 XP
Which method pair makes up the game loop each tick?
Astart() and stop()
Bupdate() and repaint()
Cmain() and pack()
2
๐Ÿ“
The Paddle
A rectangle at the bottom that slides with the arrow keys
Locked
๐ŸŽฏ
Goal for this step

Draw a paddle that moves smoothly left/right and cannot leave the screen.

  • 1Add paddle variables: padX, plus fixed width 110, height 14, near the bottom (y = 470).
  • 2Move it in update() while an arrow key is held, exactly like the platformer player.
  • 3Clamp it: never let padX go below 0 or beyond 700 - padWidth.
  • 4Draw it as a rounded orange rectangle with fillRoundRect.
GamePanel.java
    int padX = 295, padW = 110, padH = 14;
    boolean leftHeld, rightHeld;

    void update() {
        if (leftHeld)  padX -= 7;
        if (rightHeld) padX += 7;
        padX = Math.max(0, Math.min(700 - padW, padX));
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(new Color(255, 119, 0));
        g.fillRoundRect(padX, 470, padW, padH, 8, 8);
    }
โŒจ๏ธ
Code Challenge
+20 XP
Stop the paddle sliding off the screen. Fill in the clamp:
GamePanel.java
padX = Math.(0, Math.(700 - padW, padX));
๐Ÿ’ก Hint: max(0, โ€ฆ) stops it going below zero; min(rightEdge, โ€ฆ) stops it going past the right side.
๐Ÿง 
Knowledge Check
+15 XP
What does Math.max(0, Math.min(590, padX)) guarantee?
ApadX is always exactly 0 or 590
BpadX always stays between 0 and 590, clamped on screen
CpadX moves faster near the edges
3
โšช
The Bouncing Ball
Velocity, wall bounces and the paddle rebound
Locked
๐ŸŽฏ
Goal for this step

Get a ball bouncing around the arena and rebounding off your paddle.

  • 1Ball variables: position bx, by, velocity bvx, bvy, size 14.
  • 2Each frame add velocity to position. Hitting left/right walls flips bvx; the ceiling flips bvy.
  • 3Paddle hit: if the ball rectangle intersects the paddle while moving down, flip bvy upward.
  • 4Pro touch: change bvx based on where it hits the paddle, edges send it wide, centre sends it straight.
  • 5Draw with fillOval in white.
GamePanel.java
    int bx = 340, by = 300, bs = 14;
    int bvx = 4, bvy = -4;

    void update() {
        // ... paddle code ...
        bx += bvx;  by += bvy;
        if (bx <= 0 || bx + bs >= 700) bvx = -bvx;   // side walls
        if (by <= 0) bvy = -bvy;                     // ceiling

        Rectangle ball = new Rectangle(bx, by, bs, bs);
        Rectangle pad  = new Rectangle(padX, 470, padW, padH);
        if (ball.intersects(pad) && bvy > 0) {
            bvy = -bvy;
            int hit = (bx + bs/2) - (padX + padW/2);
            bvx = hit / 12;              // steer with the paddle!
            if (bvx == 0) bvx = 1;
        }
    }
๐Ÿ’ก
That hit / 12 line is the secret sauce of Breakout, skilled players aim shots by choosing where on the paddle to catch the ball.
โœ๏ธ
Fill in the Blanks
+15 XP
To bounce off a side wall we flip the horizontal velocity: bvx = . We only rebound off the paddle when bvy > , meaning the ball is moving .
๐Ÿง 
Knowledge Check
+15 XP
The ball hits the RIGHT wall. Which value changes?
Abvy flips to negative
Bbvx flips sign so the ball travels left
Cbx resets to 0
4
๐Ÿงฑ
The Brick Wall
Build a grid of bricks with a 2D array
Locked
๐ŸŽฏ
Goal for this step

Fill the top of the screen with a colourful wall of bricks stored in a 2D array.

  • 1Declare boolean[][] bricks = new boolean[5][10];, 5 rows, 10 columns, true = alive.
  • 2In the constructor, set every brick to true with nested for loops.
  • 3Each brick is 64ร—22 pixels with a little gap; row and column convert to pixels: x = col*68 + 12, y = row*26 + 50.
  • 4Draw alive bricks with a different colour per row (use an array of Colors).
  • 5Run it, a proper arcade brick wall!
GamePanel.java
    boolean[][] bricks = new boolean[5][10];
    Color[] rowColors = { new Color(248,113,113), new Color(251,146,60),
        new Color(250,204,21), new Color(74,222,128), new Color(96,165,250) };

    // in constructor:
    for (int r = 0; r < 5; r++)
        for (int c = 0; c < 10; c++)
            bricks[r][c] = true;

    // in paintComponent:
    for (int r = 0; r < 5; r++)
        for (int c = 0; c < 10; c++)
            if (bricks[r][c]) {
                g.setColor(rowColors[r]);
                g.fillRect(c*68 + 12, r*26 + 50, 64, 22);
            }
โŒจ๏ธ
Code Challenge
+20 XP
Complete the nested loop that walks every brick in the grid:
GamePanel.java
for (int r = 0; r < ; r++)
    for (int c = 0; c < ; c++)
        bricks[r][c] = ;
๐Ÿ’ก Hint: The array was declared new boolean[5][10], rows first, then columns. Alive bricks are true.
๐Ÿง 
Knowledge Check
+15 XP
What does bricks[2][7] refer to?
ARow 2, column 7 of the grid (counting from 0)
BThe 27th brick
CA brick that is 2 wide and 7 tall
5
๐Ÿ’ฅ
Smashing Bricks
Ball-brick collision, scoring and the bounce back
Locked
๐ŸŽฏ
Goal for this step

Make the ball destroy bricks it touches, bounce off them, and rack up score.

  • 1In update(), loop over the grid. For each alive brick, build its Rectangle and test ball.intersects(brick).
  • 2On hit: set that cell to false (brick destroyed), add 10 score, flip bvy, and break out so one hit kills one brick.
  • 3Track score in an int and draw it top-left.
  • 4Higher rows can be worth more: score += (5 - r) * 10;, smashing deep pays better!
GamePanel.java (update)
    int score = 0;

    outer:
    for (int r = 0; r < 5; r++)
        for (int c = 0; c < 10; c++)
            if (bricks[r][c]) {
                Rectangle brick = new Rectangle(c*68 + 12, r*26 + 50, 64, 22);
                if (ball.intersects(brick)) {
                    bricks[r][c] = false;
                    score += (5 - r) * 10;
                    bvy = -bvy;
                    break outer;   // one brick per frame
                }
            }
๐Ÿ’ก
break outer; jumps out of BOTH loops at once, a labelled break. Without it the ball could vaporise a whole column in one frame.
โœ๏ธ
Fill in the Blanks
+15 XP
When the ball hits a brick we set bricks[r][c] = , flip , and use a labelled so only one brick dies per frame.
๐Ÿง 
Knowledge Check
+15 XP
Why flip bvy when a brick is destroyed?
ATo slow the ball down
BSo the ball bounces off the brick instead of drilling through the whole wall
CTo reset the ball position
6
โค๏ธ
Lives, Losing & Winning
Three lives, a game-over screen and the victory check
Locked
๐ŸŽฏ
Goal for this step

Finish the game: lose a life when the ball drops, win when every brick is gone.

  • 1Add int lives = 3; and a boolean gameOver = false;.
  • 2If by > 520 (ball fell past the paddle): lives--, reset the ball to the centre. If lives hits 0, gameOver = true.
  • 3Count alive bricks each frame, zero alive means you win.
  • 4When the game is over (won or lost), stop updating and draw a big message + final score.
  • 5Draw lives as โค symbols top-right. Press R to restart if you want a challenge, reset every variable!
GamePanel.java
    int lives = 3;
    boolean gameOver = false, won = false;

    void update() {
        if (gameOver || won) return;    // freeze the game
        // ... all previous code ...

        if (by > 520) {                 // ball lost!
            lives--;
            bx = 340; by = 300; bvx = 4; bvy = -4;
            if (lives == 0) gameOver = true;
        }

        int alive = 0;
        for (int r = 0; r < 5; r++)
            for (int c = 0; c < 10; c++)
                if (bricks[r][c]) alive++;
        if (alive == 0) won = true;
    }
โŒจ๏ธ
Code Challenge
+20 XP
Finish the life-lost logic:
GamePanel.java
if (by > 520) {
    lives;
    bx = 340; by = 300;
    if (lives == ) gameOver = ;
}
๐Ÿ’ก Hint: The decrement operator takes one away. The game ends when no lives remain.
๐Ÿง 
Knowledge Check
+15 XP
Why does update() start with if (gameOver || won) return;?
ATo make the game faster
BTo freeze all movement once the game has ended, while still drawing the final screen
CJava requires a return in every method
๐ŸŽ‰๐Ÿ†๐ŸŽฎโœจ๐ŸŽ‰
Workshop Complete!
Paddle, ball, bricks, lives, you rebuilt an arcade legend from nothing. Episode 3 sends you to space!
0
Total XP
1
Level
0
Best Streak
0%
Accuracy
โ–ถ Episode 3: Space Shooter โ†’
โญ View My Progress & Certificates

This workshop was free and took many hours to build. If it helped you learn something new, consider supporting the project.

☕ Support on Ko-fi