Skip to content
Pedro Clerici edited this page Jul 26, 2025 · 1 revision

Worlds contain your entities and components, and are responsible for executing systems. Every world is independent and self-contained; systems and types can be used by multiple worlds, but data belongs to a single world.

Adding Systems

Worlds can be constructed with new World(config). They may add components, events, and even systems at any point.

import { World, Schedule } from 'thyseus';
import { Inventory, IsPlayer } from './components';

const world = await new World()
	.addSystems(Schedule, inventorySystem)
	.prepare();

The addSystems() method return the World itself so it can be chained. Let's add a few more systems!

import { World, Schedule } from 'thyseus';
import { move, draw, handleInput } from './systems';

const myWorldBuilder = await World.new()
	.addSystems(Schedule, [move, draw, handleInput])
	.prepare();

You'll notice we're calling .prepare() here - after adding all the systems you'd like to get started, you need to prepare the world to run. Some systems require some async setup, so this will return a promise. Any time you add new systems to the world, you'll need to prepare() it again.

import { World } from 'thyseus';

function helloSystem() {
	console.log('Hello, world!')
}

const myWorld = await new World()
	.addSystems(helloSystem)
	.prepare();

Note

Top-level await is a convenient way to handle the promise returned by prepare(), but is not required.

Let's also setup a loop to run your world!

import { World, Schedule } from 'thyseus';

function helloSystem() {
	console.log('Hello, world!')
}

function setup(world: World) {
	async function loop(timeElapsed: number) {
		world.runSchedule(Schedule);
		requestAnimationFrame(loop);
	}
	loop(0);
}

const myWorld = await new World()
	.addSystems(helloSystem)
	.prepare();

const world = await new World()
	.addSystems(helloSystem)
	.addEventListener('start', setup)
	.prepare();

world.start();

Here, we're adding an event listener to the world's "start" event. When start is emitted, we're establishing a loop that runs the default schedule (all systems added with addSystems()) once per frame.

If you look in your browser's log, you should see a whole lot of "Hello, world!"s!

Schedules

Worlds can contain multiple groups of systems called Schedules. Schedules have a number of different uses - creating groups of systems that only runs when your app starts, or when tearing down, or systems that need to run at a fixed rate like physics systems.

Thyseus provides the Schedule class which stores systems and their arguments and handles running them. You can create your own schedules by extending this class - e.g. class PhysicsSchedule extends Schedule {}. When calling addSystems(), you must specify a schedule to add systems to.

Plugins

Plugins are simply functions that accept a World and register systems and types on that World. Plugins give you the flexibility to change the implementation details of a piece of functionality without changing the external API.

import { World, Schedule } from 'thyseus';
import {
	applyForces,
	detectCollisions,
	resolveCollisions,
} from './physicsSystems';

class FixedUpdateSchedule extends Schedule {}

function physicsPlugin(world: World) {
	world.addSystems(FixedUpdateSchedule, [
		applyForces,
		detectCollisions,
		resolveCollisions,
	]);
}

const world = await World.new().addPlugin(physicsPlugin).build();

Clone this wiki locally