R-Type Architecture
This document describes the architecture and organization of the R-Type project.
ποΈ Architecture Overviewβ
The R-Type project follows a client-server architecture with a clear separation between frontend (client) and backend (server + engine).
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β R-Type Project β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββ΄ββββββββββββββββ
β β
ββββββββΌβββββββ ββββββββΌβββββββ
β Client βββββββββββββββββΊβ Server β
β (Frontend) β Network β (Backend) β
βββββββββββββββ ββββββββ¬βββββββ
β β
β β
ββββββββΌβββββββ ββββββββΌβββββββ
β SFML β β Engine β
β Wrapper β β (ECS, etc) β
βββββββββββββββ βββββββββββββββ
π Module Structureβ
Client Module (client/)β
Purpose: Game client (frontend) with graphical rendering
Structure:
client/
βββ CMakeLists.txt # Client build configuration
βββ src/ # Client source files
βββ wrapper/ # SFML abstraction layer
βββ window/ # Window management (IWindow)
βββ graphics/ # Rendering (IGraphics, ISprite)
βββ input/ # Input handling (IInput)
βββ audio/ # Audio management (IAudio)
Key Features:
- Abstract interfaces for graphics library independence
- SFML implementation (can be swapped for SDL, etc.)
- Frame-rate independent rendering (delta time)
- Clean separation from game logic
Dependencies:
- SFML 2.5+ (graphics, audio, window, system)
- C++17 standard library
Server Module (server/)β
Purpose: Game server (backend) with game logic and networking
Structure:
server/
βββ CMakeLists.txt # Server build configuration
βββ src/ # Server source files (networking, game loop)
βββ engine/ # Game engine (core systems)
βββ CMakeLists.txt # Engine build configuration
βββ src/ # Engine source files
βββ ecs/ # Entity-Component-System
βββ physics/ # Physics engine
βββ ... # Other engine systems
Key Features:
- Authoritative server architecture
- Integrated game engine for backend logic
- Network protocol handling
- Game state management
Dependencies:
- C++17 standard library
- Network library (Asio/Boost.Asio - future)
Engine Module (server/engine/)β
Purpose: Core game engine integrated into the server
Structure:
engine/
βββ CMakeLists.txt # Engine build configuration
βββ src/ # Engine source files
βββ ecs/ # Entity-Component-System
β βββ Entity.hpp/cpp
β βββ Component.hpp/cpp
β βββ System.hpp/cpp
βββ physics/ # Physics simulation
β βββ Physics.hpp/cpp
β βββ Collision.hpp/cpp
βββ ... # Other systems
Key Features:
- ECS architecture for game entities
- Physics simulation
- Game logic processing
- Runs on server side (backend)
Dependencies:
- None (pure C++17)
π Architecture Rationaleβ
Why Client-Server Separation?β
- Network Multiplayer: Authoritative server prevents cheating
- Scalability: Multiple clients can connect to one server
- Clear Responsibilities: Client handles rendering, server handles logic
- Testing: Modules can be tested independently
Why Engine in Server?β
In the R-Type architecture, the engine is integrated into the server module because:
- Authoritative Logic: Game logic must run server-side to prevent cheating
- Simplified Architecture: No need for shared code between client/server
- Performance: Engine runs once on server, not on every client
- Network Efficiency: Only game state is transmitted, not logic
Traditional Approach (NOT used):
ββββββββββ ββββββββββ ββββββββββ
β Client ββββββΊβ Engine βββββββ Server β
ββββββββββ ββββββββββ ββββββββββ
Shared engine (complex sync)
R-Type Approach (USED):
ββββββββββ ββββββββββ
β Client βββββββββββββββββββββΊβ Server β
β(Render)β Network β+Engine β
ββββββββββ ββββββββββ
Clean separation
Common Moduleβ
The common/ module contains shared code between client and server:
common/
βββ network/ # Network protocol definitions
βββ utils/ # Shared utilities
βββ replay/ # Replay recording and playback
βββ ReplayRecorder.hpp/cpp # Records game packets
βββ ReplayPlayer.hpp/cpp # Plays back replays
Key Features:
- Network protocol definitions shared between client/server
- Replay system for recording and playback
- Utility functions used across modules
πΉ Replay Systemβ
The replay system allows recording and playback of game sessions by capturing network packets.
Architectureβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Replay System β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββ΄ββββββββββββββββ
β β
ββββββββΌβββββββ ββββββββΌβββββββ
β Recording β β Playback β
β (Client) β β (Client) β
βββββββββββββββ βββββββββββββββ
β β
β β
ββββββββΌβββββββ ββββββββΌβββββββ
β .rtr βββββββββββββββββΊβ Viewer β
β Binary File β Load & Play β UI β
βββββββββββββββ βββββββββββββββ
Componentsβ
ReplayRecorder (common/replay/):
- Records all serverβclient packets during gameplay
- Saves to binary
.rtrformat with timestamps - Automatically creates
replays/directory
ReplayPlayer (common/replay/):
- Reads
.rtrfiles and replays packets - Supports pause, seek (Β±10s), speed control (0.5x/1x/2x)
- Thread-safe packet processing
ReplayBrowser (client/):
- UI for browsing available replays
- Displays replay list sorted by date
- File metadata (size, date)
ReplayControls (client/):
- Playback controls: pause, seek, speed
- Progress bar with time display
- Exit to menu
ReplayViewer (client/src/):
- Complete replay viewing interface
- Uses same rendering as live game
- Integrates with ClientGameState
File Format (.rtr)β
Header (17 bytes):
- Magic: "RTYPE_REPLAY\0" (13 bytes)
- Version: uint32_t (4 bytes)
Entry (repeated):
- Timestamp: uint64_t (8 bytes) - milliseconds from start
- PacketSize: uint16_t (2 bytes)
- PacketData: uint8_t[] (PacketSize bytes)
Recording Flowβ
- Game starts β Create ReplayRecorder
- Server sends packet β Client receives
- ReplayRecorder.recordPacket() β Write to file
- Game ends β Stop recording
Playback Flowβ
- User selects replay β Load .rtr file
- ReplayPlayer reads packets
- For each packet at timestamp:
- Process packet through ClientGameState
- Render entities/explosions
- User controls: pause/seek/speed
Benefits:
- β Exact replay of game sessions
- β No impact on server performance
- β Small file sizes (binary format)
- β Seeking without state corruption
π Communication Flowβ
Game Loop Flowβ
1. Client renders frame
ββββΊ Client sends input to server (keyboard, mouse)
2. Server receives input
ββββΊ Engine processes input
ββββΊ Physics simulation
ββββΊ Collision detection
ββββΊ Game state update
3. Server sends game state to client
ββββΊ Client receives state
ββββΊ Client renders new frame
Dependency Managementβ
- System SFML: Used if available (faster builds)
- FetchContent: Automatic SFML download if not found
- Cross-platform: Works on Linux, Windows
π― Design Patternsβ
Client: Strategy Pattern (SFML Wrapper)β
Problem: Need to support multiple graphics libraries (SFML, SDL, etc.)
Solution: Abstract interfaces + concrete implementations
// Abstract interface
class IWindow {
public:
virtual void display() = 0;
virtual bool pollEvent() = 0;
// ...
};
// SFML implementation
class WindowSFML : public IWindow {
sf::RenderWindow _window;
public:
void display() override { _window.display(); }
// ...
};
// Future SDL implementation
class WindowSDL : public IWindow {
SDL_Window* _window;
// ...
};
Benefits:
- β Easy to swap graphics libraries
- β Testing with mock implementations
- β No SFML dependencies in main code
Server: Entity-Component-System (Future)β
Problem: Managing complex game entities with different behaviors
Solution: ECS architecture
// Entity: Just an ID
struct Entity {
uint32_t id;
};
// Components: Pure data
struct PositionComponent {
float x, y;
};
struct VelocityComponent {
float dx, dy;
};
// Systems: Logic that operates on components
class MovementSystem {
void update(float deltaTime) {
for (auto entity : entities_with<Position, Velocity>()) {
entity.get<Position>().x += entity.get<Velocity>().dx * deltaTime;
entity.get<Position>().y += entity.get<Velocity>().dy * deltaTime;
}
}
};
Benefits:
- β Data-oriented design (cache-friendly)
- β Easy to add/remove behaviors
- β Parallelization potential
π Security Considerationsβ
Authoritative Serverβ
- β Server validates all actions
- β Client sends input, not state
- β Server determines game outcomes
- β Client cannot cheat by modifying state
π Performance Considerationsβ
Clientβ
- Frame-rate Independence: Delta time for smooth movement
- Efficient Rendering: Batch sprite rendering
- Asset Management: Texture/sound loading optimization
Serverβ
- Tick Rate: Fixed update rate (60 TPS)
- Entity Culling: Only update active entities
- Network Optimization: Delta compression, interpolation