Skip to content

Plugins & Resources

An Estella game is an App composed of plugins. Each subsystem — physics, audio, tilemaps, particles, UI, and so on — is a plugin that registers its systems and exposes a runtime API as a resource.

Inside a system, list the resource you need in the parameter array; the callback receives it in the same order:

import { defineSystem, Res, Audio } from 'esengine';
defineSystem([Res(Audio)], (audio) => {
audio.playSFX('assets/hit.wav');
});

Every subsystem’s imperative API is reached the same way:

Subsystem Resource Guide
Input Res(Input) Input
Audio Res(Audio) Audio
Assets Res(Assets) Assets
Tilemaps Res(Tilemaps) Tilemaps
Particles Res(Particle) Particles
Post-processing Res(PostProcess) Post-processing
Scenes Res(SceneManager) Scenes
Tweens Res(Tween) Animation
Frame animation Res(SpriteAnimation) Animation
Animator Res(AnimatorController) Animation
Timers Res(TimerRes) Scripting
Timeline Res(Timeline) Timeline
Prefabs Res(Prefabs) Prefabs
Navigation / AI Res(Nav) Gameplay AI
Localization Res(Localization) Localization
Camera view Res(CameraView) Camera
UI events Res(UIEvents) UI
Physics Res(Physics) — from esengine/physics Physics
Spine Res(Spine) — from esengine/spine Spine

Physics and Spine are optional side-modules loaded on demand, so their APIs live on subpaths to keep the base bundle small; everything else is in the main esengine package. All the base subsystems above ship in the standard app — no plugin wiring needed.

Some subsystems also publish event resources on the same pattern — a resource whose contents are this frame’s events, read the same frame: Res(PhysicsEvents) (contacts), Res(SpineEvents) (animation events), Res(UIEvents) (clicks and input from widgets).


Res(X) gives read access; use ResMut(X) when the system replaces or mutates the resource’s state — same contract as Mut on components.

  • Components are per-entity data. You attach them (in the editor or with Commands) and iterate them with Query.
  • Resources are per-app singletons — shared state and subsystem APIs — read with Res.

Subsystem APIs act on an entity, and that entity comes from a Query (or a spawn). This is the shape you’ll see throughout the guides:

import { defineSystem, Query, Res, SpriteAnimator, Tween, TweenTarget } from 'esengine';
defineSystem([Query(SpriteAnimator), Res(Tween)], (q, tween) => {
for (const [entity] of q) {
tween.to(entity, TweenTarget.PositionX, 0, 100, 1.0, {});
}
});

To create entities and attach components from a system, take Commands():

import { defineSystem, Commands, Transform, Sprite } from 'esengine';
defineSystem([Commands()], (cmds) => {
cmds.spawn()
.insert(Transform, { position: { x: 0, y: 0, z: 0 } })
.insert(Sprite, { size: { x: 32, y: 32 } });
});