Class Ecs

Entity Component System instance

Constructors

  • Construct a new ECS instance.

    The instance can be configured to defer mutating operations assign, remove, and destroy by default by passing { defer: true } to the constructor.

    Parameters

    • options: {
          defer: boolean;
      } = ...

      Options to configure the ECS

      • defer: boolean

        True to defer mutating operations by default, defaults to false.

    Returns Ecs

Properties

#entityDependencies: Map<number, Store<any>[]> = ...
#options: {
    defer: boolean;
} = ...

Type declaration

  • defer: boolean
#pending: {
    component?: any;
    entity: number;
    type: "remove" | "assign" | "destroy";
}[] = []

Type declaration

  • Optional component?: any
  • entity: number
  • type: "remove" | "assign" | "destroy"
#registry: Registry = ...
#stores: Map<Function, Store<any>> = ...

Methods

  • Parameters

    • entity: number
    • store: Store<any>

    Returns void

  • Parameters

    • tag: Function

    Returns Store<any>

  • Assign a component to an entity.

    Each entity can only have one component of a given type.

    There are two overloads to assign

    1. Component types and (optional) property values
    2. Component instances

    Type Parameters

    • T extends unknown

      component type

    Parameters

    • entity: number

      the entity to assign the component

    • component: T | Constructor<T>

      either the component to add or the type of component to add

    • Optional value: Partial<T> = undefined

      a plain object used to assign property values to the component instance

    • Optional defer: boolean = ...

      defer this operation until the next commit. defaults to the value passed into the constructor

    Returns T

    the assigned component instance

    Example

    // component type + data
    class Position { x = 0; y = 0 }
    const ecs = new Ecs()
    const e = ecs.create()
    ecs.assign(e, Position, { x: 20, y: 30 })

    Example

    // component type, no data (for 'tagging' components)
    class Vulnerable { }
    const ecs = new Ecs()
    const e = ecs.create()
    ecs.assign(e, Vulnerable)

    Example

    // component instance
    class Speed {
    amount = 0
    constructor(mode) {
    this.amount = mode === 'fast' ? 10 : 1
    }
    }
    const ecs = new Ecs()
    const e = ecs.create()
    ecs.assign(e, new Speed('fast'))
  • Commits all deferred assign, remove, and destroy operations and resets internal deferral state.

    When deferring operations it is a good idea to commit all operations at the start or end of the frame. That way your view of entities and components is stable during a frame.

    Returns void

    Example

    class Position { x=0; y=0 }
    const ecs = new Ecs({ defer: true })
    const e = ecs.create()
    ecs.assign(e, Position, { x: 10, y: 20 })
    ecs.has(e, Position) // false
    ecs.get(e, Position) // null

    ecs.commit()

    ecs.has(e, Position) // true
    ecs.get(e, Position) // Position { x:10, y:20 }
  • Create a fresh entity.

    Even though entities are just numbers, you should only use this method to allocate them. Entities created with this method are guaranteed to be unique and valid. Don't create entities any other way.

    Returns number

    Example

    const ecs = new Ecs()
    const e = ecs.create()
    ecs.isValid(e) // => true
  • Destroy an entity.

    Parameters

    • entity: number
    • Optional defer: boolean = ...

      defer this operation until the next commit. defaults to the value passed into the constructor

    Returns void

    Example

    const ecs = new Ecs()
    const e = ecs.create()
    ecs.isValid(e) // => true
    ecs.destroy(e)
    ecs.isValid(e) // => false
  • Iterate each entity that contains component matching componentTypes.

    Every resulting entity is guaranteed to have a component of every type provided in `componentTypes.

    Parameters

    • Rest ...componentTypes: Constructor<any>[]

      the types of components to query for

    Returns Generator<number, void, unknown>

    a generator of all matching entities

    Example

    class Gremlin {}
    class Goblin {}
    class Spooky { amount=0 }

    const ecs = new Ecs()

    for(let i=0; i<1000; i++) {
    const e = ecs.create()
    if(Math.random() < 0.5)
    ecs.assign(e, Goblin)
    else
    ecs.assign(e, Gremlin)
    if(Math.random() < 0.25)
    ecs.assign(e, Spooky, { amount: Math.random() })
    }

    // iterate all gremlins
    for(const e of ecs.each(Gremlin)) {
    ecs.get(e, Gremlin) // guaranteed not null
    if(ecs.has(e, Spooky)) // might be null, check with has
    ecs.get(e, Spooky)
    }

    // iterate all goblins
    for(const e of ecs.each(Goblin)) {
    ecs.get(e, Goblin) // guaranteed not null
    if(ecs.has(e, Spooky)) // might be null, check with has
    ecs.get(e, Spooky)
    }

    // iterate all spooky goblins
    for(const e of ecs.each(Spooky, Goblin)) {
    ecs.get(e, Goblin) // guaranteed not null
    ecs.get(e, Spooky) // guaranteed not null
    }
  • Find an entity that has all of the given components

    Only one entity is assumed to match. If there is more than one matching entity which entity is returned is undefined.

    Parameters

    Returns number | void

    Example

    const e = ecs.create()
    ecs.assign(e, Player)
    ecs.find(Player) === e // true
  • Get a component of a given type from an entity if its been assigned

    Throws an exception if the entity has not been assigned the component. Safe to use when iterating with each and when you otherwise know component has been assigned to entity, otherwise use has to check for component's assignment or use tryGet to return null rather than throw when component is missing.

    Type Parameters

    • T extends unknown

      component type

    Parameters

    • entity: number

      the entity to get the component from

    • component: Constructor<T>

      the component to get

    Returns T

    The component instance if it was assigned to entity

    Example

    class Player {}
    class Position { x=0; y=0 }
    class Enemy {}

    const ecs = new Ecs()
    const e = ecs.create()
    const f = ecs.create()
    ecs.assign(e, Player)
    ecs.assign(e, Position, { x: 20, y: 80 })
    ecs.assign(f, Enemy)
    ecs.assign(f, Position, { x: 40, y: 90 })

    ecs.get(e, Player) // => Player {}
    ecs.get(e, Position) // => Position { x: 20, y: 80 }
    ecs.get(e, Position).x // => 20
    ecs.get(e, Enemy) // => throws exception
    ecs.get(f, Player) // => throws exception
    ecs.get(f, Position) // => Position { x: 40, y: 90 }
    ecs.get(f, Position).y // => 90
    ecs.get(f, Enemy) // => Enemy {}

    Throws

    if entity was not assigned component

  • Check if a component of a given type has been assigned to an entity

    Type Parameters

    • T extends unknown

      component type

    Parameters

    • entity: number

      the entity to get the component from

    • component: Constructor<T>

      the component to get

    Returns boolean

    true if entity has a component assigned to it, false otherwise

    Example

    class Player {}
    class Position { x=0; y=0 }
    class Enemy {}

    const ecs = new Ecs()
    const e = ecs.create()
    const f = ecs.create()
    ecs.assign(e, Player)
    ecs.assign(e, Position, { x: 20, y: 80 })
    ecs.assign(f, Enemy)
    ecs.assign(f, Position, { x: 40, y: 90 })

    ecs.has(e, Player) // => true
    ecs.has(e, Position) // => true
    ecs.has(e, Enemy) // => false
    ecs.has(f, Player) // => false
    ecs.has(f, Position) // => true
    ecs.has(f, Enemy) // => true
  • Check if an entity value is still valid.

    A valid entity is one that was created by this ECS instance and has not been destroyed yet.

    This method is useful when you store entity values in different places in your code and need to check if they were destroyed at some point.

    Parameters

    • entity: number

    Returns boolean

    Example

    const ecs = new Ecs()
    const e = ecs.create()
    ecs.isValid(e) // true
    ecs.destroy(e)
    ecs.isValid(e) // false
  • Remove a component from an entity

    Type Parameters

    • T extends unknown

    Parameters

    • entity: number
    • component: Constructor<T>
    • Optional defer: boolean = ...

      defer this operation until the next commit. defaults to the value passed into the constructor

    Returns void

    Example

    class Position { x=0; y=0 }
    class InBounds {}
    for(const e of ecs.each(Position, InBounds)) {
    const p = ecs.get(e, Position)
    if(p.x < 0 || p.x > 10 || p.y < 0 || p.y > 10)
    ecs.remove(e, InBounds)
    }
  • Get a component of a given type from an entity or null if it has not been assigned.

    Similar to get with a less convenient return type. Always safe to call.

    Type Parameters

    • T extends unknown

    Parameters

    Returns T

    Example

    class Player {}
    class Enemy {}

    const ecs = new Ecs()
    const e = ecs.create()
    const f = ecs.create()
    ecs.assign(e, Player)
    ecs.assign(f, Enemy)

    ecs.tryGet(e, Player) // => Player {}
    ecs.tryGet(f, Enemy) // => Enemy {}
    ecs.tryGet(e, Enemy) // => null
    ecs.tryGet(f, Player) // => null