Students: i240053 Β· i240061 Β· i240054
Language: C++
Graphics & Audio Library: SFML 2.5
Build System: CMake (or direct Makefile)
- Game Overview
- Project Structure
- OOP Concepts Used
- Dependencies
- How to Build & Run
- Fix Required Before Running
- Menu Navigation
- Game Controls
- Gameplay Mechanics
- Obstacles
- Power-Ups
- Scoring System
- Class Descriptions
- File Descriptions
- Common Errors & Fixes
This is a Subway Surfers-inspired endless runner built with C++ and SFML. The player runs across 3 lanes, dodges incoming obstacles (trains, barriers, cones, fences, policemen), collects coins, and picks up power-ups to survive as long as possible. The game gets faster every 10 seconds. Your score is saved to a leaderboard.
OOP-project/
βββ main.cpp β Entry point (calls GameEngine)
βββ CMakeLists.txt β CMake build script
βββ arial.ttf β Font file
βββ assets/
β βββ subway_music.ogg β Background music (used by game)
β βββ subway_music.wav β Alternate audio format
β βββ subway_music_fixed.wav β Fixed audio version
βββ Images/
β βββ bg.png β Menu/game background
β βββ bgg.png β Start screen background
β βββ player.png β Player sprite
β βββ train.png β Train obstacle sprite
β βββ barrier.png β Barrier obstacle sprite
β βββ cone.png β Cone obstacle sprite
β βββ fence.png β Fence obstacle sprite
β βββ policeman.png β Policeman obstacle sprite
β βββ coin.png β Coin sprite
β βββ magnet.png β Magnet power-up sprite
β βββ jetpack.png β Jetpack power-up sprite
β βββ shield.png β Shield power-up sprite
β βββ doublecoin.png β Double Coin power-up sprite
β βββ gameover.png β Game over screen image
βββ PROJECT/
β βββ GameList.h β Generic dynamic list (template)
β βββ GameEngine.h / .cpp β Main game loop & state manager
β βββ Player.h / .cpp β Player class
β βββ Obstacle.h / .cpp β Obstacle base + child classes
β βββ PowerUp.h / .cpp β PowerUp base + child classes
β βββ Coin.h / .cpp β Coin class
β βββ ScoreManager.h / .cpp β Score & high score management
β βββ TrackManager.h / .cpp β Track, spawning, speed control
β βββ Makefile β Alternative direct make build
βββ build/
βββ SFMLRunner β Pre-compiled Linux executable
βββ highscore.txt β Saved high score (auto-updated)
| Concept | Where Used |
|---|---|
| Classes & Objects | Player, GameEngine, Coin, ScoreManager, TrackManager |
| Inheritance | Train, Barrier, Cone, Fence, Policeman β all inherit from Obstacle; MagnetPower, JetpackPower, ShieldPower, DoubleCoinPower β all inherit from PowerUp |
| Polymorphism | canJumpOver(), canSlideUnder(), applyEffect() are virtual and overridden in each child class |
| Encapsulation | All class members are private/protected; accessed through public getters/setters |
| Templates | GameList<T> is a generic dynamic array used for obstacles, coins, and power-ups |
| Dynamic Memory | GameList uses new/delete and auto-resizes (doubles capacity) |
| Enums | GameState (START_SCREEN, MENU, NAME_INPUT, PLAYING, LEADERBOARD, INSTRUCTIONS, GAME_OVER) and PlayerState (RUNNING, JUMPING, SLIDING) |
| File I/O | ScoreManager reads/writes high score from highscore.txt |
Ubuntu/Debian Linux:
sudo apt-get update
sudo apt-get install libsfml-devFedora/RHEL:
sudo dnf install SFML-develWindows: Download MinGW version from https://www.sfml-dev.org/download.php
macOS:
brew install sfmlsudo apt-get install cmakesudo apt-get install g++
β οΈ CRITICAL: The code has hardcoded absolute paths pointing to the original developer's computer (/home/maham/Downloads/OOP-project/...). These will cause crashes on any other machine. You must fix them before building.
1. PROJECT/GameEngine.cpp β find and replace these 3 lines:
// ORIGINAL (broken on your PC):
font.loadFromFile("/home/maham/Downloads/OOP-project/arial.ttf")
startBgTexture.loadFromFile("/home/maham/Downloads/OOP-project/Images/bgg.png")
menuBgTexture.loadFromFile("/home/maham/Downloads/OOP-project/Images/bg.png")
backgroundMusic.openFromFile("/home/maham/Downloads/OOP-project/assets/subway_music.ogg")
// FIXED (use relative paths):
font.loadFromFile("arial.ttf")
startBgTexture.loadFromFile("Images/bgg.png")
menuBgTexture.loadFromFile("Images/bg.png")
backgroundMusic.openFromFile("assets/subway_music.ogg")2. PROJECT/Player.cpp β find and replace:
// ORIGINAL (broken):
playerTexture.loadFromFile("/home/maham/Downloads/OOP-project/Images/player.png")
// FIXED:
playerTexture.loadFromFile("Images/player.png")3. PROJECT/Obstacle.cpp β similarly fix any hardcoded image paths for train.png, barrier.png, cone.png, fence.png, policeman.png to use Images/ prefix.
4. PROJECT/PowerUp.cpp and PROJECT/Coin.cpp β fix any hardcoded paths for magnet.png, jetpack.png, shield.png, doublecoin.png, coin.png.
After fixing paths, the game must always be run from the OOP-project/ folder so that Images/, assets/, and arial.ttf are found correctly.
# Step 1: Go to project root
cd OOP-project
# Step 2: Create build directory
mkdir build && cd build
# Step 3: Configure
cmake ..
# Step 4: Compile
make
# Step 5: Run (go back to OOP-project/ first so paths work)
cd ..
./build/SFMLRunner# Go into the PROJECT folder
cd OOP-project/PROJECT
# Compile
make
# Run (go back to OOP-project/ first)
cd ..
./PROJECT/PROJECTIf you are on Linux and don't want to recompile:
cd OOP-project
chmod +x build/SFMLRunner
./build/SFMLRunnerNote: Still requires SFML installed on your system, and paths must be fixed first.
- Install Code::Blocks with MinGW from http://www.codeblocks.org/
- Download SFML 2.5 for MinGW from https://www.sfml-dev.org/
- Create a new C++ project and add all
.cppfiles fromPROJECT/plusmain.cpp - In Project β Build Options β Linker Settings, add:
sfml-graphics,sfml-window,sfml-system,sfml-audio
- Add SFML include and lib paths in Search Directories
- Fix the hardcoded paths (see above)
- Build and run β make sure
Images/,assets/,arial.ttfare in the same folder as the.exe
(Background splash image)
PRESS ENTER TO START
Press ESC to Exit
| Key | Action |
|---|---|
Enter |
Go to Main Menu |
Esc |
Exit game |
SUBWAY SURFERS
1- Start Game
2- Continue
3- LeaderBoard
4- Instructions
5- Exit
| Key | Action |
|---|---|
1 |
Start new game (asks for name) |
2 |
Continue (asks for name if not set; else resumes) |
3 |
View Leaderboard |
4 |
View Instructions |
5 |
Exit game |
- Type your name (up to 20 characters)
- A blinking cursor shows your current input
- If you press Enter with no name, it defaults to "Player"
| Key | Action |
|---|---|
| Any letter/number | Type your name |
Backspace |
Delete last character |
Enter |
Confirm name and start |
Esc |
Go back to menu |
Shows:
- Current player name
- Current score
- All-time high score + who set it
| Key | Action |
|---|---|
Space or Esc |
Return to menu |
A/D - Left/Right
W/S - Jump/Slide
| Key | Action |
|---|---|
Space or Esc |
Return to menu |
Shows:
- GAME OVER
- Player name
- Final score
- High score + holder name
| Key | Action |
|---|---|
Space or Esc |
Return to menu |
| Key | Action |
|---|---|
A |
Move player to the left lane |
D |
Move player to the right lane |
W |
Jump over obstacles |
S |
Slide under obstacles |
Esc |
Pause / return to menu |
3 Lanes: Left (lane 0) Β· Center (lane 1, default) Β· Right (lane 2)
The screen is divided into 3 vertical lanes. The player starts in the center lane. Switching lanes is instant (no sliding animation between lanes).
- Game starts at a base speed
- Every 10 seconds, track speed increases by +20 units
- This makes obstacles spawn faster and move down the screen quicker
- Every 1 second survived = +10 points automatically added
- Each obstacle is checked per-frame against the player's bounding box
- Collision is only checked when the player and obstacle are in the same lane
- Depending on the obstacle type, jumping or sliding may avoid it (see Obstacles below)
The background scrolls downward to create the illusion of forward movement. Scroll speed is tied to the current track speed.
All obstacles inherit from the base Obstacle class and scroll downward at the current track speed.
| Obstacle | Image | Can Jump Over | Can Slide Under | Notes |
|---|---|---|---|---|
| Train | train.png | No | Yes | Deadly if you run into it; must slide under |
| Barrier | barrier.png | Yes | No | Jump over it |
| Cone | cone.png | Yes | No | Jump over it |
| Fence | fence.png | No | Yes | Slide under it |
| Policeman | policeman.png | Yes | No | Jump over it |
If you have a Shield active β hitting an obstacle destroys the obstacle instead of ending the game (one hit protection).
Power-ups spawn randomly on the track and move downward. Collect by running into them. Each grants +100 bonus points on pickup.
| Power-Up | Duration | Effect |
|---|---|---|
| Magnet π§² | 8 seconds | Automatically collects nearby coins within 100px range (no need to be in same lane) |
| Jetpack π | 6 seconds | Reduces gravity by 50% while jumping β makes jumps float higher and longer |
| Shield π‘οΈ | 10 seconds | Absorbs one obstacle hit β obstacle is destroyed instead of game over |
| Double Coin π° | 10 seconds | All coins collected give 2Γ points (100 instead of 50) |
Visual Indicators: Each active power-up shows a colored circle around the player:
- Shield β Blue circle
- Magnet β Red circle
- Jetpack β Orange circle
- Double Coin β Yellow circle
| Event | Points |
|---|---|
| Surviving 1 second | +10 |
| Collecting a coin (normal) | +50 |
| Collecting a coin (Double Coin active) | +100 |
| Collecting a power-up | +100 |
| Magnet auto-collecting a coin | +50 (or +100 with Double Coin) |
High Score is saved to build/highscore.txt and persists between sessions. The file stores the score and the player name who set it.
The central controller. Owns all other objects. Manages:
- The SFML render window (800Γ600)
- Game state machine (
START_SCREEN β MENU β NAME_INPUT β PLAYING β GAME_OVERetc.) - The main game loop:
handleInput()βupdate()βrender() - Background music (loops
subway_music.ogg) - All render functions per state
Manages player position, movement, state, and power-up effects.
- 3 lanes at fixed X positions (140, 410, 680)
- States:
RUNNING,JUMPING,SLIDING - Gravity = 1200 units/sΒ² (halved with Jetpack)
- Jump velocity = -600 units/s
- Sliding squishes the player sprite vertically (scale 0.35 β 0.2)
Abstract base for all obstacles. Has lane, position, speed, and sprite.
Child classes: Train, Barrier, Cone, Fence, Policeman
Each overrides canJumpOver() and canSlideUnder().
Abstract base for all power-ups. Has pure virtual applyEffect(Player*).
Child classes: MagnetPower, JetpackPower, ShieldPower, DoubleCoinPower
A simple collectible that scrolls downward. Has rotation animation.
Worth 50 points normally, 100 with Double Coin active.
Manages all spawning and updating of obstacles, coins, and power-ups using GameList<T>.
Controls current speed and calls increaseSpeed() every 10 seconds.
Also handles background rendering with scroll offset.
Tracks current score and all-time high score.
Reads/writes highscore.txt. Stores player names (up to 50 chars).
A custom dynamic array (like a simplified vector).
Starts with capacity 10, doubles when full.
Used for GameList<Obstacle>, GameList<Coin>, GameList<PowerUp>.
| File | Purpose |
|---|---|
main.cpp |
Entry point β creates GameEngine and calls run() |
CMakeLists.txt |
CMake build script β links SFML, sets C++17, includes PROJECT/ headers |
PROJECT/Makefile |
Alternative build β compiles with g++ -std=c++11 and links SFML |
PROJECT/GameList.h |
Template dynamic array (no .cpp needed β fully in header) |
PROJECT/GameEngine.h/.cpp |
Main game controller, state machine, rendering |
PROJECT/Player.h/.cpp |
Player movement, jump/slide, power-up state |
PROJECT/Obstacle.h/.cpp |
Obstacle hierarchy (Train, Barrier, Cone, Fence, Policeman) |
PROJECT/PowerUp.h/.cpp |
PowerUp hierarchy (Magnet, Jetpack, Shield, DoubleCoin) |
PROJECT/Coin.h/.cpp |
Collectible coins |
PROJECT/ScoreManager.h/.cpp |
Score tracking and file-based persistence |
PROJECT/TrackManager.h/.cpp |
Spawning, speed control, background scrolling |
arial.ttf |
Font for all in-game text |
assets/subway_music.ogg |
Background music (looping) |
Images/*.png |
All game sprites |
build/highscore.txt |
Saved high score (auto-created/updated) |
| Error | Cause | Fix |
|---|---|---|
| Game crashes on startup | Hardcoded /home/maham/ paths |
Fix all paths to relative (see Fix section above) |
ERROR: Could not load bgg.png |
Wrong working directory | Run the game from OOP-project/ folder, not from inside build/ |
SFML/Graphics.hpp: No such file |
SFML not installed | sudo apt-get install libsfml-dev |
cmake: command not found |
CMake missing | sudo apt-get install cmake |
make: command not found |
Build tools missing | sudo apt-get install build-essential |
| Font shows blank / no text | arial.ttf not found |
Copy arial.ttf to the working directory you run from |
| Music doesn't play | .ogg file path wrong |
Ensure assets/subway_music.ogg exists relative to run location |
SFMLRunner won't run on Windows |
Compiled for Linux | Recompile using Code::Blocks + MinGW + SFML for Windows |
| Score not saving | highscore.txt write permission |
Ensure build/ folder is writable; or run with proper permissions |
# 1. Extract
unzip subway_surfer.zip && cd OOP-project
# 2. Install SFML
sudo apt-get install libsfml-dev cmake g++
# 3. Fix hardcoded paths in:
# PROJECT/GameEngine.cpp (4 paths)
# PROJECT/Player.cpp (1 path)
# PROJECT/Obstacle.cpp (image paths)
# PROJECT/PowerUp.cpp (image paths)
# PROJECT/Coin.cpp (image path)
# Change /home/maham/Downloads/OOP-project/ β (nothing, just relative path)
# 4. Build
mkdir -p build && cd build
cmake ..
make
cd ..
# 5. Run from OOP-project/ folder
./build/SFMLRunnerREADME generated from full source code analysis of all .h, .cpp, CMakeLists.txt, and Makefile files.