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.
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.
Create a fresh project with the game-loop pattern from Episode 1 ready to go.
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() {}
}
Draw a paddle that moves smoothly left/right and cannot leave the screen.
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);
}
padX = Math.(0, Math.(700 - padW, padX));
Get a ball bouncing around the arena and rebounding off your paddle.
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;
}
}
Fill the top of the screen with a colourful wall of bricks stored in a 2D array.
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);
}
for (int r = 0; r < ; r++)
for (int c = 0; c < ; c++)
bricks[r][c] = ;
Make the ball destroy bricks it touches, bounce off them, and rack up score.
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
}
}
Finish the game: lose a life when the ball drops, win when every brick is gone.
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;
}
if (by > 520) {
lives;
bx = 340; by = 300;
if (lives == ) gameOver = ;
}