Skip to content

About

A C++17 tick-based railway simulation — deterministic switch logic, distance-based collision priority, and an SFML-rendered grid with signals, weather, and emergency halts.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

33 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Switchback Rails

A C++17 railway simulation using fixed-size arrays and global state declared in core/simulation_state.h. Core simulation logic has zero SFML dependency and compiles/runs standalone from console/main_console.cpp.

Install dependencies

Windows (MSYS2 MinGW64 shell):

pacman -Syu
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-make mingw-w64-x86_64-sfml

Linux:

bash libraries.sh

Build and run

mingw32-make clean      # (or `make clean` on Linux)
mingw32-make            # (or `make`)
./switchback_rails.exe data/levels/easy_level.lvl   # graphical (SFML)

Console-only build (no graphics, useful for quick logic testing):

mingw32-make console
./switchback_console.exe data/levels/easy_level.lvl

The Makefile links against -lsfml-graphics -lsfml-window -lsfml-system, and uses -std=c++17. This project's SFML code targets SFML 3's event API (sf::Event::is<...>() / getIf<...>()), which is what MSYS2's mingw-w64-x86_64-sfml package currently installs on Windows.

Linux note: apt-get install libsfml-dev on most current distros installs SFML 2.6, which uses the older pollEvent(sf::Event&) API and will not compile sfml/app.cpp as-is. Linux users should either build SFML 3 from source, or use the console-only build below, which has no SFML dependency at all.

Controls (SFML window)

Key/Mouse Action
SPACE Pause/Resume
. (period) Step one tick
Arrow keys Pan camera
R Reset camera
Left click Toggle safety tile =
Right click Toggle switch state
E (hover a switch) Emergency halt
Mouse wheel Zoom
Middle click + drag Pan
ESC Exit and save metrics

The window opens at your desktop's full resolution automatically. On Windows, SetProcessDPIAware() is called on startup so the OS doesn't auto-scale the window on displays with scaling settings above 100% (this requires linking -luser32, already in the Makefile).

Implemented and verified

  • Level parsing for MAP, SWITCHES, TRAINS, SEED, WEATHER.
  • Real D-tile destinations assigned to trains (not a placeholder formula).
  • Per-direction and global switch counters, initial state parsing, deferred post-movement flips.
  • Safety-tile delays, blocked-spawn retries, rain delays, fog-delayed signal display.
  • Same-target, head-on swap, and crossing (+) collision resolution using Manhattan-distance priority, including the "equal distance = all crash" tie rule.
  • Signal lights (GREEN/YELLOW/RED) computed before collision resolution each tick, so RED/YELLOW are visible ahead of a crash rather than always showing GREEN.
  • Sprite rendering using cropped, background-removed tile art in Sprites/tiles/ (tracks, curves, crossings, switches, spawn/destination markers, safety tiles, signal lights, and directional train sprites), loaded via sf::Texture/sf::Sprite and scaled to a consistent tile size.
  • Deterministic: identical seed + level file → byte-identical trace.csv across repeated runs (verified for all four bundled levels).

Level files

data/levels/easy_level.lvl, medium_level.lvl, and hard_level.lvl were corrected from their original versions, which had two bugs:

  1. Train spawn coordinates in TRAINS: didn't match any real S tile on the map (off by one row, or entirely out of bounds), causing most trains to derail immediately instead of demonstrating real traffic.
  2. medium_level.lvl named a switch D, colliding with the reserved destination-tile symbol D, which caused every real destination on that map to be misidentified as that switch.

Both are fixed; io.cpp also now falls back to snapping a train to the nearest real spawn tile if a level file's coordinates are still invalid, as a defensive measure against future bad level data.

Output

  • out/trace.csv - Tick,TrainID,X,Y,Direction,State
  • out/switches.csv - switch state records
  • out/signals.csv - GREEN/YELLOW/RED signal records per switch per tick
  • out/metrics.txt - delivered/crashed/signal-violation totals

Repository structure

core/            simulation logic, no SFML includes
sfml/            SFML UI, calls into core headers
console/         console-only main, for testing core logic without SFML
data/levels/     .lvl level files
out/             one committed sample run (trace.csv, switches.csv, signals.csv, metrics.txt)
Sprites/tiles/   PNG tile art
docs/            Edit.png, Simulate.png screenshots
Makefile
libraries.sh
README.md

About

A C++17 tick-based railway simulation — deterministic switch logic, distance-based collision priority, and an SFML-rendered grid with signals, weather, and emergency halts.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages