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 is designed to be extended. The Module base class provides a minimal, consistent interface — a constructor that accepts a ModuleType, a virtual start() method called each frame, and typed introspection via getType() and getTypeName(). Adding new behaviour to any Unit is a matter of inheriting from Module, registering a new enum value, and wiring the type into the Unit::addModule() switch-case. The walkthrough below uses a PhysicsModule as a concrete example.
1

Add a new ModuleType enum value

All module identity in MiniECS flows through the ModuleType enum class defined in Module.h. Open that file and add a new entry for your module. Each value must be a unique integer — the framework uses it to prevent duplicate modules from being added to the same Unit.
enum class ModuleType
{
    ModuleBase = 0,
    Transform  = 1,
    Renderer   = 2,
    Physics    = 3   // new
};
ModuleType is an enum class, so values are scoped (ModuleType::Physics) and do not implicitly convert to integers. Every entry must have a distinct value; reusing an integer will cause the duplicate-prevention check in addModule() to misidentify unrelated module types as duplicates.
2

Create the header file PhysicsModule.h

Create src/modules/physics/PhysicsModule.h. Inherit publicly from Module, bring in the base constructor with using Module::Module, declare any data members your module needs, and override start().
#ifndef PHYSICSMODULE_H
#define PHYSICSMODULE_H

#include "../module_base/Module.h"

namespace MiniECS
{
    class PhysicsModule : public Module {
    public:
        using Module::Module;

        float velocityX = 0.0f;
        float velocityY = 0.0f;

        void start() override;
    };
}

#endif //PHYSICSMODULE_H
The using Module::Module; declaration inherits the base-class constructor, so PhysicsModule can be constructed with just a ModuleType argument — exactly what Unit::addModule() passes when it calls std::make_unique<PhysicsModule>(ModuleType::Physics). No extra constructor boilerplate is needed in your subclass.
3

Implement start() in PhysicsModule.cpp

Create src/modules/physics/PhysicsModule.cpp. The start() method is called by Unit::callModuleStart() for every module attached to a unit. Put your per-frame logic here.
#include "PhysicsModule.h"
#include <iostream>

void MiniECS::PhysicsModule::start()
{
    // Apply simple gravity
    velocityY -= 9.8f * 0.016f; // 16ms frame
    std::cout << "Physics -> VelocityX: " << velocityX
              << ", VelocityY: " << velocityY << "\n";
}
4

Register the new type in Unit::addModule()

Open src/unit/Unit.cpp. At the top of the file, add an #include for your new header alongside the existing module includes:
#include "../modules/physics/PhysicsModule.h"
Then add a case for ModuleType::Physics inside the switch statement in Unit::addModule():
case ModuleType::Physics:
    modules.push_back(std::make_unique<PhysicsModule>(ModuleType::Physics));
    break;
Without this case, addModule(ModuleType::Physics) falls through to the default branch and prints "Invalid Module Type!!" without creating anything.
5

Add PhysicsModule to CMakeLists.txt

MiniECS uses a flat add_executable list in its CMakeLists.txt. Add both the header and the implementation file so CMake includes them in the build:
add_executable(MiniECS src/main.cpp
        src/modules/module_base/Module.cpp
        src/modules/module_base/Module.h
        src/modules/physics/PhysicsModule.cpp
        src/modules/physics/PhysicsModule.h
        src/unit/Unit.cpp
        src/unit/Unit.h
        src/modules/renderer/RendererModule.cpp
        src/modules/renderer/RendererModule.h
        src/modules/transform/TransformModule.cpp
        src/modules/transform/TransformModule.h
        src/world/World.cpp
        src/world/World.h)
6

Use the new module

With the enum value registered and the switch-case wired up, you can attach PhysicsModule to any Unit and access it through the templated getModule<T>() method, just like the built-in modules.
scene.getUnitByName("player")->addModule(MiniECS::ModuleType::Physics);

auto* physics = scene.getUnitByName("player")->getModule<MiniECS::PhysicsModule>();
if (physics) {
    physics->velocityX = 5.0f;
}
When scene.play() runs, callModuleStart() will invoke PhysicsModule::start() on every tick, printing the updated velocity to stdout.

Build docs developers (and LLMs) love