Skip to content

Latest commit

 

History

History

ecs

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

ecs

npm version npm downloads Twitter Follow

This project is part of the @thi.ng/umbrella monorepo.

About

Entity Component System based around typed arrays & sparse sets.

  • Entities are merely numeric identifiers
  • Component types:
    • Numeric / vectors are stored as typed array views with customizable striding
    • arbitrary JS values are stored in vanilla JS arrays
  • Component grouping w/ optional group ownership to allow re-ordering components for optimized iteration
  • Systems are plain functions
  • Configurable caching of component views: LRU, Unbounded, Null (no-cache)

Status

ALPHA - bleeding edge / work-in-progress

Search or submit any issues for this package

Installation

yarn add @thi.ng/ecs

ES module import:

<script type="module" src="https://cdn.skypack.dev/@thi.ng/ecs"></script>

Skypack documentation

For Node.js REPL:

# with flag only for < v16
node --experimental-repl-await

> const ecs = await import("@thi.ng/ecs");

Package sizes (gzipped, pre-treeshake): ESM: 3.11 KB

Dependencies

Usage examples

Several demos in this repo's /examples directory are using this package.

A selection:

Screenshot Description Live demo Source
Entity Component System w/ 100k 3D particles Demo Source

API

Generated API docs

Basic concepts

import { ECS } from "@thi.ng/ecs";

interface ComSpecs {
    pos: Float32Array;
    vel: Float32Array;
    color: string;
}

// init ECS w/ given max number of entities
const ecs = new ECS<CompSpecs>(1000);

// define components (and their memory layout)
const pos = ecs.defComponent({
    id: "pos",
    type: Type.F32,
    size: 2
});

const vel = ecs.defComponent({
    id: "vel",
    type: Type.F32,
    size: 2,
    stride: 4
    default: () => [Math.random()*2-1, Math.random()*2-1]
});

// this component stores string values (not mem-mapped)
const color = ecs.defComponent({
    id: "color",
    default: () => ["red","green","blue"][(Math.random()*3)|0]
});

// define group of given components
// the group will obtain ownership of all by default, meaning
// it is allowed to re-order entities to optimize iteration performance
const group = ecs.defGroup([pos, vel, color]);

// add entities and associate them w/ different components
// if a component is part of a group, the group will be notified/updated
ecs.defEntity(["pos", "vel", "color"]);

ecs.defEntity([pos, vel]);

ecs.defEntity({
    pos: [1, 2],
    vel: [-1, 0],
    color: "red"
});

// apply given function to each entity in the group
// note: entity (id=1) is NOT part of the group,
// since it doesn't have a `color` component...
group.forEach((x) => console.log(x));
// {
//   id: 0,
//   color: 'green',
//   vel: Float32Array [ 0.16836269199848175, -0.36699679493904114 ],
//   pos: Float32Array [ 0, 0 ]
// }
// {
//   id: 2,
//   color: 'blue',
//   vel: Float32Array [ -0.7642428278923035, -0.43176573514938354 ],
//   pos: Float32Array [ 0, 0 ]
// }

Authors

Karsten Schmidt

If this project contributes to an academic publication, please cite it as:

@misc{thing-ecs,
  title = "@thi.ng/ecs",
  author = "Karsten Schmidt",
  note = "https://thi.ng/ecs",
  year = 2019
}

License

© 2019 - 2021 Karsten Schmidt // Apache Software License 2.0