Skip to main content

Technical Choices

This document explains the key technical decisions for the R-Type project.


🎯 Quick Overview

TechnologyPurposeWhy
vcpkgPackage ManagerCross-platform, works with CMake
CMakeBuild SystemStandard for C++, multi-platform
SFML 2.6.1Graphics & AudioSimple 2D API, stable
Boost.AsioNetworkingAsync I/O, UDP/TCP support
ECSGame Engine PatternFlexible, performance, composition

📦 vcpkg (Package Manager)

What: Microsoft's C++ package manager

Why we chose it:

  • Works on Windows, Linux, macOS
  • Integrates directly with CMake
  • Reproducible builds with vcpkg.json
  • Team members get same library versions

🔨 CMake (Build System)

What: Cross-platform build configuration tool

Why we chose it:

  • Standard in C++ industry
  • One configuration works everywhere
  • Modular: client, server, engine as separate modules
  • Finds libraries automatically with vcpkg

🎮 SFML 2.6.1 (Graphics Library)

What: Simple and Fast Multimedia Library

Why we chose it:

  • Easy to learn, clean C++ API
  • Perfect for 2D games
  • Cross-platform (Windows, Linux, macOS)
  • Hardware-accelerated (OpenGL)
  • Version 2.6.1 is stable (v3 has breaking changes)

Wrapper Pattern

We don't use SFML directly in game code. Instead, we use interfaces:

// Interface (game code uses this)
class IGraphics {
virtual void drawSprite(const ISprite& sprite) = 0;
};

// Implementation (uses SFML internally)
class GraphicsSFML : public IGraphics {
// Wraps sf::RenderWindow
};

Benefits:

  • Can swap SFML for another library later
  • Easier to test (mock implementations)
  • Game code independent from library

🌐 Boost.Asio (Networking)

What: Asynchronous networking library

Why we chose it:

  • Async I/O: Network doesn't block game loop
  • UDP & TCP: Fast updates (UDP) + reliable lobby (TCP)
  • Cross-platform
  • Mature and well-tested
  • Better than SFML's basic networking

🧩 ECS (Entity Component System)

What: Design pattern for game engines

Why we chose it:

  • Flexible: Mix components to create any entity type
  • Performance: Data-oriented, cache-friendly
  • Maintainable: No deep inheritance hierarchies
  • Standard: Used in Unity, Unreal, Godot

How it works:

Entity = Just an ID (uint32_t)

Components = Data only

struct PositionComponent { float x, y; };
struct VelocityComponent { float dx, dy; };
struct HealthComponent { int current, max; };

Systems = Logic that processes components

void MovementSystem::update(float dt) {
for (auto entity : entities_with<Position, Velocity>()) {
position.x += velocity.dx * dt;
position.y += velocity.dy * dt;
}
}