โš™๏ธ My First C++ Game ยท Episode 3 of 7 ยท See All Episodes
๐Ÿงฑ Episode 3 ยท Improver ยท Classes & Vectors

Brick by Brick!
Breakout in C++

Breakout rebuilt the C++ way: a Brick class, std::vector, constructors, and collision that knows which side it hit. Your third Breakout, but your first with real object-oriented C++.

๐Ÿ‘ถ Ages 12+ โฑ๏ธ ~2 Hours โš™๏ธ C++ & SFML โœ“ Free
๐Ÿ—๏ธ C++ classes ๐Ÿ“š std::vector ๐Ÿงฑ Brick objects ๐Ÿ’ฅ Side detection โค๏ธ Lives ๐Ÿ† Win state
โญ
0 XP
Level 1
๐Ÿ”ฅ0
Your Progress 0 / 6 steps
1
๐Ÿ—๏ธ
Setup & the Paddle
Project skeleton plus a mouse-driven paddle
Active
๐ŸŽฏ
Goal for this step

Set up 700ร—520 Breakout with a paddle that follows the mouse.

  • 1New breakout.cpp with the standard skeleton (Episode 1 muscle memory).
  • 2New input style: the paddle follows the MOUSE, sf::Mouse::getPosition(window).x, centred and clamped.
  • 3Mouse control makes Breakout feel amazing, instant, precise.
  • 4Draw the paddle orange at y 480.
breakout.cpp
sf::RectangleShape paddle(sf::Vector2f(110, 14));
paddle.setFillColor(sf::Color(255, 119, 0));

// in the loop:
float mx = (float)sf::Mouse::getPosition(window).x;
float px = mx - 55;                       // centre on cursor
px = std::max(0.f, std::min(590.f, px));  // clamp
paddle.setPosition(px, 480);
โœ๏ธ
Fill in the Blanks
+15 XP
The paddle centres on the cursor by subtracting half its (55). The clamp maximum is 700 โˆ’ 110 = .
๐Ÿง 
Knowledge Check
+15 XP
Why does mouse control suit Breakout better than keys?
AKeyboards break easily
BPositional control, the paddle goes exactly where you point, enabling precise catches and aimed spin
CSFML has no key input
2
๐Ÿงฑ
The Brick Class
Your first C++ class with a constructor
Locked
๐ŸŽฏ
Goal for this step

Write a Brick class and build the wall in a std::vector.

  • 1A class bundles data AND behaviour: shape, points, alive, plus a constructor to set up each brick.
  • 2The wall is std::vector<Brick>, filled by nested loops calling the constructor.
  • 3vector::emplace_back(r, c) constructs the brick right inside the vector, modern and fast.
  • 4Colour by row inside the constructor: the object sets ITSELF up. That is encapsulation, C++ style.
breakout.cpp
class Brick {
public:
    sf::RectangleShape shape;
    int points;
    bool alive = true;

    Brick(int row, int col) {
        shape.setSize(sf::Vector2f(64, 22));
        shape.setPosition(col * 68.f + 12, row * 26.f + 50);
        points = (5 - row) * 10;
        static const sf::Color colours[5] = {
            {248,113,113}, {251,146,60}, {250,204,21},
            {74,222,128}, {96,165,250} };
        shape.setFillColor(colours[row]);
    }
};

std::vector<Brick> bricks;
for (int r = 0; r < 5; r++)
    for (int c = 0; c < 10; c++)
        bricks.emplace_back(r, c);
โŒจ๏ธ
Code Challenge
+20 XP
Build the wall with the constructor:
breakout.cpp
for (int r = 0; r < 5; r++)
    for (int c = 0; c < 10; c++)
        bricks.(r, );
๐Ÿ’ก Hint: The modern vector method constructs in place, passing the constructor arguments (row, col).
๐Ÿง 
Knowledge Check
+15 XP
What does the Brick constructor achieve?
AIt draws the brick
BEvery brick configures ITSELF (position, colour, points) from just (row, col), no outside setup code
CIt deletes old bricks
3
โšช
Ball Physics
Delta-time ball with wall and paddle bounces
Locked
๐ŸŽฏ
Goal for this step

A dt-driven ball that bounces off walls and takes spin from the paddle.

  • 1Ball + velocity in px/sec (Episode 1 skill): 260, -260 to start.
  • 2Walls flip the matching velocity; floor is death (later).
  • 3Paddle rebound with mouse-aimed spin: offset from paddle centre ร— 4 becomes bvx.
  • 4Clamp total bvx to ยฑ500 so spin cannot go crazy.
breakout.cpp
sf::CircleShape ball(7);
ball.setPosition(343, 300);
float bvx = 260.f, bvy = -260.f;

ball.move(bvx * dt, bvy * dt);
auto p = ball.getPosition();
if (p.x <= 0 || p.x + 14 >= 700) bvx = -bvx;
if (p.y <= 0) bvy = -bvy;

if (ball.getGlobalBounds().intersects(paddle.getGlobalBounds()) && bvy > 0) {
    bvy = -bvy;
    float offset = (p.x + 7) - (px + 55);
    bvx = std::max(-500.f, std::min(500.f, offset * 4.f));
}
โœ๏ธ
Fill in the Blanks
+15 XP
The rebound spin is the offset between ball centre and paddle centre times , clamped to ยฑ px/sec.
๐Ÿง 
Knowledge Check
+15 XP
The ball uses px/second velocities while Snake used grid ticks. When do you pick each?
ATicks are always better
BContinuous motion โ†’ dt velocities; cell-based games โ†’ grid ticks. Match the technique to the game
Cdt is only for C++
4
๐Ÿ’ฅ
Smart Brick Collision
Detect WHICH side you hit for correct bounces
Locked
๐ŸŽฏ
Goal for this step

Bounce correctly off brick sides, not just up/down.

  • 1Naive Breakout always flips bvy, hitting a brickโ€™s SIDE then looks wrong. We compare overlap depths.
  • 2On intersect, compute horizontal and vertical overlap; the SMALLER overlap is the entry side.
  • 3Shallow horizontal overlap โ†’ side hit โ†’ flip bvx. Otherwise flip bvy.
  • 4Mark the brick dead, add points, break out of the loop.
breakout.cpp
for (auto& brick : bricks) {
    if (!brick.alive) continue;
    sf::FloatRect bb = ball.getGlobalBounds();
    sf::FloatRect kb = brick.shape.getGlobalBounds();
    if (bb.intersects(kb)) {
        float overlapX = std::min(bb.left + bb.width,  kb.left + kb.width)
                       - std::max(bb.left, kb.left);
        float overlapY = std::min(bb.top + bb.height, kb.top + kb.height)
                       - std::max(bb.top, kb.top);
        if (overlapX < overlapY) bvx = -bvx;   // side hit
        else                     bvy = -bvy;   // top/bottom hit
        brick.alive = false;
        score += brick.points;
        break;
    }
}
๐Ÿ’ก
Overlap-depth side detection is the same technique 2D engines use under the hood. You just wrote engine code.
โŒจ๏ธ
Code Challenge
+20 XP
Bounce off the correct side:
breakout.cpp
if (overlapX < overlapY)  = -bvx;   // came in from the side
else                      = -bvy;
brick.alive = ;
๐Ÿ’ก Hint: A shallow horizontal overlap means a side entry, flipping horizontal velocity. The brick then stops existing.
๐Ÿง 
Knowledge Check
+15 XP
The smaller overlap tells you the entry side becauseโ€ฆ
ASmall numbers are sides
BThe ball has barely penetrated on the axis it entered from, depth of penetration reveals direction of travel
CSFML sorts overlaps
5
๐Ÿงน
Alive Flags vs Erasing
Two cleanup strategies and the erase-remove idiom
Locked
๐ŸŽฏ
Goal for this step

Skip dead bricks efficiently and learn the famous C++ idiom.

  • 1We used alive = false and skip dead bricks when drawing/colliding, simple and fast for a fixed wall.
  • 2The alternative is really deleting: the erase-remove idiom, worth knowing because ALL serious C++ uses it.
  • 3Win check with the flag approach: std::none_of over the vector asking if any brick is alive.
  • 4Draw only living bricks.
breakout.cpp
#include <algorithm>

// erase-remove (the famous idiom, for reference):
bricks.erase(
    std::remove_if(bricks.begin(), bricks.end(),
        [](const Brick& b){ return !b.alive; }),
    bricks.end());

// win check with flags:
bool won = std::none_of(bricks.begin(), bricks.end(),
    [](const Brick& b){ return b.alive; });
โœ๏ธ
Fill in the Blanks
+15 XP
The famous C++ deletion pattern is the erase- idiom. Our simpler approach keeps bricks but marks them with an flag.
๐Ÿง 
Knowledge Check
+15 XP
Why can we get away with alive-flags here instead of erasing?
AErasing is illegal on vectors
BThe wall is small and fixed (50 bricks), skipping dead ones costs nothing. Erasing matters when lists grow unbounded
CFlags draw faster
6
โค๏ธ
Lives, Loss & Victory
The complete game loop with all three endings
Locked
๐ŸŽฏ
Goal for this step

Finish with lives, a losing screen, a winning screen, and restart.

  • 1Ball past y 520: life lost, re-serve from centre; 0 lives โ†’ LOSE state.
  • 2All bricks dead โ†’ WIN state.
  • 3Freeze physics in end states; draw the message + final score; R rebuilds the wall (clear the vector, refill with the nested loops) and resets everything.
  • 4Three languages, three Breakouts, three times faster each time. THAT is learning to program.
breakout.cpp
int lives = 3;
enum State { PLAY, WIN, LOSE };
State state = PLAY;

if (p.y > 520) {
    lives--;
    ball.setPosition(343, 300);
    bvx = 260; bvy = -260;
    if (lives == 0) state = LOSE;
}
if (won) state = WIN;

// restart on R:
bricks.clear();
for (int r = 0; r < 5; r++)
    for (int c = 0; c < 10; c++)
        bricks.emplace_back(r, c);
lives = 3; score = 0; state = PLAY;
โŒจ๏ธ
Code Challenge
+20 XP
Use a proper C++ enum for the game state:
breakout.cpp
enum State { PLAY, , LOSE };
State state = ;
if (lives == 0) state = ;
๐Ÿ’ก Hint: Three named states; the game starts in play mode; zero lives means the losing state.
๐Ÿง 
Knowledge Check
+15 XP
An enum beats a String state (like Java Ep 4 used) becauseโ€ฆ
AEnums are colourful
BThe compiler catches typos, sate = PLYA will not compile, while "PLYA" would silently break a string version
CEnums are required by SFML
๐ŸŽ‰๐Ÿ†๐ŸŽฎโœจ๐ŸŽ‰
Workshop Complete!
Classes, vectors, erase-remove, Breakout in proper object-oriented C++. Episode 4 brings gravity: the platformer!
0
Total XP
1
Level
0
Best Streak
0%
Accuracy
โ–ถ Episode 4: Simple Platformer โ†’
โญ 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