A TypeScript Entity-Component System (ECS) for Node and web browsers.
Visit https://javelin.games for documentation, examples, and external resources.
Entities are organized by their component makeup into Archetypes for quick lookups and iteration. In a small app (10 component types, 10 archetypes, 10 queries), Javelin can iterate ~2.5 million entities per 16ms on a 2GHz Intel i5 processor.
Define your game's data model using plain old JavaScript objects.
const Transform = {
x: float64,
y: float64,
}
const Inventory = {
bags: arrayOf(arrayOf(uint32)),
}
const world = createWorld()
const entity = world.create(
component(Transform), // => { x: 0, y: 0 }
component(Inventory), // => { bags: [] }
)
Use third-party objects as components.
const Mesh = {
position: {
x: number,
y: number,
z: number,
},
}
world.create(toComponent(new Three.Mesh(), Mesh))
Query game state using familiar syntax.
const bodies = createQuery(Transform, Velocity)
const physics = () =>
bodies((e, [t, v]) => {
t.x += v.x
t.y += v.y
})
Best practices are built-in with tools like Topics for inter-system messaging.
const commands = createTopic<PhysicsCommand>()
const movement = () =>
input((e, [input]) => {
if (input.jump) {
commands.push(impulse(e, 0, 10))
}
})
const physics = () => {
for (const command of commands) {
// ...
}
}
and Effects for handling async code, third-party dependencies, and events.
const render = () => {
const scene = useScene()
const model = useLoadGLTF("llama.gltf")
useMonitor(
players,
e => scene.insert(e, model, world.get(e, Transform)),
e => scene.destroy(e),
)
}