Skip to main content

Overview

The Component system in Atlas Engine allows you to extend GameObject functionality through composition. Components are behaviors or properties that can be attached to GameObjects to add capabilities like custom update logic, collision handling, and more.

Component Class

Base class for all components. Inherit from this class to create custom components.

Creating a Component

class CustomComponent : public Component {
public:
    void init() override {
        // Custom initialization code here
    }
    
    void update(float deltaTime) override {
        // Custom update code here
    }
};

Lifecycle Methods

init

virtual void init();
Initializes the component. This method is called once when the component is added to a GameObject.

atAttach

virtual void atAttach();
Called immediately when the component is attached to a GameObject, before init().

update

virtual void update(float deltaTime);
Updates the component each frame. This method is called every frame before rendering.
deltaTime
float
The time elapsed since the last frame.

beforePhysics

virtual void beforePhysics();
Called before physics simulation each frame. Use this for applying forces or modifying physics properties.

Matrix Updates

setViewMatrix

virtual void setViewMatrix(const glm::mat4 &view);
Performs changes when the GameObject’s view matrix is updated.
view
const glm::mat4&
The new view matrix.

setProjectionMatrix

virtual void setProjectionMatrix(const glm::mat4 &projection);
Performs changes when the GameObject’s projection matrix is updated.
projection
const glm::mat4&
The new projection matrix.

Event Handlers

onCollisionEnter

virtual void onCollisionEnter(GameObject *other);
Called when the GameObject begins colliding with another object.
other
GameObject*
The other GameObject involved in the collision.

onCollisionExit

virtual void onCollisionExit(GameObject *other);
Called when the GameObject stops colliding with another object.
other
GameObject*
The other GameObject that was colliding.

onCollisionStay

virtual void onCollisionStay(GameObject *other);
Called every frame while the GameObject is colliding with another object.
other
GameObject*
The other GameObject currently colliding.

onSignalRecieve

virtual void onSignalRecieve(const std::string &signal, GameObject *sender);
Called when the GameObject receives a signal from another object.
signal
const std::string&
The signal identifier.
sender
GameObject*
The GameObject that sent the signal.

onSignalEnd

virtual void onSignalEnd(const std::string &signal, GameObject *sender);
Called when a signal transmission ends.
signal
const std::string&
The signal identifier.
sender
GameObject*
The GameObject that sent the signal.

onQueryReceive

virtual void onQueryReceive(QueryResult &result);
Called when the GameObject receives a query result.
result
QueryResult&
The query result data.

Utility Methods

getWindow

Window* getWindow();
Gets the window associated with the component’s GameObject.
return
Window*
The window instance.

clone

virtual std::shared_ptr<Component> clone() const;
Creates a copy of the component. Override this to support cloning.
return
std::shared_ptr<Component>
A cloned component, or nullptr if not implemented.

Properties

object
GameObject*
The GameObject associated with the component. Set automatically when the component is attached.

TraitComponent

Component that is specifically tied to a certain type of GameObject. It cannot be added to objects that do not inherit from the specified type.
template <typename T>
class TraitComponent : public Component;

Creating a TraitComponent

class CameraController : public TraitComponent<Camera> {
public:
    void updateComponent(Camera *camera) override {
        // Update logic with direct access to Camera
        camera->move({0.0f, 0.0f, 0.1f});
    }
};

Methods

updateComponent

virtual void updateComponent(T *object);
Updates the component with a typed reference to the GameObject it is bound to.
object
T*
A pointer to the typed GameObject.

getObject

T* getObject();
Provides direct access to the specialized GameObject this trait decorates.
return
T*
Pointer to the typed object, or nullptr if the component has not been attached yet.

setTypedObject

void setTypedObject(T *obj);
Sets the typed object reference for the component.
obj
T*
A pointer to the typed GameObject.

GameObject Class

Base class for all Game Objects. It extends from Renderable and provides common functionality for all game objects in the scene.

Constructor

GameObject();
Constructs a new GameObject and assigns it a unique ID.

Component Management

addComponent

template <typename T>
void addComponent(T &&existing);
Adds a component to the object.
existing
T&&
The component instance to add.
The component must be long-lived. Declaring it as a class property is recommended.

addTraitComponent

template <typename U, typename T>
void addTraitComponent(T &&existing);
Adds a trait component to the object. A trait component is a component that is tied to a specific type of GameObject.
existing
T&&
The trait component instance to add.

getComponent

template <typename T>
std::shared_ptr<T> getComponent();
Gets the first component that matches the specified type.
return
std::shared_ptr<T>
A shared pointer to the component if found, or nullptr if not found.

Virtual Methods

The GameObject class provides many virtual methods that can be overridden:
virtual void attachProgram(const ShaderProgram &program);
virtual void createAndAttachProgram(VertexShader &vertexShader, FragmentShader &fragmentShader);
virtual void attachTexture(const Texture &texture);
virtual void setColor(const Color &color);
virtual void setPosition(const Position3d &newPosition);
virtual void move(const Position3d &deltaPosition);
virtual void setRotation(const Rotation3d &newRotation);
virtual void lookAt(const Position3d &target, const Normal3d &up);
virtual void rotate(const Rotation3d &deltaRotation);
virtual void setScale(const Scale3d &newScale);
virtual void hide();
virtual void show();

Event Handlers

GameObject provides the same event handlers as Component:
  • onCollisionEnter(GameObject *other)
  • onCollisionExit(GameObject *other)
  • onCollisionStay(GameObject *other)
  • onSignalRecieve(const std::string &signal, GameObject *sender)
  • onSignalEnd(const std::string &signal, GameObject *sender)
  • onQueryReceive(QueryResult &result)

Properties

rigidbody
Rigidbody*
The rigidbody component attached to this GameObject, if any.
id
int
The unique identifier for the object.

Utility Methods

getId

unsigned int getId();
Returns the unique identifier associated with this object.
return
unsigned int
The object’s unique ID.

addDependency

void addDependency(GameObject *obj);
Adds a dependency relationship to another GameObject.
obj
GameObject*
The GameObject to add as a dependency.

getDependencies

std::vector<GameObject*> getDependencies() const;
Returns all GameObject dependencies.
return
std::vector<GameObject*>
Vector of dependent GameObjects.

UIObject Class

A GameObject that is used for creating user interface elements.
class UIObject : public GameObject;
UIObjects are automatically rendered in forward mode and do not participate in deferred rendering.

UIView Class

A conjunction of UI elements that share the same view and projection matrices. Acts as a container for organizing UI objects.
class UIView : public UIObject;

Methods

addChild

void addChild(UIObject *child);
Adds a child UI object to this view.
child
UIObject*
The UI object to add. Must be long-lived.

Example Usage

Basic Component

class RotatorComponent : public Component {
private:
    float rotationSpeed = 45.0f; // degrees per second
    
public:
    void init() override {
        std::cout << "RotatorComponent initialized" << std::endl;
    }
    
    void update(float deltaTime) override {
        // Rotate the parent object
        if (object) {
            object->rotate({0.0f, rotationSpeed * deltaTime, 0.0f});
        }
    }
    
    void setRotationSpeed(float speed) {
        rotationSpeed = speed;
    }
};

// Usage
CoreObject cube = createBox({1.0, 1.0, 1.0});
RotatorComponent rotator;
rotator.setRotationSpeed(90.0f);
cube.addComponent(rotator);

Collision Handler Component

class CollisionLogger : public Component {
public:
    void onCollisionEnter(GameObject *other) override {
        std::cout << "Collision started with object " << other->getId() << std::endl;
    }
    
    void onCollisionExit(GameObject *other) override {
        std::cout << "Collision ended with object " << other->getId() << std::endl;
    }
    
    void onCollisionStay(GameObject *other) override {
        // Called every frame during collision
        std::cout << "Still colliding with " << other->getId() << std::endl;
    }
};

// Usage
CoreObject sphere = createSphere(1.0);
CollisionLogger logger;
sphere.addComponent(logger);

TraitComponent Example

class CameraController : public TraitComponent<Camera> {
private:
    float moveSpeed = 5.0f;
    
public:
    void updateComponent(Camera *camera) override {
        Window* window = getWindow();
        if (!window) return;
        
        float dt = window->getDeltaTime();
        
        // WASD movement
        if (window->isKeyPressed(Key::W)) {
            camera->moveTo(camera->getFrontVector(), moveSpeed * dt);
        }
        if (window->isKeyPressed(Key::S)) {
            camera->moveTo(camera->getFrontVector() * -1.0f, moveSpeed * dt);
        }
        // Add A and D for strafing...
    }
};

// Usage - can only be attached to Camera objects
Camera camera;
CameraController controller;
camera.addTraitComponent<Camera>(controller);

Signal Communication

class TriggerZone : public Component {
public:
    void onCollisionEnter(GameObject *other) override {
        // Send signal to other objects
        for (auto* dependent : object->getDependencies()) {
            dependent->onSignalRecieve("trigger_activated", object);
        }
    }
};

class Door : public Component {
private:
    bool isOpen = false;
    
public:
    void onSignalRecieve(const std::string &signal, GameObject *sender) override {
        if (signal == "trigger_activated" && !isOpen) {
            std::cout << "Opening door!" << std::endl;
            isOpen = true;
            // Animate door opening...
        }
    }
};

// Setup
CoreObject trigger = createBox({2.0, 0.1, 2.0});
CoreObject door = createBox({1.0, 2.0, 0.1});

trigger.addComponent(TriggerZone());
door.addComponent(Door());

// Establish dependency so trigger can signal door
trigger.addDependency(&door);

Physics Component

class GravityComponent : public Component {
private:
    float gravity = -9.81f;
    float velocity = 0.0f;
    
public:
    void beforePhysics() override {
        // Apply gravity before physics simulation
        if (object->rigidbody) {
            velocity += gravity * getWindow()->getDeltaTime();
            object->move({0.0f, velocity * getWindow()->getDeltaTime(), 0.0f});
        }
    }
    
    void onCollisionEnter(GameObject *other) override {
        // Reset velocity on ground collision
        velocity = 0.0f;
    }
};

UI Example

class MenuSystem : public UIView {
private:
    UIObject titleText;
    UIObject playButton;
    UIObject quitButton;
    
public:
    void init() {
        // Set up UI elements
        titleText.setPosition({0.0f, 100.0f, 0.0f});
        playButton.setPosition({0.0f, 0.0f, 0.0f});
        quitButton.setPosition({0.0f, -50.0f, 0.0f});
        
        // Add to view
        addChild(&titleText);
        addChild(&playButton);
        addChild(&quitButton);
    }
};

MenuSystem menu;
menu.init();
window.addUIObject(&menu);

Component Lifecycle

The typical lifecycle of a component is:
  1. Creation: Component is instantiated
  2. Attachment: addComponent() is called, setting object pointer
  3. atAttach(): Called immediately after attachment
  4. init(): Called once during GameObject initialization
  5. beforePhysics(): Called every frame before physics simulation
  6. update(): Called every frame with deltaTime
  7. Event Handlers: Called when relevant events occur (collisions, signals, etc.)
  8. Destruction: Component is destroyed with its parent GameObject
Components are copied when GameObjects are cloned, provided the component implements the clone() method.

Build docs developers (and LLMs) love