Skip to content

Quick Start

npm install @woven-ecs/core

Components are data containers that can be attached to entities. Define them using defineComponent with typed fields:

import { defineComponent, field } from '@woven-ecs/core';
export const Position = defineComponent({
x: field.float32().default(0),
y: field.float32().default(0),
z: field.float32().default(0),
});
export const Velocity = defineComponent({
x: field.float32(),
y: field.float32(),
z: field.float32(),
});

The World is the container that manages all entities, components, and systems:

import { World } from '@woven-ecs/core';
import { Position, Velocity } from './components';
// Create a world with the defined components
const world = new World([Position, Velocity]);
import { createEntity, addComponent, type Context } from '@woven-ecs/core';
// Initialize the world with an entity
world.execute((ctx: Context) => {
// Create an entity
const particle = createEntity(ctx);
// Add components and set data
addComponent(ctx, particle, Position, { x: 100, y: 50, z: 0 });
addComponent(ctx, particle, Velocity, { x: 1, y: 1, z: 0 });
});

Queries find entities that have specific component combinations:

import { defineQuery, type QueryBuilder } from '@woven-ecs/core';
// Find all entities with Position and Velocity
const particles = defineQuery((q: QueryBuilder) =>
q.with(Position, Velocity)
);

Systems are functions that process entities:

import { defineSystem, type Context } from '@woven-ecs/core';
const movementSystem = defineSystem((ctx: Context) => {
for (const eid of particles.current(ctx)) {
const pos = Position.write(ctx, eid);
const vel = Velocity.read(ctx, eid);
pos.x += vel.x;
pos.y += vel.y;
pos.z += vel.z;
}
});
function loop() {
world.execute(movementSystem);
requestAnimationFrame(loop);
}
loop();

Here’s a complete example putting it all together:

import {
World,
defineComponent,
defineQuery,
defineSystem,
defineSingleton,
field,
createEntity,
addComponent,
type Context,
type QueryBuilder,
} from '@woven-ecs/core';
// Components
const Position = defineComponent({
x: field.float32(),
y: field.float32(),
z: field.float32(),
});
const Velocity = defineComponent({
x: field.float32(),
y: field.float32(),
z: field.float32(),
});
// Query
const particles = defineQuery((q: QueryBuilder) =>
q.with(Position, Velocity)
);
// System
const movementSystem = defineSystem((ctx: Context) => {
for (const eid of particles.current(ctx)) {
const pos = Position.write(ctx, eid);
const vel = Velocity.read(ctx, eid);
pos.x += vel.x;
pos.y += vel.y;
pos.z += vel.z;
}
});
// World
const world = new World([Position, Velocity]);
// Initialize with an entity
world.execute((ctx: Context) => {
const particle = createEntity(ctx);
addComponent(ctx, particle, Position, { x: 100, y: 50, z: 0 });
addComponent(ctx, particle, Velocity, { x: 1, y: 1, z: 0 });
});
// Game loop
function loop() {
world.execute(movementSystem);
requestAnimationFrame(loop);
}
loop();
  • Components - Learn about all available field types
  • Systems - Explore worker systems for multithreading
  • Queries - Master change tracking queries