← blog

My ECS Journey - Learning Modern C++ from Scratch

5 August 2026


Introduction

As a game developer, I am always fascinated by the next big thing that can improve a game—whether it involves graphics, gameplay, or, above all, performance.

I consider myself a novice-to-intermediate C++ developer. I briefly studied the language in university for an embedded systems course. When I turned in my final exam project—a functional turn-signal state machine built on an ESP32 micro-controller—my professor was thoroughly surprised. Everything worked flawlessly, and he called the code "excellent." In retrospect, those words inflated my ego almost negatively. I went through the rest of my university years without writing a line of C++, believing I was already proficient enough.

Eventually, curiosity led me to explore more technical content online: GitHub repositories, technical blog posts, and YouTube videos on game development. The moment I started looking at production-grade code, I was stunned.

I realized I knew next to nothing about C++. I had missed out on so much. Part of it was my fault for not staying curious during my studies, but part of it was also a university curriculum that lacked deeper C++ coursework.

I began researching the topics I missed—data structures, algorithms, and technical books on C++ and game architecture. However, I fell into a trap that almost every learner encounters: consuming without practicing. I spent countless hours watching videos titled "HOW TO CREATE MINECRAFT IN C++" or "THIS C++ TERRARIA CLONE LANDED ME MY FIRST JOB," but I never actually wrote code.

Fast forward a couple of years: I landed a job as an Unreal Engine game developer at an indie studio in Italy (LKA), thanks to personal projects I had built in the engine.

I had often heard the phrase "Unreal Engine C++ is nothing like standard C++," and I finally understood why. Although I write C++ daily at work, engine-specific abstractions are vastly different from standard C++ codebases.

To bridge this gap, I decided to take matters into my own hands and master low-level C++ once and for all.

In my research, one term kept appearing repeatedly in game architecture discussions: ECS.


What is ECS?

ECS (Entity Component System) is a software architectural pattern that follows the principle of composition over inheritance.

It consists of three main elements:

ECS provides an alternative to traditional Object-Oriented Programming (OOP), avoiding common pitfalls such as:

If OOP asks "What is this object?", ECS asks "What does this object HAVE?"

For example, a Player entity might consist of:


My Learning Journey

To learn ECS, I took the sensible route... reading reference books and architectural articles? Not quite.

Claude

I used an LLM to guide my learning, setting strict constraints:

I didn't want this project to be all vibe-coded while i learned nothing.

I find interactive exploration much more engaging than passive reading.

Once I had a conceptual foundation, I began setting up the core structures. I started by defining entities with a minimalist approach:

#pragma once

#include <cstdint>   
#include <cstddef>

using Entity = std::uint32_t;
using ComponentID = std::size_t;

constexpr Entity NULL_ENTITY = 0;
constexpr std::uint32_t MAX_ENTITIES = 5000;

It was the absolute minimum needed to get started. (I have since updated this to an Index + Generation layout, which I will detail in a future post).

Next, I created World.h to manage entities and components:

#include <vector>
#include <unordered_map>
#include <typeindex>
#include <any>

class World {
public:
    Entity createEntity();
    void destroyEntity(Entity entity);
    bool isAlive(Entity entity) const;

private:
    std::vector<Entity> m_aliveEntities;
    std::unordered_map<std::type_index, std::unordered_map<Entity, std::any>> m_components;
};

I initially used std::unordered_map as a simple component store to test the concept. (This has since been replaced with a sparse set to prevent cache misses caused by std::unordered_map, but I will save those details for the next post).

Alongside the core World class, I wrote generic member templates for component management. This was my first practical experience writing C++ templates:

template<typename T>
void addComponent(Entity entity, T component) {
    auto key = std::type_index(typeid(T));
    m_components[key][entity] = std::move(component);
}

template<typename T>
T& getComponent(Entity entity) {
    auto key = std::type_index(typeid(T));
    assert(hasComponent<T>(entity) && "Entity does not have the requested component!");
    return std::any_cast<T&>(m_components[key][entity]);
}

template<typename T>
bool hasComponent(Entity entity) const {
    auto key = std::type_index(typeid(T));
    auto typeIt = m_components.find(key);
    if (typeIt == m_components.end()) return false;
    return typeIt->second.count(entity) > 0;
}

template<typename T>
void removeComponent(Entity entity) {
    auto key = std::type_index(typeid(T));
    m_components[key].erase(entity);
}

template<typename... Ts>
std::vector<Entity> getEntitiesWith() {
    std::vector<Entity> result;
    for (Entity e : m_aliveEntities) {
        if ((hasComponent<Ts>(e) && ...)) {
            result.push_back(e);
        }
    }
    return result;
}

With these foundations in place, I built an early prototype of a tower defense game using Raylib for rendering to avoid low-level OpenGL boilerplate.

The initial setup consists of a 30x30 grid map where the player can place towers, while enemies spawn randomly and move toward the base.

Current progress includes:


Conclusion

That covers my first steps implementing an ECS architecture in C++. The codebase has already progressed significantly, and I am launching this series to document my progress and solidify my understanding of these systems.

I will be posting updates as the project evolves. Thanks for reading!