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
Initializes the component. This method is called once when the component is added to a GameObject.
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.
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.
setProjectionMatrix
virtual void setProjectionMatrix(const glm::mat4 &projection);
Performs changes when the GameObject’s projection matrix is updated.
The new projection matrix.
Event Handlers
onCollisionEnter
virtual void onCollisionEnter(GameObject *other);
Called when the GameObject begins colliding with another object.
The other GameObject involved in the collision.
onCollisionExit
virtual void onCollisionExit(GameObject *other);
Called when the GameObject stops colliding with another object.
The other GameObject that was colliding.
onCollisionStay
virtual void onCollisionStay(GameObject *other);
Called every frame while the GameObject is colliding with another object.
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.
The GameObject that sent the signal.
onSignalEnd
virtual void onSignalEnd(const std::string &signal, GameObject *sender);
Called when a signal transmission ends.
The GameObject that sent the signal.
onQueryReceive
virtual void onQueryReceive(QueryResult &result);
Called when the GameObject receives a query result.
Utility Methods
getWindow
Gets the window associated with the component’s GameObject.
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
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.
A pointer to the typed GameObject.
getObject
Provides direct access to the specialized GameObject this trait decorates.
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.
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
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.
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.
The trait component instance to add.
getComponent
template <typename T>
std::shared_ptr<T> getComponent();
Gets the first component that matches the specified type.
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
The rigidbody component attached to this GameObject, if any.
The unique identifier for the object.
Utility Methods
getId
Returns the unique identifier associated with this object.
addDependency
void addDependency(GameObject *obj);
Adds a dependency relationship to another GameObject.
The GameObject to add as a dependency.
getDependencies
std::vector<GameObject*> getDependencies() const;
Returns all GameObject dependencies.
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.
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:
- Creation: Component is instantiated
- Attachment:
addComponent() is called, setting object pointer
- atAttach(): Called immediately after attachment
- init(): Called once during GameObject initialization
- beforePhysics(): Called every frame before physics simulation
- update(): Called every frame with deltaTime
- Event Handlers: Called when relevant events occur (collisions, signals, etc.)
- Destruction: Component is destroyed with its parent GameObject
Components are copied when GameObjects are cloned, provided the component implements the clone() method.