An enhanced Pong clone for macOS, built with modern C++17 and the latest SDL3 / SDL3_ttf libraries. Features smooth ball physics, AI-controlled opponent with predictive trajectory tracking, adjustable difficulty levels, and on-screen scoring.
- Smooth Ball Physics — Subpixel movement using
SDL_FRectfor precise positioning - AI Opponent — Predictive trajectory tracking with bounce simulation
- Adjustable Difficulty — Easy, Medium, and Hard modes with different AI behaviors
- Dynamic Gameplay — Ball speed increases on paddle hits, angle varies by hit position
- Score Display — Real-time score rendering with SDL3_ttf
- Classic Visuals — Dashed center line, clean black & white aesthetic
| Key | Action |
|---|---|
W / ↑ |
Move paddle up |
S / ↓ |
Move paddle down |
1 |
Set difficulty to Easy |
2 |
Set difficulty to Medium |
3 |
Set difficulty to Hard |
ESC |
Quit game |
Pong/
├── main.cpp # Entry point - creates and runs Game instance
├── src/
│ ├── Game.h # Game class interface & Difficulty enum
│ ├── Game.cpp # Full game implementation
│ ├── Ball.h # Ball struct definition
│ └── Paddle.h # Paddle struct definition
├── CMakeLists.txt # CMake build configuration
├── conanfile.py # Conan dependency manager config
├── conan_provider.cmake # Conan CMake integration
└── README.md
Ball (src/Ball.h)
struct Ball {
SDL_FRect rect; // Position (x, y) and size (w, h)
float vx; // Velocity in x direction (px/sec)
float vy; // Velocity in y direction (px/sec)
};Paddle (src/Paddle.h)
struct Paddle {
SDL_FRect rect; // Position and size
float speed; // Movement speed (px/sec)
};Difficulty Enum (src/Game.h)
enum class Difficulty { Easy, Medium, Hard };Game Class (src/Game.h)
Main game manager handling initialization, game loop, rendering, and cleanup.
| Method | Description |
|---|---|
Init() |
Initialize SDL3, TTF, window, renderer, and game objects |
Run() |
Main game loop - events, physics, AI, rendering |
SetDifficulty() |
Adjust AI paddle speed and behavior |
ResetBall() |
Reset ball to center with random direction |
UpdateAI() |
AI paddle movement with trajectory prediction |
PredictBallImpactX() |
Calculate where ball will intersect paddle plane |
UpdateScoreTexture() |
Render score text to texture |
The AI opponent uses predictive trajectory tracking rather than simply following the ball's current position.
- Trajectory Prediction — Calculates where the ball will be when it reaches the AI paddle's x-coordinate
- Bounce Simulation — Uses modular arithmetic to simulate wall reflections:
reflectedY = mod > h ? (2 * h - mod) : mod; - Difficulty Scaling — AI behavior varies by difficulty level:
| Difficulty | AI Speed | Reaction | Accuracy |
|---|---|---|---|
| Easy | 400 px/s | Waits until ball passes midfield | ±20px random offset |
| Medium | 640 px/s | Reacts at 30% field distance | ±10px random offset |
| Hard | 900 px/s | Immediate reaction | Perfect tracking |
- Base Speed: 520 px/sec
- Max Speed: 1100 px/sec
- Speed Increase: 5% on each paddle hit
- Angle Range: ±25° initial launch angle
The ball's outgoing angle depends on where it hits the paddle:
- Center hit → Shallow angle
- Edge hit → Steep angle (up to ~55°)
float impactDist = (ballCenter - paddleCenter);
ball->vy += impactDist * 5.0f; // Angle adjustment factorSimple AABB (Axis-Aligned Bounding Box) collision:
if (bl.x < pl.x + pl.w && bl.x + bl.w > pl.x &&
bl.y < pl.y + pl.h && bl.y + bl.h > pl.y && ball->vx < 0)| Tool | Version | Installation |
|---|---|---|
| CMake | 3.16+ | cmake.org |
| Conan | 2.x | pip install conan |
| C++17 Compiler | — | See platform-specific below |
- Xcode Command Line Tools or full Xcode
- AppleClang (included with Xcode)
# Install Xcode CLI tools (if not already installed)
xcode-select --install
# Install Conan via Homebrew (recommended)
brew install conan
# Or via pip
pip3 install conan# Clone the repository
git clone <repo-url>
cd Pong
# Install dependencies (first time only)
conan install . --build=missing
# Configure with CMake
cmake --preset conan-release
# Build
cmake --build --preset conan-release
# Run the game
./build/build/Release/Pong- Visual Studio 2019/2022 with "Desktop development with C++" workload
- Or MinGW-w64 with GCC 8+
# Install Conan (via pip or standalone installer)
pip install conan
# Clone and enter directory
git clone <repo-url>
cd Pong
# Detect default profile (first time only)
conan profile detect
# Install dependencies
conan install . --build=missing -s build_type=Release
# Configure with CMake (Visual Studio generator)
cmake --preset conan-default
# Build
cmake --build --preset conan-release --config Release
# Run the game
.\build\build\Release\Pong.exe# Install MSYS2 from https://www.msys2.org/
# Open MSYS2 MinGW64 terminal
# Install required packages
pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc
# Install Conan
pip install conan
# Configure Conan for MinGW
conan profile detect
# Edit ~/.conan2/profiles/default and set:
# compiler=gcc
# compiler.version=<your-version>
# Build steps same as macOS
conan install . --build=missing
cmake --preset conan-release
cmake --build --preset conan-release
# Run
./build/build/Release/Pong.exe# Ubuntu/Debian - install dependencies
sudo apt update
sudo apt install build-essential cmake libgl1-mesa-dev
# Install Conan
pip3 install conan
# Build (same as macOS)
conan install . --build=missing
cmake --preset conan-release
cmake --build --preset conan-release
# Run
./build/build/Release/Pong- Open the project folder
- CLion auto-detects CMake
- Configure Conan plugin or run
conan install . --build=missingin terminal - Select
conan-releasepreset in CMake settings - Build & Run
- Install extensions: CMake Tools, C/C++
- Run
conan install . --build=missingin terminal - Select kit and preset via CMake Tools
- Press
F5to build and run
- Run
conan install . --build=missingin Developer PowerShell - Open folder (CMake project support)
- Select
conan-releaseconfiguration - Build with
Ctrl+Shift+B
Managed via Conan:
| Package | Version | Purpose |
|---|---|---|
sdl |
3.2.20 | Windowing, rendering, input |
sdl_ttf |
3.2.2 | TrueType font rendering |
SDL3_ttf also brings in: Freetype, HarfBuzz, libpng, zlib, brotli
| Constant | Value | Description |
|---|---|---|
| Window Size | 800×600 | Default window dimensions |
| Ball Size | 16×16 px | Square ball |
| Paddle Size | 18×120 px | Paddle dimensions |
| Player Speed | 720 px/sec | Left paddle movement speed |
| Font Size | 48 px | Score text size |
This project uses SDL3 (not SDL2), which includes several API changes:
- Functions return
boolinstead ofintfor success/failure - Event types use
SDL_EVENT_*prefix (e.g.,SDL_EVENT_QUIT) SDL_DestroySurface()replacesSDL_FreeSurface()SDL_RenderTexture()replacesSDL_RenderCopy()SDL_FRectused for subpixel precision rendering- Must include
<SDL3/SDL_main.h>separately
Open source - feel free to modify and extend!
- SDL Wiki for comprehensive documentation
- Lazy Foo' Productions for SDL3 tutorials
- Hack Club for project inspiration