Pixi

RenderSync

A system that mirrors ECS entities into renderer nodes.

Every renderer integration does the same bookkeeping: create a node when an entity gains its renderable component, re-apply it when its transform changes, and destroy it when the renderable is removed or the entity despawns. RenderSync.system(...) builds one system that does all three, in a safe order (destroy, create, update), for one bound Game. What a node looks like and how state is applied stay caller-defined.

Change detection is per system, so the system sees every addition, change, and removal exactly once, wherever it sits in the schedule, and applies each node at most once per run: a node created in a run is not applied again for the same changes. redrawOn lists more components whose changes re-run apply, for node state beyond the transform (animation frames, tints, interpolation). Place the system after the applyDeferred() that commits spawns to render new entities in the same tick.

create and apply receive one context: the renderable and transform values, the entity id, extra read-only slots declared in select (as query cells), resources declared in resources (as read cells), and extra services declared in services. Those resources and services become runtime requirements like the registry itself.

Examples

const Sprites = Descriptor.Service<NodeRegistry.NodeRegistry<Sprite>>()("Game/Sprites")

const Render = RenderSync.system(Game, {
  name: "Game/Render",
  renderable: Renderable,
  transform: Position,
  registry: Sprites,
  services: { assets: Assets },
  create: ({ renderable, services }) => new Sprite(services.assets.textures[renderable.texture]),
  apply: (sprite, { transform }) => sprite.position.set(transform.x, transform.y)
})

const update = Game.Schedule(Gameplay, Game.Schedule.applyDeferred(), Render)

Functions

system

Source

Builds the render system for one renderable component.

interpolate

Source

Builds the system that draws moving entities between fixed steps.

A fixed-step simulation moves things in steps; drawing them at their latest position makes motion stutter whenever the display rate differs from the step rate. This system places every node at previous + (current - previous) * alpha, where alpha comes from the loop (FixedLoop's render callback). The game copies current into previous at the start of each step.

const Interpolate = RenderSync.interpolate(Game, {
  name: "Game/Interpolate",
  registry: Sprites,
  previous: PrevPosition,
  current: Position,
  clock: RenderClock,
  place: (sprite, { x, y }) => sprite.position.set(x, y)
})
const render = Game.Schedule(Sync, Interpolate)