System Types
The framework provides several different system base classes for different use cases.
EntitySystem - Base System
Section titled “EntitySystem - Base System”The most basic system class, all other systems inherit from it:
import { EntitySystem, ECSSystem, Matcher } from '@esengine/ecs-framework';
@ECSSystem('Movement')class MovementSystem extends EntitySystem { constructor() { // Use Matcher to define entity conditions to process super(Matcher.all(Position, Velocity)); }
protected process(entities: readonly Entity[]): void { for (const entity of entities) { const position = entity.getComponent(Position); const velocity = entity.getComponent(Velocity);
if (position && velocity) { position.x += velocity.dx * Time.deltaTime; position.y += velocity.dy * Time.deltaTime; } } }}ProcessingSystem - Processing System
Section titled “ProcessingSystem - Processing System”Suitable for systems that don’t need to process entities individually:
@ECSSystem('Physics')class PhysicsSystem extends ProcessingSystem { constructor() { super(); // No Matcher needed }
public processSystem(): void { // Execute physics world step this.physicsWorld.step(Time.deltaTime); }}PassiveSystem - Passive System
Section titled “PassiveSystem - Passive System”Passive systems don’t actively process, mainly used for listening to entity add and remove events:
@ECSSystem('EntityTracker')class EntityTrackerSystem extends PassiveSystem { constructor() { super(Matcher.all(Health)); }
protected onAdded(entity: Entity): void { console.log(`Health entity added: ${entity.name}`); }
protected onRemoved(entity: Entity): void { console.log(`Health entity removed: ${entity.name}`); }}IntervalSystem - Interval System
Section titled “IntervalSystem - Interval System”Systems that execute at fixed time intervals:
@ECSSystem('AutoSave')class AutoSaveSystem extends IntervalSystem { constructor() { // Execute every 5 seconds super(5.0, Matcher.all(SaveData)); }
protected process(entities: readonly Entity[]): void { console.log('Executing auto save...'); // Save game data this.saveGameData(entities); }
private saveGameData(entities: readonly Entity[]): void { // Save logic }}WorkerEntitySystem - Multi-threaded System
Section titled “WorkerEntitySystem - Multi-threaded System”A Web Worker-based multi-threaded processing system, suitable for compute-intensive tasks, capable of fully utilizing multi-core CPU performance.
Worker systems provide true parallel computing capabilities, support SharedArrayBuffer optimization, and have automatic fallback support. Particularly suitable for physics simulation, particle systems, AI computation, and similar scenarios.
For detailed content, please refer to: Worker System
Entity Matcher
Section titled “Entity Matcher”Matcher is used to define which entities a system needs to process. It provides flexible condition combinations:
Basic Match Conditions
Section titled “Basic Match Conditions”// Must have both Position and Velocity componentsconst matcher1 = Matcher.all(Position, Velocity);
// Must have at least one of Health or Shield componentsconst matcher2 = Matcher.any(Health, Shield);
// Must not have Dead componentconst matcher3 = Matcher.none(Dead);Compound Match Conditions
Section titled “Compound Match Conditions”// Complex combination conditionsconst complexMatcher = Matcher.all(Position, Velocity) .any(Player, Enemy) .none(Dead, Disabled);
@ECSSystem('Combat')class CombatSystem extends EntitySystem { constructor() { super(complexMatcher); }}Special Match Conditions
Section titled “Special Match Conditions”// Match by tagconst tagMatcher = Matcher.byTag(1); // Match entities with tag 1
// Match by nameconst nameMatcher = Matcher.byName("Player"); // Match entities named "Player"
// Single component matchconst componentMatcher = Matcher.byComponent(Health); // Match entities with Health component
// Match no entitiesconst nothingMatcher = Matcher.nothing(); // For systems that only need lifecycle callbacksEmpty Matcher vs Nothing Matcher
Section titled “Empty Matcher vs Nothing Matcher”// empty() - Empty condition, matches all entitiesconst emptyMatcher = Matcher.empty();
// nothing() - Matches no entities, for systems that only need lifecycle methodsconst nothingMatcher = Matcher.nothing();
// Use case: Systems that only need onBegin/onEnd lifecycle@ECSSystem('FrameTimer')class FrameTimerSystem extends EntitySystem { constructor() { super(Matcher.nothing()); // Process no entities }
protected onBegin(): void { // Execute at the start of each frame console.log('Frame started'); }
protected process(entities: readonly Entity[]): void { // Never called because there are no matching entities }
protected onEnd(): void { // Execute at the end of each frame console.log('Frame ended'); }}System Type Selection Guide
Section titled “System Type Selection Guide”| System Type | Use Case |
|---|---|
EntitySystem | General system that processes matched entities one by one |
ProcessingSystem | No entity list needed, only executes global logic |
PassiveSystem | Only listens for entity add/remove events |
IntervalSystem | Executes at fixed time intervals |
WorkerEntitySystem | Compute-intensive tasks requiring multi-threading |