Component Operations
Entities gain functionality by adding components. This section details all component operation APIs.
Adding Components
Section titled “Adding Components”addComponent
Section titled “addComponent”Add an already-created component instance:
import { Component, ECSComponent } from '@esengine/ecs-framework';
@ECSComponent('Position')class Position extends Component { x: number = 0; y: number = 0;
constructor(x: number = 0, y: number = 0) { super(); this.x = x; this.y = y; }}
const player = scene.createEntity("Player");const position = new Position(100, 200);player.addComponent(position);createComponent
Section titled “createComponent”Pass the component type and constructor arguments directly—the entity creates the instance (recommended):
// Create and add componentconst position = player.createComponent(Position, 100, 200);const health = player.createComponent(Health, 150);
// Equivalent to:// const position = new Position(100, 200);// player.addComponent(position);addComponents
Section titled “addComponents”Add multiple components at once:
const components = player.addComponents([ new Position(100, 200), new Health(150), new Velocity(0, 0)]);Getting Components
Section titled “Getting Components”getComponent
Section titled “getComponent”Get a component of a specific type:
// Returns Position | nullconst position = player.getComponent(Position);
if (position) { position.x += 10; position.y += 20;}hasComponent
Section titled “hasComponent”Check if an entity has a specific component type:
if (player.hasComponent(Position)) { const position = player.getComponent(Position)!; // Use ! because we confirmed it exists}getComponents
Section titled “getComponents”Get all components of a specific type (for multi-component scenarios):
const allHealthComponents = player.getComponents(Health);getComponentByType
Section titled “getComponentByType”Get components with inheritance support using instanceof checking:
// Find CompositeNodeComponent or any subclassconst composite = entity.getComponentByType(CompositeNodeComponent);if (composite) { // composite could be SequenceNode, SelectorNode, etc.}Difference from getComponent():
| Method | Lookup Method | Performance | Use Case |
|---|---|---|---|
getComponent | Exact type match (bitmask) | High | Known exact type |
getComponentByType | instanceof check | Lower | Need inheritance support |
getOrCreateComponent
Section titled “getOrCreateComponent”Get or create a component—automatically creates if it doesn’t exist:
// Ensure entity has Position componentconst position = player.getOrCreateComponent(Position, 0, 0);position.x = 100;
// If exists, returns existing component// If not, creates new component with (0, 0) argscomponents Property
Section titled “components Property”Get all entity components (read-only):
const allComponents = player.components; // readonly Component[]
allComponents.forEach(component => { console.log(component.constructor.name);});Removing Components
Section titled “Removing Components”removeComponent
Section titled “removeComponent”Remove by component instance:
const healthComponent = player.getComponent(Health);if (healthComponent) { player.removeComponent(healthComponent);}removeComponentByType
Section titled “removeComponentByType”Remove by component type:
const removedHealth = player.removeComponentByType(Health);if (removedHealth) { console.log("Health component removed");}removeComponentsByTypes
Section titled “removeComponentsByTypes”Remove multiple component types at once:
const removedComponents = player.removeComponentsByTypes([ Position, Health, Velocity]);removeAllComponents
Section titled “removeAllComponents”Remove all components:
player.removeAllComponents();Change Detection
Section titled “Change Detection”markDirty
Section titled “markDirty”Mark components as modified for frame-level change detection:
const pos = entity.getComponent(Position)!;pos.x = 100;entity.markDirty(pos);
// Or mark multiple componentsconst vel = entity.getComponent(Velocity)!;entity.markDirty(pos, vel);Use with reactive queries:
// Query for components modified this frameconst changedQuery = scene.createReactiveQuery({ all: [Position], changed: [Position] // Only match modified this frame});
for (const entity of changedQuery.getEntities()) { // Handle entities with position changes}Component Mask
Section titled “Component Mask”Each entity maintains a component bitmask for efficient hasComponent checks:
// Get component mask (internal use)const mask = entity.componentMask;Complete Example
Section titled “Complete Example”import { Component, ECSComponent, Scene } from '@esengine/ecs-framework';
@ECSComponent('Position')class Position extends Component { constructor(public x = 0, public y = 0) { super(); }}
@ECSComponent('Health')class Health extends Component { constructor(public current = 100, public max = 100) { super(); }}
// Create entity and add componentsconst player = scene.createEntity("Player");player.createComponent(Position, 100, 200);player.createComponent(Health, 150, 150);
// Get and modify componentconst position = player.getComponent(Position);if (position) { position.x += 10; player.markDirty(position);}
// Get or create componentconst velocity = player.getOrCreateComponent(Velocity, 0, 0);
// Check component existenceif (player.hasComponent(Health)) { const health = player.getComponent(Health)!; health.current -= 10;}
// Remove componentplayer.removeComponentByType(Velocity);
// List all componentsconsole.log(player.components.map(c => c.constructor.name));Next Steps
Section titled “Next Steps”- Entity Handle - Safe cross-frame entity references
- Component System - Component definition and lifecycle