Entities
Entities are the fundamental objects that make up any game created with Angry Pixel Engine.
Each entity is simply a unique identifier (numeric ID) that groups one or more components that define its behavior and attributes.
📝 Note: Entities themselves have no data or logic. All their behavior and state are defined through the components they contain.
Creating entities
The engine provides the EntityManager
to create and manage entities.
Create an empty entity
const entity = entityManager.createEntity();
Create an entity with components
const entity = entityManager.createEntity([
new Player({ health: 100 }),
new Transform({ position: new Vector2(0, 0) }),
]);
📝 You can pass either instances of components or component classes (the engine will automatically instantiate the class if no instance is provided).
Create an entity from an archetype
An archetype is a reusable template that defines which components the entity and its children will have.
const playerArchetype = {
components: [new Player({ health: 100 }), new Transform({ position: new Vector2(0, 0) })],
enabled: true,
};
const entity = entityManager.createEntityFromArchetype(playerArchetype);
Parent-child relationships
You can establish hierarchies between entities:
const parent = entityManager.createEntity([Transform]);
const child = entityManager.createEntity([Transform]);
entityManager.setParent(child, parent);
This is useful for logically grouping entities (for example, an enemy with multiple parts or a character and their sword).
🔎 Important: If both entities have a
Transform
component, the system will automatically create a relationship between thoseTransform
components so the child’s position updates relative to the parent.
Enabling and disabling entities
You can enable or disable entire entities:
entityManager.disableEntity(entity);
entityManager.enableEntity(entity);
🔎 Disabled entities and components are not processed by systems (they won’t appear in
search
results).
Searching for entities
The search
method allows you to find entities that have a specific component:
const result = entityManager.search(Player);
result.forEach(({ entity, component }) => {
console.log(`Entity: ${entity}, HP: ${component.health}`);
});
You can also search by specific attributes:
const alivePlayers = entityManager.search(Player, (component) => component.status === "alive");
Modifying components of an entity
To update the data of a component on an entity:
entityManager.updateComponentData(entity, Player, (component) => {
component.health = 80;
});
Removing entities and components
Remove an entity (its components and children will also be removed):
entityManager.removeEntity(entity);
Remove a component:
entityManager.removeComponent(entity, Player);
Archetype examples
Archetypes are reusable templates that define:
- Which components the entity will have.
- Whether it will be enabled or disabled when created.
- Whether it will have child entities with their own components.
They are ideal for creating complex or repeatable entities (for example: enemies, pickups, obstacles).
1️⃣ Basic archetype
const playerArchetype = {
components: [
new Player({ health: 100, speed: 50 }),
new Transform({ position: new Vector2(0, 0) }),
SpriteRenderer,
],
enabled: true,
};
const entity = entityManager.createEntityFromArchetype(playerArchetype);
Result:
An entity is created with the Player
, Transform
, and SpriteRenderer
components and is enabled.
2️⃣ Archetype with disabled components
const stealthEnemyArchetype = {
components: [
new Enemy({ aggression: 80 }),
new Transform({ position: new Vector2(100, 200) }),
disableComponent(new BoxCollider()), // The enemy starts without collision
],
enabled: true,
};
const enemy = entityManager.createEntityFromArchetype(stealthEnemyArchetype);
Result:
The enemy is created with its collider disabled. You can activate it later with:
entityManager.enableComponent(enemy, BoxCollider);
3️⃣ Archetype with parent-child hierarchy
const bossArchetype = {
components: [new Enemy({ health: 1000 }), new Transform({ position: new Vector2(500, 300) }), SpriteRenderer],
children: [
{
components: [new WeaponMount(), SpriteRenderer],
enabled: true,
},
{
components: [new Shield({ durability: 200 }), SpriteRenderer],
enabled: false, // The shield starts disabled
},
],
enabled: true,
};
const boss = entityManager.createEntityFromArchetype(bossArchetype);
Result:
A boss is created with two child entities:
- An active weapon.
- A disabled shield that can be activated later using
entityManager.enableEntity(shieldEntity)
.
🔎 Note: If both the parent and child entities have
Transform
components, a positional relationship between them will be automatically created.
Important note
When creating entities from archetypes:
- Components are cloned, allowing you to use the same archetype multiple times without component instances overlapping.
- Disabled components will not be processed by systems until they are enabled.
- Children inherit parent relationships and can be searched or modified using methods like
getChildren
orsearchInChildren
.
Summary
✅ Entities are simple identifiers that group components.
✅ The EntityManager
provides full management of entities and components.
✅ Archetypes are a powerful tool for defining templates of complex entities.