Important
Please participate in the survey here!
(open until end of February)
To achieve a better sample size, I'd highly appreciate if you could circulate the link to this survey in your own networks.
Note
This is one of 189 standalone projects, maintained as part of the @thi.ng/umbrella monorepo and anti-framework.
🚀 Help me to work full-time on these projects by sponsoring me on GitHub. Thank you! ❤️
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)
ALPHA - bleeding edge / work-in-progress
Search or submit any issues for this package
yarn add @thi.ng/ecs
ES module import:
<script type="module" src="https://cdn.skypack.dev/@thi.ng/ecs"></script>
For Node.js REPL:
const ecs = await import("@thi.ng/ecs");
Package sizes (brotli'd, pre-treeshake): ESM: 3.17 KB
- @thi.ng/api
- @thi.ng/associative
- @thi.ng/binary
- @thi.ng/checks
- @thi.ng/dcons
- @thi.ng/errors
- @thi.ng/idgen
- @thi.ng/logger
- @thi.ng/malloc
- @thi.ng/transducers
- tslib
One project in this repo's /examples directory is using this package:
Screenshot | Description | Live demo | Source |
---|---|---|---|
![]() |
Entity Component System w/ 100k 3D particles | Demo | Source |
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 ]
// }
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
}
© 2019 - 2024 Karsten Schmidt // Apache License 2.0