Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/raoulkdev/MiniECS/llms.txt

Use this file to discover all available pages before exploring further.

MiniECS::World is the top-level container for an entire simulation. It owns every Unit in the scene through a std::vector<std::unique_ptr<Unit>>, exposes a full set of Unit management methods, and provides the play() method that starts the main game loop. Nothing runs until a World exists and play() is called.

Constructing a World

Create a World by passing a name string to its constructor. The name is stored for identification purposes.
#include "world/World.h"

MiniECS::World scene("Scene");
World uses std::unique_ptr to manage every Unit it contains. You never need to manually delete a Unit — destroying the World (or letting it go out of scope) automatically cleans up all Units and their attached Modules.

Managing Units

All Unit lifetime is controlled through the World. Units cannot be constructed independently and inserted — they must be created via createUnit().

createUnit(name)

Constructs a new Unit with the given name and pushes it into the internal worldUnits vector. If the name string is empty, the call is a no-op and a message is printed to stdout.
scene.createUnit("u1");

removeUnitByName(name)

Removes the first Unit whose getName() matches the provided string. Prints a message to stdout if no match is found.
scene.removeUnitByName("u1");

removeUnitByIndex(index)

Removes the Unit at the given zero-based position in the internal vector.
scene.removeUnitByIndex(0);

getUnitByName(name)

Returns a std::unique_ptr<Unit>& reference to the Unit with the matching name. Use this to chain Module operations directly.
scene.getUnitByName("u1")->addModule(MiniECS::ModuleType::Transform);
getUnitByName() has undefined behaviour if no Unit with the given name exists. The function iterates worldUnits and returns a reference on match, but if it reaches the end of the vector without finding a match there is no fallback return — the result is undefined behaviour. Always ensure the name exists before calling this method.

getUnitByIndex(index)

Returns a std::unique_ptr<Unit>& reference by zero-based vector position.
scene.getUnitByIndex(0)->addModule(MiniECS::ModuleType::Renderer);

getUnitsVector()

Returns a const std::vector<std::unique_ptr<Unit>>& — a read-only view of all Units currently in the World. Useful for inspection or iteration without modifying the scene.
const auto& units = scene.getUnitsVector();
for (const auto& unit : units)
{
    std::cout << unit->getName() << "\n";
}

The Game Loop

play() is a const method that starts the simulation. It first checks that worldUnits is non-empty. It then iterates over Units one at a time; for each Unit whose Module list is non-empty it enters a while (true) loop — calling callModuleStart() on that Unit then sleeping 16 milliseconds before repeating. Units with no Modules print a message to stdout and are skipped.
void MiniECS::World::play() const
{
    if (!worldUnits.empty())
    {
        for (auto& unit : worldUnits)
        {
            if (!unit->getModulesVector().empty())
            {
                while (true)
                {
                    unit->callModuleStart();
                    std::this_thread::sleep_for(std::chrono::milliseconds(16));
                }
            }
            else
            {
                std::cout << "No units in the scene have modules\n";
            }
        }
    }
    else
    {
        std::cout << "No units in the scene\n";
    }
}
play() contains an infinite while (true) loop that never returns. Because the loop is entered for the first Unit that has Modules, all subsequent Units in the vector are never reached. Only the first Unit with at least one Module attached will be ticked. Do not call play() until all Units and Modules have been fully configured.

Full Usage Example

The following example mirrors the main.cpp entry point bundled with MiniECS and demonstrates the complete World setup pattern:
#include <memory>
#include "modules/transform/TransformModule.h"
#include "unit/Unit.h"
#include "world/World.h"

int main()
{
    // 1. Create the World (scene container)
    MiniECS::World scene("Scene");

    // 2. Create a Unit inside the World
    scene.createUnit("u1");

    // 3. Add a Renderer module to the Unit
    scene.getUnitByName("u1")->addModule(MiniECS::ModuleType::Renderer);

    // 4. Add a Transform module to the Unit
    scene.getUnitByName("u1")->addModule(MiniECS::ModuleType::Transform);

    // 5. Access the TransformModule and set an initial position
    scene.getUnitByName("u1")->getModule<MiniECS::TransformModule>()->position = {22.5f, 33.4f};

    // 6. Start the game loop — this call does not return
    scene.play();
}
1

Construct the World

Instantiate MiniECS::World with a descriptive name. This allocates the internal Unit vector.
2

Create Units

Call createUnit() for each entity you need. The World takes ownership immediately.
3

Attach Modules

Use getUnitByName() or getUnitByIndex() to reach a Unit, then call addModule() with the desired ModuleType.
4

Configure Module state

Retrieve typed Module pointers with getModule<T>() and set any initial values.
5

Call play()

Invoke scene.play() to start the simulation. The game loop runs indefinitely from this point on the first Unit that has Modules.

Build docs developers (and LLMs) love