ignifx0.x · unpublished
GitHub

API reference·skills/ignifx/references/api/2d.md

@ignifx/2d

@ignifx/2d public barrel: Camera2D, SpriteRenderer, SpriteAnimator, atlases, Tilemap, sorting layers, pixel-perfect rendering, parallax, and 2D picking (docs/architecture/11-2d-toolkit.md). Explicit named re-exports only — no export * (coding standards §4).

Classes#

Camera2D#

The 2D camera.

Remarks#

orthographicSize is a half-height in metres, exactly as Unity's orthographic camera is, so the zoom it produces is viewportHeightPx / (2 · size · PPU). With pixelPerfect on, that zoom is snapped to a whole number (or to 1/n when the camera is pulled far out) and the camera's position is snapped to the pixel grid at sync time — scripts keep their sub-pixel positions, so movement stays smooth even though drawing does not.

Example#

typescript
const camera = app.world.createEntity({ name: "camera" }).addComponent(Camera2D);camera.orthographicSize = 3;camera.pixelPerfect = true;

Extends#

  • Component

Constructors#

Constructor#

new Camera2D(): Camera2D

Builds a camera with the schema's defaults.

Returns#

Camera2D

Overrides#

Component.constructor

Properties#

allowMultiple#

static allowMultiple: boolean = false

One camera per entity.

boundsMax#

boundsMax: Vec2Like | null

The upper bound of the camera's travel, in metres, or null for no bound.

boundsMin#

boundsMin: Vec2Like | null

The lower bound of the camera's travel, in metres, or null for no bound.

deadZone#

deadZone: Vec2Like

The half-size of the rectangle the target may move inside before the camera reacts, in metres.

follow#

follow: Entity | null

The entity this camera follows, or null. Read by Camera2DFollow.

followDamping#

followDamping: number

How long the follow takes to catch up, in seconds.

followOffset#

followOffset: Vec2Like

A constant offset added to the followed entity's position, in metres.

orthographicSize#

orthographicSize: number

Half the viewport height, in metres.

pixelPerfect#

pixelPerfect: boolean

Whether zoom snaps to an integer and positions snap to the pixel grid.

priority#

priority: number

Highest wins when a world has several enabled cameras.

referenceResolution#

referenceResolution: Vec2Like

The design resolution a pixel-perfect camera fits an integer zoom to, in pixels.

schema#

static schema: Schema

The declarative fields (ADR-0004).

typeId#

static typeId: string = "ignifx/Camera2D"

The registration id the serializer writes into scene files.

Accessors#

app#
Get Signature#

get app(): App

The app that owns the world.

Returns#

App

The app.

Inherited from#

Component.app

centre#
Get Signature#

get centre(): Vec2Like

The world point the camera is centred on, after bounds clamping and pixel-perfect snapping.

Returns#

Vec2Like

A read-only view of the centre, in metres.

enabled#
Get Signature#

get enabled(): boolean

The component's own enabled flag; true by default. Setting it runs the enable or disable transition (docs/architecture/01-lifecycle-and-time.md §6): onDisable runs immediately, awake/onEnable run in the next lifecycle flush — or immediately and nested when the change happens inside a callback.

Returns#

boolean

true when the component's own flag is set.

Set Signature#

set enabled(value): void

Parameters#
value#

boolean

Returns#

void

Inherited from#

Component.enabled

entity#
Get Signature#

get entity(): Entity

The entity this component is attached to.

Returns#

Entity

The owning entity.

Inherited from#

Component.entity

handle#
Get Signature#

get handle(): ComponentHandle

The dense runtime handle; invalid after destruction.

Returns#

ComponentHandle

The handle.

Inherited from#

Component.handle

isDestroyed#
Get Signature#

get isDestroyed(): boolean

true from the moment destroy() is called, long before the destroy flush runs.

Returns#

boolean

true once the component has been queued for destruction.

Inherited from#

Component.isDestroyed

isEnabledInHierarchy#
Get Signature#

get isEnabledInHierarchy(): boolean

true when the component's own flag is set and its entity is active in the hierarchy.

Returns#

boolean

true when the component is effectively enabled.

Inherited from#

Component.isEnabledInHierarchy

onDestroyed#
Get Signature#

get onDestroyed(): Signal<Component>

Emitted once when the component is destroyed, in the destroy flush. Connecting with { owner: this } elsewhere uses it to detach handlers automatically (docs/architecture/02-scene-graph.md §8).

Returns#

Signal<Component>

The signal. It is created on first access, so a component nobody listens to allocates nothing.

Inherited from#

Component.onDestroyed

transform#
Get Signature#

get transform(): Transform

The entity's transform — sugar for this.entity.transform, the most-used lookup there is.

Returns#

Transform

The entity's transform.

Inherited from#

Component.transform

uid#
Get Signature#

get uid(): string

The stable ULID; the key files use to reference this component.

Returns#

string

The identifier.

Inherited from#

Component.uid

viewportSizePx#
Get Signature#

get viewportSizePx(): Vec2Like

The viewport the camera last measured, in pixels.

Returns#

Vec2Like

A read-only view of the size.

world#
Get Signature#

get world(): World

The world the entity belongs to.

Returns#

World

The world.

Inherited from#

Component.world

zoom#
Get Signature#

get zoom(): number

The zoom the camera last resolved to — Sprite2DView.zoom.

Returns#

number

The zoom; 1 before the first sync.

Methods#

define()#

static define<S>(schema): ComponentDefinition<S>

Declares a component's serialized fields and returns the base class to extend (ADR-0004, docs/architecture/03-scripting-and-components.md §3). The returned class exposes every field as a typed instance property, applies the defaults in its constructor, and carries the schema for the serializer, the inspector, and the docs harness.

Type Parameters#
S#

S extends Readonly<Record<string, FieldDefinition<unknown>>>

The schema being declared.

Parameters#
schema#

S

The field definitions, keyed by the property name they become.

Returns#

ComponentDefinition<S>

An abstract class to extend.

Throws#

IgnifxError with code IGX-0607 when a field name is not identifier-like or collides with a Component/Script member.

Example#
typescript
class Spinner extends Component.define({  degreesPerSecond: f32(90, { min: -360, max: 360 }),  axis: vec3({ x: 0, y: 1, z: 0 }),}) {  static typeId = "mygame/Spinner";}
Inherited from#

Component.define

destroy()#

destroy(): void

Queues this component for destruction. It stays usable until the destroy flush of the current frame, but reports isDestroyed === true immediately (docs/architecture/01-lifecycle-and-time.md §6). Calling it twice is a no-op.

Returns#

void

Inherited from#

Component.destroy

getComponent()#

getComponent<T>(type): T | null

Finds another component on the same entity — sugar for this.entity.getComponent.

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class; matching is by class identity and inheritance.

Returns#

T | null

The first match in attach order, or null.

Inherited from#

Component.getComponent

requireComponent()#

requireComponent<T>(type): T

Finds another component on the same entity, requiring it to be there — the supported way to link components (docs/architecture/03-scripting-and-components.md §8).

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class.

Returns#

T

The first match in attach order.

Throws#

IgnifxError with code IGX-0201 when the entity has no such component.

Inherited from#

Component.requireComponent

screenToWorld()#

screenToWorld(x, y, out?): MutableVec2

Converts a viewport pixel into a world point.

Parameters#
x#

number

The viewport x, in pixels from the left edge.

y#

number

The viewport y, in pixels from the top edge.

out?#

MutableVec2 = ...

The vector to write; omitting it allocates one.

Returns#

MutableVec2

out, in world metres.

Remarks#

x and y are measured from the surface's top-left corner, which is what a PointerEvent reports and what @ignifx/input's pointer position carries. The result is in metres with +Y up. Before the first frame has synced, the camera has no viewport and the result is the camera's own centre.

Example#
typescript
const world = camera.screenToWorld(pointer.x, pointer.y);
worldToScreen()#

worldToScreen(point, out?): MutableVec2

Converts a world point into a viewport pixel.

Parameters#
point#

Vec2Like

The world point, in metres.

out?#

MutableVec2 = ...

The vector to write; omitting it allocates one.

Returns#

MutableVec2

out, in pixels from the surface's top-left corner.


Camera2DFollow#

A damped, dead-zoned camera follow.

Example#

typescript
const camera = app.world.createEntity({ name: "camera" });const view = camera.addComponent(Camera2D);view.follow = player;view.deadZone = { x: 0.5, y: 0.3 };camera.addComponent(Camera2DFollow);

Extends#

  • Script

Constructors#

Constructor#

new Camera2DFollow(): Camera2DFollow

Creates a component. The engine constructs components; game code never calls new.

Returns#

Camera2DFollow

Inherited from#

Script.constructor

Properties#

allowMultiple#

static allowMultiple: boolean = false

One follow per entity.

typeId#

static typeId: string = "ignifx/Camera2DFollow"

The registration id the serializer writes into scene files.

Accessors#

app#
Get Signature#

get app(): App

The app that owns the world.

Returns#

App

The app.

Inherited from#

Script.app

enabled#
Get Signature#

get enabled(): boolean

The component's own enabled flag; true by default. Setting it runs the enable or disable transition (docs/architecture/01-lifecycle-and-time.md §6): onDisable runs immediately, awake/onEnable run in the next lifecycle flush — or immediately and nested when the change happens inside a callback.

Returns#

boolean

true when the component's own flag is set.

Set Signature#

set enabled(value): void

Parameters#
value#

boolean

Returns#

void

Inherited from#

Script.enabled

entity#
Get Signature#

get entity(): Entity

The entity this component is attached to.

Returns#

Entity

The owning entity.

Inherited from#

Script.entity

handle#
Get Signature#

get handle(): ComponentHandle

The dense runtime handle; invalid after destruction.

Returns#

ComponentHandle

The handle.

Inherited from#

Script.handle

isDestroyed#
Get Signature#

get isDestroyed(): boolean

true from the moment destroy() is called, long before the destroy flush runs.

Returns#

boolean

true once the component has been queued for destruction.

Inherited from#

Script.isDestroyed

isEnabledInHierarchy#
Get Signature#

get isEnabledInHierarchy(): boolean

true when the component's own flag is set and its entity is active in the hierarchy.

Returns#

boolean

true when the component is effectively enabled.

Inherited from#

Script.isEnabledInHierarchy

onDestroyed#
Get Signature#

get onDestroyed(): Signal<Component>

Emitted once when the component is destroyed, in the destroy flush. Connecting with { owner: this } elsewhere uses it to detach handlers automatically (docs/architecture/02-scene-graph.md §8).

Returns#

Signal<Component>

The signal. It is created on first access, so a component nobody listens to allocates nothing.

Inherited from#

Script.onDestroyed

transform#
Get Signature#

get transform(): Transform

The entity's transform — sugar for this.entity.transform, the most-used lookup there is.

Returns#

Transform

The entity's transform.

Inherited from#

Script.transform

uid#
Get Signature#

get uid(): string

The stable ULID; the key files use to reference this component.

Returns#

string

The identifier.

Inherited from#

Script.uid

world#
Get Signature#

get world(): World

The world the entity belongs to.

Returns#

World

The world.

Inherited from#

Script.world

Methods#

awake()#

awake(): void

Finds the camera on this entity.

Returns#

void

define()#

static define<S>(schema): ScriptDefinition<S>

Declares a script's serialized fields and returns the base class to extend — the Script counterpart of Component.define.

Type Parameters#
S#

S extends Readonly<Record<string, FieldDefinition<unknown>>>

The schema being declared.

Parameters#
schema#

S

The field definitions, keyed by the property name they become.

Returns#

ScriptDefinition<S>

An abstract class to extend.

Throws#

IgnifxError with code IGX-0607 when a field name is not identifier-like or collides with a Component/Script member.

Example#
typescript
class Patrol extends Script.define({ waypoints: array(vec3()), speed: f32(3) }) {  static typeId = "mygame/Patrol";}
Inherited from#

Script.define

destroy()#

destroy(): void

Queues this component for destruction. It stays usable until the destroy flush of the current frame, but reports isDestroyed === true immediately (docs/architecture/01-lifecycle-and-time.md §6). Calling it twice is a no-op.

Returns#

void

Inherited from#

Script.destroy

getComponent()#

getComponent<T>(type): T | null

Finds another component on the same entity — sugar for this.entity.getComponent.

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class; matching is by class identity and inheritance.

Returns#

T | null

The first match in attach order, or null.

Inherited from#

Script.getComponent

lateUpdate()#

lateUpdate(deltaTime): void

Moves the camera toward its target.

Parameters#
deltaTime#

number

The scaled frame delta.

Returns#

void

Remarks#

The damping is frame-rate independent: the camera covers the same fraction of the remaining distance per second, not per frame, so a 30 fps machine and a 144 fps machine see the same motion. followDamping is the time constant in seconds; 0 snaps.

requireComponent()#

requireComponent<T>(type): T

Finds another component on the same entity, requiring it to be there — the supported way to link components (docs/architecture/03-scripting-and-components.md §8).

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class.

Returns#

T

The first match in attach order.

Throws#

IgnifxError with code IGX-0201 when the entity has no such component.

Inherited from#

Script.requireComponent

startCoroutine()#

startCoroutine(routine): CoroutineHandle

Starts a coroutine owned by this script (docs/architecture/01-lifecycle-and-time.md §5). The coroutine is paused while the script is not effectively enabled and cancelled when it is destroyed.

Parameters#
routine#

Coroutine

The generator to drive. Call the generator function: this.spawnLoop().

Returns#

CoroutineHandle

A handle for stopping it or waiting on it.

Example#
typescript
blink() {  while (true) {    this.renderer.enabled = !this.renderer.enabled;    yield waitSeconds(0.2);  }}onEnable(): void {  this.startCoroutine(this.blink());}
Inherited from#

Script.startCoroutine

stopAllCoroutines()#

stopAllCoroutines(): void

Stops every coroutine this script started.

Returns#

void

Inherited from#

Script.stopAllCoroutines

stopCoroutine()#

stopCoroutine(handle): void

Stops one coroutine this script started. Stopping a finished coroutine is a no-op.

Parameters#
handle#

CoroutineHandle

The handle Script.startCoroutine returned.

Returns#

void

Inherited from#

Script.stopCoroutine


ParallaxLayer#

A parallax layer.

Example#

typescript
const sky = app.world.createEntity({ name: "sky" }).addComponent(ParallaxLayer);sky.sortingLayer = "Background";sky.factor = { x: 0.2, y: 0.5 };

Extends#

  • Component

Constructors#

Constructor#

new ParallaxLayer(): ParallaxLayer

Builds a parallax layer with the schema's defaults.

Returns#

ParallaxLayer

Overrides#

Component.constructor

Properties#

allowMultiple#

static allowMultiple: boolean = false

One parallax setting per entity; several entities may each drive a different sorting layer.

factor#

factor: Vec2Like

How much of the camera's motion the layer follows, per axis; 1 is no parallax.

repeatHeight#

repeatHeight: number

The world height one repetition spans, in metres.

repeatWidth#

repeatWidth: number

The world width one repetition spans, in metres; 0 disables horizontal repetition.

repeatX#

repeatX: boolean

Whether the layer's sprites repeat horizontally across the camera's view.

repeatY#

repeatY: boolean

Whether the layer's sprites repeat vertically.

schema#

static schema: Schema

The declarative fields (ADR-0004).

sortingLayer#

sortingLayer: string

Which sorting layer this component slows down.

typeId#

static typeId: string = "ignifx/ParallaxLayer"

The registration id the serializer writes into scene files.

Accessors#

app#
Get Signature#

get app(): App

The app that owns the world.

Returns#

App

The app.

Inherited from#

Component.app

enabled#
Get Signature#

get enabled(): boolean

The component's own enabled flag; true by default. Setting it runs the enable or disable transition (docs/architecture/01-lifecycle-and-time.md §6): onDisable runs immediately, awake/onEnable run in the next lifecycle flush — or immediately and nested when the change happens inside a callback.

Returns#

boolean

true when the component's own flag is set.

Set Signature#

set enabled(value): void

Parameters#
value#

boolean

Returns#

void

Inherited from#

Component.enabled

entity#
Get Signature#

get entity(): Entity

The entity this component is attached to.

Returns#

Entity

The owning entity.

Inherited from#

Component.entity

handle#
Get Signature#

get handle(): ComponentHandle

The dense runtime handle; invalid after destruction.

Returns#

ComponentHandle

The handle.

Inherited from#

Component.handle

isDestroyed#
Get Signature#

get isDestroyed(): boolean

true from the moment destroy() is called, long before the destroy flush runs.

Returns#

boolean

true once the component has been queued for destruction.

Inherited from#

Component.isDestroyed

isEnabledInHierarchy#
Get Signature#

get isEnabledInHierarchy(): boolean

true when the component's own flag is set and its entity is active in the hierarchy.

Returns#

boolean

true when the component is effectively enabled.

Inherited from#

Component.isEnabledInHierarchy

onDestroyed#
Get Signature#

get onDestroyed(): Signal<Component>

Emitted once when the component is destroyed, in the destroy flush. Connecting with { owner: this } elsewhere uses it to detach handlers automatically (docs/architecture/02-scene-graph.md §8).

Returns#

Signal<Component>

The signal. It is created on first access, so a component nobody listens to allocates nothing.

Inherited from#

Component.onDestroyed

transform#
Get Signature#

get transform(): Transform

The entity's transform — sugar for this.entity.transform, the most-used lookup there is.

Returns#

Transform

The entity's transform.

Inherited from#

Component.transform

uid#
Get Signature#

get uid(): string

The stable ULID; the key files use to reference this component.

Returns#

string

The identifier.

Inherited from#

Component.uid

world#
Get Signature#

get world(): World

The world the entity belongs to.

Returns#

World

The world.

Inherited from#

Component.world

Methods#

define()#

static define<S>(schema): ComponentDefinition<S>

Declares a component's serialized fields and returns the base class to extend (ADR-0004, docs/architecture/03-scripting-and-components.md §3). The returned class exposes every field as a typed instance property, applies the defaults in its constructor, and carries the schema for the serializer, the inspector, and the docs harness.

Type Parameters#
S#

S extends Readonly<Record<string, FieldDefinition<unknown>>>

The schema being declared.

Parameters#
schema#

S

The field definitions, keyed by the property name they become.

Returns#

ComponentDefinition<S>

An abstract class to extend.

Throws#

IgnifxError with code IGX-0607 when a field name is not identifier-like or collides with a Component/Script member.

Example#
typescript
class Spinner extends Component.define({  degreesPerSecond: f32(90, { min: -360, max: 360 }),  axis: vec3({ x: 0, y: 1, z: 0 }),}) {  static typeId = "mygame/Spinner";}
Inherited from#

Component.define

destroy()#

destroy(): void

Queues this component for destruction. It stays usable until the destroy flush of the current frame, but reports isDestroyed === true immediately (docs/architecture/01-lifecycle-and-time.md §6). Calling it twice is a no-op.

Returns#

void

Inherited from#

Component.destroy

getComponent()#

getComponent<T>(type): T | null

Finds another component on the same entity — sugar for this.entity.getComponent.

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class; matching is by class identity and inheritance.

Returns#

T | null

The first match in attach order, or null.

Inherited from#

Component.getComponent

requireComponent()#

requireComponent<T>(type): T

Finds another component on the same entity, requiring it to be there — the supported way to link components (docs/architecture/03-scripting-and-components.md §8).

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class.

Returns#

T

The first match in attach order.

Throws#

IgnifxError with code IGX-0201 when the entity has no such component.

Inherited from#

Component.requireComponent


SortingLayerTable#

Resolves sorting-layer names to draw orders.

Example#

typescript
const layers = new SortingLayerTable(["Background", "Default", "Foreground"]);layers.indexOf("Foreground"); // 2

Constructors#

Constructor#

new SortingLayerTable(names): SortingLayerTable

Builds the table from the project's sortingLayers section.

Parameters#
names#

readonly string[]

The names, back to front. An empty list falls back to ["Default"].

Returns#

SortingLayerTable

Accessors#

names#
Get Signature#

get names(): readonly string[]

The layer names, back to front.

Returns#

readonly string[]

The names.

Methods#

indexOf()#

indexOf(name): number

Resolves a name to its index.

Parameters#
name#

string

The sorting layer name.

Returns#

number

The index, or -1 when the project declares no such layer.

orderOf()#

orderOf(name): number

The Lite Sprite2DLayer.order a sorting layer's sub-layers start at.

Parameters#
name#

string

The sorting layer name.

Returns#

number

The base order.

Throws#

IgnifxError with code IGX-1107 when the project declares no such layer.

require()#

require(name): number

Resolves a name to its index and refuses to guess.

Parameters#
name#

string

The sorting layer name.

Returns#

number

The index.

Throws#

IgnifxError with code IGX-1107 when the project declares no such layer.


SpriteAnimationAsset#

A loaded sprite-animation document.

Remarks#

Resolution needs an atlas, and a document may be loaded before, after, or without one. The asset therefore keeps the parsed clips and resolves them lazily the first time an atlas is offered; SpriteAnimator offers its renderer's atlas. Under a headless app everything here works unchanged, which is what makes animation timing testable with app.step.

Example#

typescript
const clips = await app.assets.load<SpriteAnimationAsset>("2d/hero.spriteanim.json").promise;clips.clipNames(); // ["idle", "run"]

Properties#

address#

readonly address: string

The address the document was loaded from.

assetType#

static assetType: string = SPRITE_ANIMATION_ASSET_TYPE

The type name the asset service registers animation documents under.

atlasAddress#

readonly atlasAddress: string

The atlas address the document names, already resolved against its own address.

definition#

readonly definition: SpriteAnimationDefinition

The parsed document.

Accessors#

defaultClipName#
Get Signature#

get defaultClipName(): string

The name of the clip a component that names none plays.

Returns#

string

The first clip's name, or "" when the document is empty.

Methods#

clipNames()#

clipNames(): readonly string[]

Every clip name, in declaration order.

Returns#

readonly string[]

A freshly allocated array.

requireClip()#

requireClip(name, atlas): SpriteClip

Looks a clip up, resolving against an atlas first.

Parameters#
name#

string

The clip name.

atlas#

SpriteAtlasAsset

The atlas the frame names index into.

Returns#

SpriteClip

The clip.

Throws#

IgnifxError with code IGX-1108 when the document declares no such clip.

resolve()#

resolve(atlas): ReadonlyMap<string, SpriteClip>

Resolves every clip's frame names against an atlas.

Parameters#
atlas#

SpriteAtlasAsset

The atlas the frame names index into.

Returns#

ReadonlyMap<string, SpriteClip>

The clips, keyed by name.

Remarks#

The result is cached against the atlas it was resolved with, so playing ten characters off one atlas resolves once. Offering a different atlas re-resolves.


SpriteAnimator#

A sprite animator.

Example#

typescript
const animator = hero.addComponent(SpriteAnimator);animator.animations = app.assets.load<SpriteAnimationAsset>("2d/hero.spriteanim.json").retain();animator.onEvent.connect((name) => { if (name === "footstep") playStep(); }, { owner: animator });animator.play("run");

Extends#

  • Component

Implements#

  • ComponentHooks

Constructors#

Constructor#

new SpriteAnimator(): SpriteAnimator

Builds an animator with the schema's defaults.

Returns#

SpriteAnimator

Overrides#

Component.constructor

Properties#

allowMultiple#

static allowMultiple: boolean = false

One animator per entity.

animations#

animations: AssetHandle<SpriteAnimationAsset> | null

The document holding the clips.

defaultClip#

defaultClip: string

Which clip to start on; empty plays the document's first.

playOnAwake#

playOnAwake: boolean

Whether the default clip starts as soon as the document has loaded.

schema#

static schema: Schema

The declarative fields (ADR-0004).

speed#

speed: number

A multiplier on the clip's own frame rate.

typeId#

static typeId: string = "ignifx/SpriteAnimator"

The registration id the serializer writes into scene files.

Accessors#

app#
Get Signature#

get app(): App

The app that owns the world.

Returns#

App

The app.

Inherited from#

Component.app

asset#
Get Signature#

get asset(): SpriteAnimationAsset | null

The loaded animation document, or null while it is still loading.

Returns#

SpriteAnimationAsset | null

The document.

clip#
Get Signature#

get clip(): SpriteClip | null

The clip currently playing, or null.

Returns#

SpriteClip | null

The clip.

enabled#
Get Signature#

get enabled(): boolean

The component's own enabled flag; true by default. Setting it runs the enable or disable transition (docs/architecture/01-lifecycle-and-time.md §6): onDisable runs immediately, awake/onEnable run in the next lifecycle flush — or immediately and nested when the change happens inside a callback.

Returns#

boolean

true when the component's own flag is set.

Set Signature#

set enabled(value): void

Parameters#
value#

boolean

Returns#

void

Inherited from#

Component.enabled

entity#
Get Signature#

get entity(): Entity

The entity this component is attached to.

Returns#

Entity

The owning entity.

Inherited from#

Component.entity

frame#
Get Signature#

get frame(): number

The atlas frame index the animator last wrote.

Returns#

number

The frame index, or -1 when no clip is playing.

handle#
Get Signature#

get handle(): ComponentHandle

The dense runtime handle; invalid after destruction.

Returns#

ComponentHandle

The handle.

Inherited from#

Component.handle

isDestroyed#
Get Signature#

get isDestroyed(): boolean

true from the moment destroy() is called, long before the destroy flush runs.

Returns#

boolean

true once the component has been queued for destruction.

Inherited from#

Component.isDestroyed

isEnabledInHierarchy#
Get Signature#

get isEnabledInHierarchy(): boolean

true when the component's own flag is set and its entity is active in the hierarchy.

Returns#

boolean

true when the component is effectively enabled.

Inherited from#

Component.isEnabledInHierarchy

isPlaying#
Get Signature#

get isPlaying(): boolean

Whether a clip is currently advancing.

Returns#

boolean

true while playing.

onClipEnded#
Get Signature#

get onClipEnded(): Signal<string>

Emitted with a clip's name when a non-looping clip reaches its last frame.

Returns#

Signal<string>

The signal.

onDestroyed#
Get Signature#

get onDestroyed(): Signal<Component>

Emitted once when the component is destroyed, in the destroy flush. Connecting with { owner: this } elsewhere uses it to detach handlers automatically (docs/architecture/02-scene-graph.md §8).

Returns#

Signal<Component>

The signal. It is created on first access, so a component nobody listens to allocates nothing.

Inherited from#

Component.onDestroyed

onEvent#
Get Signature#

get onEvent(): Signal<string>

Emitted with an event's name when playback passes the frame that declares it.

Remarks#

A looping clip fires each event once per pass. A clip advanced by more than one frame in a single step — a long frame, or a high speed — fires every event it skipped over, in order, so a footstep is never silently dropped.

Returns#

Signal<string>

The signal.

time#
Get Signature#

get time(): number

How far into the clip playback is, in seconds.

Returns#

number

The elapsed time.

transform#
Get Signature#

get transform(): Transform

The entity's transform — sugar for this.entity.transform, the most-used lookup there is.

Returns#

Transform

The entity's transform.

Inherited from#

Component.transform

uid#
Get Signature#

get uid(): string

The stable ULID; the key files use to reference this component.

Returns#

string

The identifier.

Inherited from#

Component.uid

world#
Get Signature#

get world(): World

The world the entity belongs to.

Returns#

World

The world.

Inherited from#

Component.world

Methods#

define()#

static define<S>(schema): ComponentDefinition<S>

Declares a component's serialized fields and returns the base class to extend (ADR-0004, docs/architecture/03-scripting-and-components.md §3). The returned class exposes every field as a typed instance property, applies the defaults in its constructor, and carries the schema for the serializer, the inspector, and the docs harness.

Type Parameters#
S#

S extends Readonly<Record<string, FieldDefinition<unknown>>>

The schema being declared.

Parameters#
schema#

S

The field definitions, keyed by the property name they become.

Returns#

ComponentDefinition<S>

An abstract class to extend.

Throws#

IgnifxError with code IGX-0607 when a field name is not identifier-like or collides with a Component/Script member.

Example#
typescript
class Spinner extends Component.define({  degreesPerSecond: f32(90, { min: -360, max: 360 }),  axis: vec3({ x: 0, y: 1, z: 0 }),}) {  static typeId = "mygame/Spinner";}
Inherited from#

Component.define

destroy()#

destroy(): void

Queues this component for destruction. It stays usable until the destroy flush of the current frame, but reports isDestroyed === true immediately (docs/architecture/01-lifecycle-and-time.md §6). Calling it twice is a no-op.

Returns#

void

Inherited from#

Component.destroy

getComponent()#

getComponent<T>(type): T | null

Finds another component on the same entity — sugar for this.entity.getComponent.

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class; matching is by class identity and inheritance.

Returns#

T | null

The first match in attach order, or null.

Inherited from#

Component.getComponent

onAttach()#

onAttach(): void

Clears playback state, so a recycled component does not inherit the previous one's.

Returns#

void

Implementation of#

ComponentHooks.onAttach

onDetach()#

onDetach(): void

Releases the signals' handlers.

Returns#

void

Implementation of#

ComponentHooks.onDetach

pause()#

pause(): void

Suspends playback where it is; SpriteAnimator.resume continues from there.

Returns#

void

play()#

play(name, options?): void

Starts a clip.

Parameters#
name#

string

The clip's name.

options?#

PlayClipOptions

Whether to rewind a clip that is already playing.

Returns#

void

Throws#

IgnifxError with code IGX-1108 when the document declares no such clip.

Example#
typescript
animator.play("run", { restart: true });
requireComponent()#

requireComponent<T>(type): T

Finds another component on the same entity, requiring it to be there — the supported way to link components (docs/architecture/03-scripting-and-components.md §8).

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class.

Returns#

T

The first match in attach order.

Throws#

IgnifxError with code IGX-0201 when the entity has no such component.

Inherited from#

Component.requireComponent

resume()#

resume(): void

Continues a paused clip.

Returns#

void

stop()#

stop(): void

Stops playback and rewinds to the clip's first frame.

Returns#

void


SpriteAtlasAsset#

A loaded sprite atlas.

Remarks#

Under a headless app the document is parsed and every frame is queryable, but lite.atlas is null — nothing is uploaded (docs/architecture/07-rendering.md §6). That is what lets a headless test assert frame counts, pivots, and animation timing without a GPU.

Example#

typescript
const handle = app.assets.load<SpriteAtlasAsset>("2d/hero.atlas.json");const atlas = await handle.promise;atlas.frameIndex("idle_0"); // 0

Properties#

address#

readonly address: string

The address the atlas was loaded from.

assetType#

static assetType: string = SPRITE_ATLAS_ASSET_TYPE

The type name the asset service registers sprite atlases under.

definition#

readonly definition: SpriteAtlasDefinition

The parsed .atlas.json document.

Accessors#

frameCount#
Get Signature#

get frameCount(): number

How many frames the atlas declares.

Returns#

number

The frame count.

isReleased#
Get Signature#

get isReleased(): boolean

Whether the atlas was uploaded to a device at all.

Returns#

boolean

true once the GPU texture has been given up, or under a headless app.

lite#
Get Signature#

get lite(): SpriteAtlasAssetLiteHandles

The Babylon Lite objects the asset owns. Unstable escape hatch (CONSTITUTION.md §3.4).

Returns#

SpriteAtlasAssetLiteHandles

The Lite atlas, or null under a headless app.

Methods#

frame()#

frame(index): SpriteFrameInfo | null

Describes one frame.

Parameters#
index#

number

The frame index.

Returns#

SpriteFrameInfo | null

The frame, or null when the index is out of range.

frameIndex()#

frameIndex(name): number

Looks a frame up by name.

Parameters#
name#

string

The frame name.

Returns#

number

The index, or -1 when the atlas has no such frame.

frameNames()#

frameNames(): readonly string[]

Every frame name, in index order.

Returns#

readonly string[]

A freshly allocated array.

requireFrame()#

requireFrame(name): number

Looks a frame up by name and refuses to guess.

Parameters#
name#

string

The frame name.

Returns#

number

The index.

Throws#

IgnifxError with code IGX-1106 when the atlas declares no such frame.


SpriteLayerEffect#

A per-layer shader effect.

Example#

typescript
const dusk = app.world.createEntity({ name: "dusk" }).addComponent(SpriteLayerEffect);dusk.sortingLayer = "Default";dusk.kind = "tint";dusk.tint = { r: 0.6, g: 0.6, b: 0.9, a: 1 };

Extends#

  • Component

Constructors#

Constructor#

new SpriteLayerEffect(): SpriteLayerEffect

Builds an effect with the schema's defaults.

Returns#

SpriteLayerEffect

Overrides#

Component.constructor

Properties#

allowMultiple#

static allowMultiple: boolean = false

One effect per entity; several entities may each drive a different sorting layer.

kind#

kind: "custom" | "tint"

Which shader to install.

params#

params: Vec4Like

The fx.params vec4 a custom shader reads.

schema#

static schema: Schema

The declarative fields (ADR-0004).

shader#

shader: string

The WGSL fragment body a custom effect installs.

sortingLayer#

sortingLayer: string

Which sorting layer the effect applies to.

tint#

tint: object

The colour the tint effect multiplies by, written into fx.params.

a#

readonly a: number

b#

readonly b: number

g#

readonly g: number

r#

readonly r: number

typeId#

static typeId: string = "ignifx/SpriteLayerEffect"

The registration id the serializer writes into scene files.

Accessors#

app#
Get Signature#

get app(): App

The app that owns the world.

Returns#

App

The app.

Inherited from#

Component.app

enabled#
Get Signature#

get enabled(): boolean

The component's own enabled flag; true by default. Setting it runs the enable or disable transition (docs/architecture/01-lifecycle-and-time.md §6): onDisable runs immediately, awake/onEnable run in the next lifecycle flush — or immediately and nested when the change happens inside a callback.

Returns#

boolean

true when the component's own flag is set.

Set Signature#

set enabled(value): void

Parameters#
value#

boolean

Returns#

void

Inherited from#

Component.enabled

entity#
Get Signature#

get entity(): Entity

The entity this component is attached to.

Returns#

Entity

The owning entity.

Inherited from#

Component.entity

handle#
Get Signature#

get handle(): ComponentHandle

The dense runtime handle; invalid after destruction.

Returns#

ComponentHandle

The handle.

Inherited from#

Component.handle

isDestroyed#
Get Signature#

get isDestroyed(): boolean

true from the moment destroy() is called, long before the destroy flush runs.

Returns#

boolean

true once the component has been queued for destruction.

Inherited from#

Component.isDestroyed

isEnabledInHierarchy#
Get Signature#

get isEnabledInHierarchy(): boolean

true when the component's own flag is set and its entity is active in the hierarchy.

Returns#

boolean

true when the component is effectively enabled.

Inherited from#

Component.isEnabledInHierarchy

onDestroyed#
Get Signature#

get onDestroyed(): Signal<Component>

Emitted once when the component is destroyed, in the destroy flush. Connecting with { owner: this } elsewhere uses it to detach handlers automatically (docs/architecture/02-scene-graph.md §8).

Returns#

Signal<Component>

The signal. It is created on first access, so a component nobody listens to allocates nothing.

Inherited from#

Component.onDestroyed

transform#
Get Signature#

get transform(): Transform

The entity's transform — sugar for this.entity.transform, the most-used lookup there is.

Returns#

Transform

The entity's transform.

Inherited from#

Component.transform

uid#
Get Signature#

get uid(): string

The stable ULID; the key files use to reference this component.

Returns#

string

The identifier.

Inherited from#

Component.uid

world#
Get Signature#

get world(): World

The world the entity belongs to.

Returns#

World

The world.

Inherited from#

Component.world

Methods#

define()#

static define<S>(schema): ComponentDefinition<S>

Declares a component's serialized fields and returns the base class to extend (ADR-0004, docs/architecture/03-scripting-and-components.md §3). The returned class exposes every field as a typed instance property, applies the defaults in its constructor, and carries the schema for the serializer, the inspector, and the docs harness.

Type Parameters#
S#

S extends Readonly<Record<string, FieldDefinition<unknown>>>

The schema being declared.

Parameters#
schema#

S

The field definitions, keyed by the property name they become.

Returns#

ComponentDefinition<S>

An abstract class to extend.

Throws#

IgnifxError with code IGX-0607 when a field name is not identifier-like or collides with a Component/Script member.

Example#
typescript
class Spinner extends Component.define({  degreesPerSecond: f32(90, { min: -360, max: 360 }),  axis: vec3({ x: 0, y: 1, z: 0 }),}) {  static typeId = "mygame/Spinner";}
Inherited from#

Component.define

destroy()#

destroy(): void

Queues this component for destruction. It stays usable until the destroy flush of the current frame, but reports isDestroyed === true immediately (docs/architecture/01-lifecycle-and-time.md §6). Calling it twice is a no-op.

Returns#

void

Inherited from#

Component.destroy

getComponent()#

getComponent<T>(type): T | null

Finds another component on the same entity — sugar for this.entity.getComponent.

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class; matching is by class identity and inheritance.

Returns#

T | null

The first match in attach order, or null.

Inherited from#

Component.getComponent

requireComponent()#

requireComponent<T>(type): T

Finds another component on the same entity, requiring it to be there — the supported way to link components (docs/architecture/03-scripting-and-components.md §8).

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class.

Returns#

T

The first match in attach order.

Throws#

IgnifxError with code IGX-0201 when the entity has no such component.

Inherited from#

Component.requireComponent

source()#

source(): string

The WGSL fragment body this effect installs.

Returns#

string

The shader source.

Throws#

IgnifxError with code IGX-1113 when kind is "custom" and shader is empty.


SpriteLayerRegistry#

Owns every Lite sprite layer in one app.

Constructors#

Constructor#

new SpriteLayerRegistry(sortingLayers, ySort, onLayerCreated, onLayerRemoved): SpriteLayerRegistry

Builds the registry.

Parameters#
sortingLayers#

SortingLayerTable

Resolves a sorting-layer name to its draw order.

ySort#

Readonly<Record<string, boolean>>

Which sorting layers draw back-to-front by world Y.

onLayerCreated#

(layer) => void

Called with each new Lite layer, so the sprite renderer can draw it.

onLayerRemoved#

(layer) => void

Called before a layer is dropped.

Returns#

SpriteLayerRegistry

Methods#

collectLayers()#

collectLayers(worldOnly, out): Sprite2DLayer[]

The Lite layers, in draw order — what picking tests against.

Parameters#
worldOnly#

boolean

Whether to skip screen-space layers.

out#

Sprite2DLayer[]

The array to fill; it is emptied first, so one array serves every frame.

Returns#

Sprite2DLayer[]

out.

describe()#

describe(): readonly SpriteLayerEntry[]

Every layer, in draw order.

Returns#

readonly SpriteLayerEntry[]

A freshly allocated snapshot, for diagnostics.


SpriteRenderer#

A sprite.

Remarks#

The sprite field is an atlas handle; the frame inside it comes from the address's #frame: fragment when there is one, and otherwise from SpriteRenderer.frame, which game code and SpriteAnimator both write. A sprite whose atlas has not finished loading draws nothing and costs nothing.

Example#

typescript
const hero = app.world.createEntity({ name: "hero" });const sprite = hero.addComponent(SpriteRenderer);sprite.sprite = app.assets.load<SpriteAtlasAsset>("2d/hero.atlas.json").retain();sprite.sortingLayer = "Default";

Extends#

  • Component

Implements#

  • ComponentHooks

Constructors#

Constructor#

new SpriteRenderer(): SpriteRenderer

Builds a sprite with the schema's defaults.

Returns#

SpriteRenderer

Overrides#

Component.constructor

Properties#

allowMultiple#

static allowMultiple: boolean = true

Several sprites may share an entity — a character and its shadow, for instance.

blend#

blend: "alpha" | "premultiplied" | "additive" | "multiply" | "opaque"

How the sprite's colour combines with what is behind it.

color#

color: ColorLike

The tint multiplied into every texel.

flipX#

flipX: boolean

Whether the sprite is mirrored horizontally.

flipY#

flipY: boolean

Whether the sprite is mirrored vertically.

orderInLayer#

orderInLayer: number

The sub-order within the sorting layer; higher draws in front.

pickable#

pickable: boolean

Whether app.twoD.pickAt considers this sprite.

pivotOverride#

pivotOverride: Vec2Like | null

The pivot in [0, 1] of the frame, overriding the frame's own; null uses the frame's.

schema#

static schema: Schema

The declarative fields (ADR-0004).

screenSpace#

screenSpace: boolean

Whether the sprite keeps the identity view instead of following the Camera2D.

sortingLayer#

sortingLayer: string

Which sorting layer the sprite draws on.

sprite#

sprite: AssetHandle<SpriteAtlasAsset> | null

The atlas this sprite draws a frame of.

typeId#

static typeId: string = "ignifx/SpriteRenderer"

The registration id the serializer writes into scene files.

Accessors#

app#
Get Signature#

get app(): App

The app that owns the world.

Returns#

App

The app.

Inherited from#

Component.app

atlas#
Get Signature#

get atlas(): SpriteAtlasAsset | null

The loaded atlas, or null while it is still loading or failed.

Returns#

SpriteAtlasAsset | null

The atlas.

bounds#
Get Signature#

get bounds(): object

The sprite's world-space axis-aligned bounding box, for coarse queries (docs/architecture/11-2d-toolkit.md §5).

Remarks#

The box is the one the last sync computed, so it is a frame behind a sprite that has just moved, and it is the origin-sized empty box until the sprite has been synced once. It ignores rotation: a rotated sprite reports the box of its unrotated quad, which is the cheap conservative answer only for rotations that are multiples of a quarter turn.

Returns#

object

A freshly allocated box in world metres.

max#

readonly max: Vec2Like

min#

readonly min: Vec2Like

enabled#
Get Signature#

get enabled(): boolean

The component's own enabled flag; true by default. Setting it runs the enable or disable transition (docs/architecture/01-lifecycle-and-time.md §6): onDisable runs immediately, awake/onEnable run in the next lifecycle flush — or immediately and nested when the change happens inside a callback.

Returns#

boolean

true when the component's own flag is set.

Set Signature#

set enabled(value): void

Parameters#
value#

boolean

Returns#

void

Inherited from#

Component.enabled

entity#
Get Signature#

get entity(): Entity

The entity this component is attached to.

Returns#

Entity

The owning entity.

Inherited from#

Component.entity

frame#
Get Signature#

get frame(): number

The atlas frame drawn.

Returns#

number

The frame index.

Set Signature#

set frame(value): void

Sets the atlas frame drawn, marking the sprite for the next sync when it changes.

Parameters#
value#

number

The frame index.

Returns#

void

handle#
Get Signature#

get handle(): ComponentHandle

The dense runtime handle; invalid after destruction.

Returns#

ComponentHandle

The handle.

Inherited from#

Component.handle

isDestroyed#
Get Signature#

get isDestroyed(): boolean

true from the moment destroy() is called, long before the destroy flush runs.

Returns#

boolean

true once the component has been queued for destruction.

Inherited from#

Component.isDestroyed

isEnabledInHierarchy#
Get Signature#

get isEnabledInHierarchy(): boolean

true when the component's own flag is set and its entity is active in the hierarchy.

Returns#

boolean

true when the component is effectively enabled.

Inherited from#

Component.isEnabledInHierarchy

lite#
Get Signature#

get lite(): object

The Babylon Lite objects the component uses. Unstable escape hatch (CONSTITUTION.md §3.4).

Returns#

object

The sprite handle, or null when the sprite is not in a layer.

sprite#

readonly sprite: Sprite2DHandle | null

onDestroyed#
Get Signature#

get onDestroyed(): Signal<Component>

Emitted once when the component is destroyed, in the destroy flush. Connecting with { owner: this } elsewhere uses it to detach handlers automatically (docs/architecture/02-scene-graph.md §8).

Returns#

Signal<Component>

The signal. It is created on first access, so a component nobody listens to allocates nothing.

Inherited from#

Component.onDestroyed

transform#
Get Signature#

get transform(): Transform

The entity's transform — sugar for this.entity.transform, the most-used lookup there is.

Returns#

Transform

The entity's transform.

Inherited from#

Component.transform

uid#
Get Signature#

get uid(): string

The stable ULID; the key files use to reference this component.

Returns#

string

The identifier.

Inherited from#

Component.uid

world#
Get Signature#

get world(): World

The world the entity belongs to.

Returns#

World

The world.

Inherited from#

Component.world

Methods#

define()#

static define<S>(schema): ComponentDefinition<S>

Declares a component's serialized fields and returns the base class to extend (ADR-0004, docs/architecture/03-scripting-and-components.md §3). The returned class exposes every field as a typed instance property, applies the defaults in its constructor, and carries the schema for the serializer, the inspector, and the docs harness.

Type Parameters#
S#

S extends Readonly<Record<string, FieldDefinition<unknown>>>

The schema being declared.

Parameters#
schema#

S

The field definitions, keyed by the property name they become.

Returns#

ComponentDefinition<S>

An abstract class to extend.

Throws#

IgnifxError with code IGX-0607 when a field name is not identifier-like or collides with a Component/Script member.

Example#
typescript
class Spinner extends Component.define({  degreesPerSecond: f32(90, { min: -360, max: 360 }),  axis: vec3({ x: 0, y: 1, z: 0 }),}) {  static typeId = "mygame/Spinner";}
Inherited from#

Component.define

destroy()#

destroy(): void

Queues this component for destruction. It stays usable until the destroy flush of the current frame, but reports isDestroyed === true immediately (docs/architecture/01-lifecycle-and-time.md §6). Calling it twice is a no-op.

Returns#

void

Inherited from#

Component.destroy

getComponent()#

getComponent<T>(type): T | null

Finds another component on the same entity — sugar for this.entity.getComponent.

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class; matching is by class identity and inheritance.

Returns#

T | null

The first match in attach order, or null.

Inherited from#

Component.getComponent

onAttach()#

onAttach(): void

Resets the sync shadow state, so a recycled component does not inherit the previous one's.

Returns#

void

Implementation of#

ComponentHooks.onAttach

onDetach()#

onDetach(): void

Marks the sprite for removal from its layer. The sync system does the removal, because it owns the layer.

Returns#

void

Implementation of#

ComponentHooks.onDetach

requireComponent()#

requireComponent<T>(type): T

Finds another component on the same entity, requiring it to be there — the supported way to link components (docs/architecture/03-scripting-and-components.md §8).

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class.

Returns#

T

The first match in attach order.

Throws#

IgnifxError with code IGX-0201 when the entity has no such component.

Inherited from#

Component.requireComponent


Tilemap#

A tilemap.

Example#

typescript
const level = app.world.createEntity({ name: "level" }).addComponent(Tilemap);level.map = app.assets.load<TilemapAsset>("2d/level-1.tilemap.json").retain();level.setTile(0, 3, 2, 0); // carve a hole in the ground layer

Extends#

  • Component

Implements#

  • ComponentHooks

Constructors#

Constructor#

new Tilemap(): Tilemap

Builds a tilemap with the schema's defaults.

Returns#

Tilemap

Overrides#

Component.constructor

Properties#

allowMultiple#

static allowMultiple: boolean = false

One tilemap per entity.

cellSizeOverride#

cellSizeOverride: number

The metres one cell spans, overriding the document's own; 0 uses the document's.

chunkSize#

chunkSize: number

How many cells one chunk spans on each axis.

map#

map: AssetHandle<TilemapAsset> | null

The .tilemap.json document.

schema#

static schema: Schema

The declarative fields (ADR-0004).

typeId#

static typeId: string = "ignifx/Tilemap"

The registration id the serializer writes into scene files.

Accessors#

app#
Get Signature#

get app(): App

The app that owns the world.

Returns#

App

The app.

Inherited from#

Component.app

asset#
Get Signature#

get asset(): TilemapAsset | null

The loaded document, or null while it is still loading.

Returns#

TilemapAsset | null

The asset.

cellSize#
Get Signature#

get cellSize(): number

How many metres one cell spans.

Returns#

number

The cell size; 0 when nothing has loaded.

collisionData#
Get Signature#

get collisionData(): TilemapCollisionData

The merged collision surface, rebuilt if a tile changed since the last read.

Remarks#

The shape is the contract @ignifx/physics-2d consumes: chunked, in world metres relative to the tilemap entity's origin, with adjacent full-cell tiles merged into as few counter-clockwise rectangles as possible.

Returns#

TilemapCollisionData

The collision data.

definition#
Get Signature#

get definition(): TilemapDefinition | null

The parsed document, or null.

Returns#

TilemapDefinition | null

The definition.

enabled#
Get Signature#

get enabled(): boolean

The component's own enabled flag; true by default. Setting it runs the enable or disable transition (docs/architecture/01-lifecycle-and-time.md §6): onDisable runs immediately, awake/onEnable run in the next lifecycle flush — or immediately and nested when the change happens inside a callback.

Returns#

boolean

true when the component's own flag is set.

Set Signature#

set enabled(value): void

Parameters#
value#

boolean

Returns#

void

Inherited from#

Component.enabled

entity#
Get Signature#

get entity(): Entity

The entity this component is attached to.

Returns#

Entity

The owning entity.

Inherited from#

Component.entity

handle#
Get Signature#

get handle(): ComponentHandle

The dense runtime handle; invalid after destruction.

Returns#

ComponentHandle

The handle.

Inherited from#

Component.handle

isDestroyed#
Get Signature#

get isDestroyed(): boolean

true from the moment destroy() is called, long before the destroy flush runs.

Returns#

boolean

true once the component has been queued for destruction.

Inherited from#

Component.isDestroyed

isEnabledInHierarchy#
Get Signature#

get isEnabledInHierarchy(): boolean

true when the component's own flag is set and its entity is active in the hierarchy.

Returns#

boolean

true when the component is effectively enabled.

Inherited from#

Component.isEnabledInHierarchy

layerCount#
Get Signature#

get layerCount(): number

How many layers the document has.

Returns#

number

The layer count.

onCollisionChanged#
Get Signature#

get onCollisionChanged(): Signal

Emitted after the merged collision surface has been rebuilt.

Remarks#

@ignifx/physics-2d connects to this and rebuilds only the chunks whose geometry moved. The rebuild is lazy: the signal fires on the first read of Tilemap.collisionData after a change, not on the setTile call itself, so a script that rewrites a thousand tiles in one frame pays for one merge.

Returns#

Signal

The signal.

onDestroyed#
Get Signature#

get onDestroyed(): Signal<Component>

Emitted once when the component is destroyed, in the destroy flush. Connecting with { owner: this } elsewhere uses it to detach handlers automatically (docs/architecture/02-scene-graph.md §8).

Returns#

Signal<Component>

The signal. It is created on first access, so a component nobody listens to allocates nothing.

Inherited from#

Component.onDestroyed

onTileChanged#
Get Signature#

get onTileChanged(): Signal<TileChange>

Emitted whenever setTile changes a cell.

Returns#

Signal<TileChange>

The signal.

transform#
Get Signature#

get transform(): Transform

The entity's transform — sugar for this.entity.transform, the most-used lookup there is.

Returns#

Transform

The entity's transform.

Inherited from#

Component.transform

uid#
Get Signature#

get uid(): string

The stable ULID; the key files use to reference this component.

Returns#

string

The identifier.

Inherited from#

Component.uid

world#
Get Signature#

get world(): World

The world the entity belongs to.

Returns#

World

The world.

Inherited from#

Component.world

Methods#

cellToWorld()#

cellToWorld<TOut>(x, y, out): TOut

Converts a cell into the world point at its centre.

Type Parameters#
TOut#

TOut extends MutableVec2

Parameters#
x#

number

The cell's column.

y#

number

The cell's row, with 0 at the bottom.

out#

TOut

The vector to write.

Returns#

TOut

out, in world metres.

collisionAt()#

collisionAt(x, y): TileCollisionInfo

The collision footprint of whatever is at a cell, across every collision layer.

Parameters#
x#

number

The cell's column.

y#

number

The cell's row, with 0 at the bottom.

Returns#

TileCollisionInfo

The topmost non-empty collider, or a "none" shape.

define()#

static define<S>(schema): ComponentDefinition<S>

Declares a component's serialized fields and returns the base class to extend (ADR-0004, docs/architecture/03-scripting-and-components.md §3). The returned class exposes every field as a typed instance property, applies the defaults in its constructor, and carries the schema for the serializer, the inspector, and the docs harness.

Type Parameters#
S#

S extends Readonly<Record<string, FieldDefinition<unknown>>>

The schema being declared.

Parameters#
schema#

S

The field definitions, keyed by the property name they become.

Returns#

ComponentDefinition<S>

An abstract class to extend.

Throws#

IgnifxError with code IGX-0607 when a field name is not identifier-like or collides with a Component/Script member.

Example#
typescript
class Spinner extends Component.define({  degreesPerSecond: f32(90, { min: -360, max: 360 }),  axis: vec3({ x: 0, y: 1, z: 0 }),}) {  static typeId = "mygame/Spinner";}
Inherited from#

Component.define

destroy()#

destroy(): void

Queues this component for destruction. It stays usable until the destroy flush of the current frame, but reports isDestroyed === true immediately (docs/architecture/01-lifecycle-and-time.md §6). Calling it twice is a no-op.

Returns#

void

Inherited from#

Component.destroy

getComponent()#

getComponent<T>(type): T | null

Finds another component on the same entity — sugar for this.entity.getComponent.

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class; matching is by class identity and inheritance.

Returns#

T | null

The first match in attach order, or null.

Inherited from#

Component.getComponent

getTile()#

getTile(layer, x, y): number

Reads a tile.

Parameters#
layer#

number

The layer's index in the document.

x#

number

The cell's column, with 0 at the left.

y#

number

The cell's row, with 0 at the bottom.

Returns#

number

The tile id, or 0 for an empty or out-of-range cell.

layerSize()#

layerSize(layer): Vec2Like

A layer's size, in cells.

Parameters#
layer#

number

The layer's index.

Returns#

Vec2Like

The size, or a zero size for an unknown layer.

onAttach()#

onAttach(): void

Drops the grids, so a recycled component does not inherit the previous one's.

Returns#

void

Implementation of#

ComponentHooks.onAttach

onDetach()#

onDetach(): void

Releases the grids.

Returns#

void

Implementation of#

ComponentHooks.onDetach

requireComponent()#

requireComponent<T>(type): T

Finds another component on the same entity, requiring it to be there — the supported way to link components (docs/architecture/03-scripting-and-components.md §8).

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class.

Returns#

T

The first match in attach order.

Throws#

IgnifxError with code IGX-0201 when the entity has no such component.

Inherited from#

Component.requireComponent

setTile()#

setTile(layer, x, y, tileId): void

Writes a tile.

Parameters#
layer#

number

The layer's index in the document.

x#

number

The cell's column, with 0 at the left.

y#

number

The cell's row, with 0 at the bottom.

tileId#

number

The tile id, or 0 to clear the cell.

Returns#

void

Throws#

IgnifxError with code IGX-1111 when the cell is outside the layer.

worldToCell()#

worldToCell<TOut>(point, out): TOut

Converts a world point into the cell containing it.

Type Parameters#
TOut#

TOut extends MutableVec2

Parameters#
point#

Vec2Like

The world point, in metres.

out#

TOut

The vector to write.

Returns#

TOut

out, holding integer cell coordinates that may be outside the map.

Remarks#

The point is in world metres; the map's own origin is the tilemap entity's position, so a moved or scaled tilemap still answers correctly. The result is floored, so a point exactly on a cell boundary belongs to the cell above and to the right of it.


TilemapAsset#

A loaded tilemap document.

Example#

typescript
const map = await app.assets.load<TilemapAsset>("2d/level-1.tilemap.json").promise;map.definition.layers.length; // 2

Properties#

address#

readonly address: string

The address the document was loaded from.

assetType#

static assetType: string = TILEMAP_ASSET_TYPE

The type name the asset service registers tilemaps under.

atlasAddresses#

readonly atlasAddresses: readonly string[]

Each tileset's atlas address, resolved against this document's address.

definition#

readonly definition: TilemapDefinition

The parsed document, with every tile layer decoded to a dense array.

Methods#

atlasFor()#

atlasFor(tilesetIndex): string

The atlas address a tileset's tiles come from.

Parameters#
tilesetIndex#

number

The tileset's index in the document.

Returns#

string

The address, or "" when the index is out of range.


TilemapRenderer#

A tilemap renderer.

Example#

typescript
const level = app.world.createEntity({ name: "level" });level.addComponent(Tilemap).map = app.assets.load<TilemapAsset>("2d/level-1.tilemap.json").retain();const renderer = level.addComponent(TilemapRenderer);renderer.atlas = app.assets.load<SpriteAtlasAsset>("2d/tiles.atlas.json").retain();

Extends#

  • Component

Implements#

  • ComponentHooks

Constructors#

Constructor#

new TilemapRenderer(): TilemapRenderer

Builds a renderer with the schema's defaults.

Returns#

TilemapRenderer

Overrides#

Component.constructor

Properties#

allowMultiple#

static allowMultiple: boolean = false

One renderer per entity.

atlas#

atlas: AssetHandle<SpriteAtlasAsset> | null

The atlas the tile frames come from.

cullChunks#

cullChunks: boolean

Whether chunks outside the camera's visible bounds are dropped.

schema#

static schema: Schema

The declarative fields (ADR-0004).

sortingLayer#

sortingLayer: string

Which sorting layer the tiles draw on, when the document's layers name none.

typeId#

static typeId: string = "ignifx/TilemapRenderer"

The registration id the serializer writes into scene files.

Accessors#

app#
Get Signature#

get app(): App

The app that owns the world.

Returns#

App

The app.

Inherited from#

Component.app

chunkCount#
Get Signature#

get chunkCount(): number

How many chunks are currently materialised.

Returns#

number

The count.

enabled#
Get Signature#

get enabled(): boolean

The component's own enabled flag; true by default. Setting it runs the enable or disable transition (docs/architecture/01-lifecycle-and-time.md §6): onDisable runs immediately, awake/onEnable run in the next lifecycle flush — or immediately and nested when the change happens inside a callback.

Returns#

boolean

true when the component's own flag is set.

Set Signature#

set enabled(value): void

Parameters#
value#

boolean

Returns#

void

Inherited from#

Component.enabled

entity#
Get Signature#

get entity(): Entity

The entity this component is attached to.

Returns#

Entity

The owning entity.

Inherited from#

Component.entity

handle#
Get Signature#

get handle(): ComponentHandle

The dense runtime handle; invalid after destruction.

Returns#

ComponentHandle

The handle.

Inherited from#

Component.handle

isDestroyed#
Get Signature#

get isDestroyed(): boolean

true from the moment destroy() is called, long before the destroy flush runs.

Returns#

boolean

true once the component has been queued for destruction.

Inherited from#

Component.isDestroyed

isEnabledInHierarchy#
Get Signature#

get isEnabledInHierarchy(): boolean

true when the component's own flag is set and its entity is active in the hierarchy.

Returns#

boolean

true when the component is effectively enabled.

Inherited from#

Component.isEnabledInHierarchy

loadedAtlas#
Get Signature#

get loadedAtlas(): SpriteAtlasAsset | null

The loaded atlas, or null.

Returns#

SpriteAtlasAsset | null

The atlas.

onDestroyed#
Get Signature#

get onDestroyed(): Signal<Component>

Emitted once when the component is destroyed, in the destroy flush. Connecting with { owner: this } elsewhere uses it to detach handlers automatically (docs/architecture/02-scene-graph.md §8).

Returns#

Signal<Component>

The signal. It is created on first access, so a component nobody listens to allocates nothing.

Inherited from#

Component.onDestroyed

spriteCount#
Get Signature#

get spriteCount(): number

How many sprites the materialised chunks hold in total.

Returns#

number

The count.

transform#
Get Signature#

get transform(): Transform

The entity's transform — sugar for this.entity.transform, the most-used lookup there is.

Returns#

Transform

The entity's transform.

Inherited from#

Component.transform

uid#
Get Signature#

get uid(): string

The stable ULID; the key files use to reference this component.

Returns#

string

The identifier.

Inherited from#

Component.uid

world#
Get Signature#

get world(): World

The world the entity belongs to.

Returns#

World

The world.

Inherited from#

Component.world

Methods#

define()#

static define<S>(schema): ComponentDefinition<S>

Declares a component's serialized fields and returns the base class to extend (ADR-0004, docs/architecture/03-scripting-and-components.md §3). The returned class exposes every field as a typed instance property, applies the defaults in its constructor, and carries the schema for the serializer, the inspector, and the docs harness.

Type Parameters#
S#

S extends Readonly<Record<string, FieldDefinition<unknown>>>

The schema being declared.

Parameters#
schema#

S

The field definitions, keyed by the property name they become.

Returns#

ComponentDefinition<S>

An abstract class to extend.

Throws#

IgnifxError with code IGX-0607 when a field name is not identifier-like or collides with a Component/Script member.

Example#
typescript
class Spinner extends Component.define({  degreesPerSecond: f32(90, { min: -360, max: 360 }),  axis: vec3({ x: 0, y: 1, z: 0 }),}) {  static typeId = "mygame/Spinner";}
Inherited from#

Component.define

destroy()#

destroy(): void

Queues this component for destruction. It stays usable until the destroy flush of the current frame, but reports isDestroyed === true immediately (docs/architecture/01-lifecycle-and-time.md §6). Calling it twice is a no-op.

Returns#

void

Inherited from#

Component.destroy

getComponent()#

getComponent<T>(type): T | null

Finds another component on the same entity — sugar for this.entity.getComponent.

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class; matching is by class identity and inheritance.

Returns#

T | null

The first match in attach order, or null.

Inherited from#

Component.getComponent

onAttach()#

onAttach(): void

Marks every chunk stale, so a recycled component rebuilds.

Returns#

void

Implementation of#

ComponentHooks.onAttach

onDetach()#

onDetach(): void

Marks every chunk stale; the 2D sync system does the removal, because it owns the layers.

Returns#

void

Implementation of#

ComponentHooks.onDetach

requireComponent()#

requireComponent<T>(type): T

Finds another component on the same entity, requiring it to be there — the supported way to link components (docs/architecture/03-scripting-and-components.md §8).

Type Parameters#
T#

T extends Component

The component type to look for.

Parameters#
type#

ComponentType<T>

The component class.

Returns#

T

The first match in attach order.

Throws#

IgnifxError with code IGX-0201 when the entity has no such component.

Inherited from#

Component.requireComponent


TwoDAnimationSystem#

Advances sprite animation on ignifx's clock.

Implements#

  • System

Constructors#

Constructor#

new TwoDAnimationSystem(tilemaps): TwoDAnimationSystem

Builds the system.

Parameters#
tilemaps#

AnimatedTilemapSink

Advances animated tiles on the same clock.

Returns#

TwoDAnimationSystem

Properties#

name#

readonly name: "ignifx/2d-animation" = "ignifx/2d-animation"

The name diagnostics and error reports use.

Implementation of#

System.name

Methods#

update()#

update(ctx): void

Advances every animator and every animated tile.

Parameters#
ctx#

SystemContext

The world, clock, phase, and delta.

Returns#

void

Implementation of#

System.update


TwoDService#

The 2D service.

Example#

typescript
const hit = app.twoD.pickAt(pointer.x, pointer.y);if (hit !== null) {  hit.entity.destroy();}

Accessors#

layers#
Get Signature#

get layers(): readonly SpriteLayerEntry[]

Every Lite sprite layer in draw order, for diagnostics and tests.

Remarks#

The snapshot is freshly allocated on each read; it is a debugging surface, not a per-frame one.

Returns#

readonly SpriteLayerEntry[]

The layers.

lite#
Get Signature#

get lite(): TwoDLiteHandles

The Babylon Lite objects the toolkit owns. Unstable escape hatch (CONSTITUTION.md §3.4).

Returns#

TwoDLiteHandles

The sprite rendering context, or null under a headless app or before the first frame.

mainCamera#
Get Signature#

get mainCamera(): Camera2D | null

The camera the last frame was drawn through: the highest-priority enabled Camera2D.

Returns#

Camera2D | null

The camera, or null when the world has none enabled.

mode#
Get Signature#

get mode(): "sprite" | "mixed"

Whether sprites are the whole frame or composite over the 3D scene.

Returns#

"sprite" | "mixed"

The mode.

pixelsPerUnit#
Get Signature#

get pixelsPerUnit(): number

How many pixels one world metre spans (docs/architecture/11-2d-toolkit.md §1).

Returns#

number

The conversion factor; 100 unless the project or a scene changed it.

settings#
Get Signature#

get settings(): TwoDSettings

The resolved twoD settings, after any scene-file override.

Returns#

TwoDSettings

The settings.

sortingLayers#
Get Signature#

get sortingLayers(): readonly string[]

The project's sorting layers, back to front.

Returns#

readonly string[]

The names.

spriteCount#
Get Signature#

get spriteCount(): number

How many SpriteRenderer components the last frame walked.

Returns#

number

The count.

syncedLastFrame#
Get Signature#

get syncedLastFrame(): number

How many sprites the last frame actually wrote to Lite.

Remarks#

This is the number spike S6.1 watches: on a steady frame with a static tilemap it is the count of sprites that genuinely moved, not the count that exist.

Returns#

number

The count.

Methods#

pickAt()#

pickAt(xPx, yPx): TwoDPick | null

Picks the topmost sprite under a viewport pixel (docs/architecture/11-2d-toolkit.md §5).

Parameters#
xPx#

number

The viewport x, in pixels from the left edge.

yPx#

number

The viewport y, in pixels from the top edge.

Returns#

TwoDPick | null

The hit, or null for a miss.

Remarks#

Picking is a CPU test against every world layer's instance data, in draw order — no GPU readback and no frame of latency, which is what makes it usable from a click handler. It resolves only SpriteRenderer components: a tilemap's tiles have no component, so use Tilemap.worldToCell for those.

registerTileObjectFactory()#

registerTileObjectFactory(type, factory): void

Registers the factory that turns one kind of tilemap object into an entity (docs/architecture/11-2d-toolkit.md §2.5).

Parameters#
type#

string

The object type the map writes.

factory#

TileObjectFactory

Builds the entity, or returns null to spawn nothing.

Returns#

void

Throws#

IgnifxError with code IGX-1110 when a factory for the type is already registered.

Example#
typescript
app.twoD.registerTileObjectFactory("spawn", ({ world, position }) => {  const player = world.createEntity({ name: "player" });  player.transform.position2D = new Vec2(position.x, position.y);  return player;});
screenToWorld()#

screenToWorld(xPx, yPx, out?): MutableVec2

Converts a viewport pixel into a world point through the active camera.

Parameters#
xPx#

number

The viewport x.

yPx#

number

The viewport y.

out?#

MutableVec2 = ...

The vector to write; omitting it allocates one.

Returns#

MutableVec2

out, or the origin when no camera is active.

unregisterTileObjectFactory()#

unregisterTileObjectFactory(type): boolean

Removes a tile-object factory.

Parameters#
type#

string

The object type.

Returns#

boolean

true when a factory was registered.

visibleWorldBounds()#

visibleWorldBounds(out): boolean

The world-space rectangle the camera can currently see.

Parameters#
out#

WorldBox

The box to write: its min takes the lower corner and its max the upper.

Returns#

boolean

true when a camera and a layer existed to measure against.

worldToScreen()#

worldToScreen(point, out?): MutableVec2

Converts a world point into a viewport pixel through the active camera.

Parameters#
point#

Vec2Like

The world point, in metres.

out?#

MutableVec2 = ...

The vector to write; omitting it allocates one.

Returns#

MutableVec2

out, or the origin when no camera is active.


TwoDSyncSystem#

Writes sprites and camera views into Babylon Lite once per frame.

Implements#

  • System

Properties#

name#

readonly name: "ignifx/2d-sync" = "ignifx/2d-sync"

The name diagnostics and error reports use.

Implementation of#

System.name

Methods#

onWorldCreated()#

onWorldCreated(world): void

Connects the scene hook to a new world.

Parameters#
world#

World

The new world.

Returns#

void

Remarks#

This is the only hook that fires for every world. register runs before the world exists and onStart runs only when a game calls app.start(), so a headless tool that loads a scene without ever starting a loop would otherwise never see its settings.twoD block.

Implementation of#

System.onWorldCreated

onWorldDisposed()#

onWorldDisposed(_world): void

Drops every layer when the world goes away.

Parameters#
_world#

World

The world being disposed.

Returns#

void

Implementation of#

System.onWorldDisposed

update()#

update(ctx): void

Runs one frame's synchronisation.

Parameters#
ctx#

SystemContext

The world, clock, phase, and delta.

Returns#

void

Implementation of#

System.update

Interfaces#

AnimatedTilemapSink#

Anything that owns animated tiles and can step them.

Methods#

advanceAnimatedTiles()#

advanceAnimatedTiles(world, deltaSeconds): void

Advances every animated tile by one frame's worth of scaled time.

Parameters#
world#

World

The world holding the tilemaps.

deltaSeconds#

number

The scaled frame delta, time.deltaTime.

Returns#

void


AsepriteAnimationImportOptions#

What importAsepriteAnimations accepts alongside the document.

Properties#

atlas?#

readonly optional atlas?: string

The .atlas.json address the clips index into. Defaults to "", the renderer's own atlas.

defaultFps?#

readonly optional defaultFps?: number

The rate a tag gets when Aseprite recorded no usable frame durations. Defaults to 12.

frameNameOf?#

readonly optional frameNameOf?: (index) => string

Names the atlas frame at a document frame index. Defaults to the same normalisation importAsepriteAtlas applies to the document's own frame keys, which is what makes the two imports agree; override it when the atlas was produced some other way.

Parameters#
index#

number

Returns#

string


AsepriteImportOptions#

What importAsepriteAtlas accepts alongside the document.

Properties#

image?#

readonly optional image?: string

The image address to write into the atlas. Defaults to the document's meta.image.

premultipliedAlpha?#

readonly optional premultipliedAlpha?: boolean

Whether the image's RGB is already multiplied by its alpha. Defaults to false.

sampling?#

readonly optional sampling?: "linear" | "nearest"

The min/mag filter. Defaults to "linear"; pixel art wants "nearest".


CollisionMergeOptions#

The grid mergeTileCollisions walks.

Properties#

cellSize#

readonly cellSize: number

The edge length of one cell, in metres.

chunkSize#

readonly chunkSize: number

The edge length of one chunk, in cells; 32 is what TilemapRenderer uses.

height#

readonly height: number

The grid's height, in cells.

width#

readonly width: number

The grid's width, in cells.


GridAtlasImportOptions#

What gridAtlas needs to cut an evenly spaced sheet into frames.

Properties#

cellHeight#

readonly cellHeight: number

One cell's height, in pixels. Must be positive.

cellWidth#

readonly cellWidth: number

One cell's width, in pixels. Must be positive.

columns?#

readonly optional columns?: number

How many columns to emit. Defaults to as many as the image holds; clamped to that.

image#

readonly image: string

The address of the image the frames are cut from.

imageHeight#

readonly imageHeight: number

The image's full height, in pixels.

imageWidth#

readonly imageWidth: number

The image's full width, in pixels.

margin?#

readonly optional margin?: number

The border left around the whole grid, in pixels. Defaults to 0.

namePrefix?#

readonly optional namePrefix?: string

The <prefix>_<index> frame names use. Defaults to "tile".

pivot?#

readonly optional pivot?: Vec2Like

The pivot every frame gets, in [0, 1]. Defaults to the centre.

premultipliedAlpha?#

readonly optional premultipliedAlpha?: boolean

Whether the image's RGB is already multiplied by its alpha. Defaults to false.

rows?#

readonly optional rows?: number

How many rows to emit. Defaults to as many as the image holds; clamped to that.

sampling?#

readonly optional sampling?: "linear" | "nearest"

The min/mag filter. Defaults to "linear"; pixel art wants "nearest".

spacing?#

readonly optional spacing?: number

The gap between adjacent cells, in pixels. Defaults to 0.


LdtkImportOptions#

How importLdtkLevel maps LDtk's conventions onto ignifx's.

Properties#

atlasFor?#

readonly optional atlasFor?: (relPath) => string

Maps an LDtk tileset's relPath onto the address of the ignifx .atlas.json generated from it. Defaults to swapping the file extension for .atlas.json.

Parameters#
relPath#

string

Returns#

string

intGridColliders?#

readonly optional intGridColliders?: Readonly<Record<number, TileColliderDefinition>>

Replaces LDTK_DEFAULT_INTGRID_COLLIDERS for this import.

level?#

readonly optional level?: string

The identifier of the level to import. Defaults to the project's first level.

pixelsPerUnit?#

readonly optional pixelsPerUnit?: number

The pixels one world metre spans. Defaults to 100, matching twoD.pixelsPerUnit.

sortingLayer?#

readonly optional sortingLayer?: string

The sorting layer every layer lands in. Defaults to "Default".


PlayClipOptions#

What SpriteAnimator.play accepts.

Properties#

restart?#

readonly optional restart?: boolean

Whether to rewind a clip that is already playing. Defaults to false.


SpriteAnimationDefinition#

The parsed .spriteanim.json document.

Properties#

atlas#

readonly atlas: string

The address of the .atlas.json the clips index into; empty uses the renderer's own atlas.

clips#

readonly clips: readonly SpriteClipDefinition[]

The clips, in declaration order; the first is the default when the component names none.

format#

readonly format: "ignifx.spriteanimation"

Always "ignifx.spriteanimation".

formatVersion#

readonly formatVersion: number

Always 1 in this build.


SpriteAnimationEvent#

A frame event: a name emitted on SpriteAnimator.onEvent when the clip reaches a frame.

Properties#

frame#

readonly frame: number

The zero-based index within the clip, not within the atlas.

name#

readonly name: string

The name emitted on SpriteAnimator.onEvent.


SpriteAnimationInput#

What defineSpriteAnimation accepts.

Properties#

atlas?#

readonly optional atlas?: string

The address of the .atlas.json the clips index into.

clips#

readonly clips: readonly SpriteClipDefinition[]

The clips.

format?#

readonly optional format?: string

Always "ignifx.spriteanimation" when present.

formatVersion?#

readonly optional formatVersion?: number

The document version.


SpriteAsset#

A sprite: one frame of one atlas, which is what SpriteRenderer.sprite points at.

Remarks#

A bare "2d/hero.atlas.json" address resolves to frame 0; the #frame: fragment picks another (docs/architecture/11-2d-toolkit.md §2.2). The asset service shares the underlying atlas between every fragment of the same address, so ten sprites off one atlas upload one texture.

Properties#

atlas#

readonly atlas: SpriteAtlasAsset

The atlas the frame lives in.

frame#

readonly frame: number

The frame index.

name#

readonly name: string

The frame's name.


SpriteAtlasAssetLiteHandles#

The Babylon Lite objects a SpriteAtlasAsset owns.

Properties#

atlas#

readonly atlas: SpriteAtlas | null

The Lite atlas, or null under a headless app, which uploads nothing.


SpriteAtlasDefinition#

The parsed .atlas.json document.

Example#

typescript
const atlas = defineSpriteAtlas({  image: "2d/hero.png",  sampling: "nearest",  frames: [{ name: "idle_0", x: 0, y: 0, w: 32, h: 32, pivot: { x: 0.5, y: 1 } }],});

Properties#

format#

readonly format: "ignifx.spriteatlas"

Always "ignifx.spriteatlas".

formatVersion#

readonly formatVersion: number

Always 1 in this build.

frames#

readonly frames: readonly SpriteFrameDefinition[]

The frames, in the order they are indexed.

image#

readonly image: string

The address of the image the frames are cut from.

premultipliedAlpha#

readonly premultipliedAlpha: boolean

Whether the image's RGB is already multiplied by its alpha. Defaults to false.

sampling#

readonly sampling: "linear" | "nearest"

The min/mag filter. "nearest" is what pixel art wants. Defaults to "linear".


SpriteAtlasInput#

What defineSpriteAtlas accepts: the document with every defaulted field optional.

Properties#

format?#

readonly optional format?: string

Always "ignifx.spriteatlas" when present.

formatVersion?#

readonly optional formatVersion?: number

The document version.

frames#

readonly frames: readonly SpriteFrameDefinition[]

The frames.

image#

readonly image: string

The address of the image the frames are cut from.

premultipliedAlpha?#

readonly optional premultipliedAlpha?: boolean

Whether the image is premultiplied. Defaults to false.

sampling?#

readonly optional sampling?: "linear" | "nearest"

The min/mag filter. Defaults to "linear".


SpriteClip#

One clip, resolved against an atlas.

Properties#

durationSeconds#

readonly durationSeconds: number

How long one pass through the clip takes, in seconds.

events#

readonly events: readonly SpriteAnimationEvent[]

Events fired as the clip passes a frame.

fps#

readonly fps: number

Frames per second.

frames#

readonly frames: readonly number[]

The atlas frame indices, in play order.

loop#

readonly loop: boolean

Whether the clip restarts at its end.

name#

readonly name: string

The clip's name.


SpriteClipDefinition#

One clip: an ordered run of atlas frames with a rate and a loop flag.

Properties#

events?#

readonly optional events?: readonly SpriteAnimationEvent[]

Events fired as the clip passes a frame.

fps?#

readonly optional fps?: number

Frames per second. Defaults to 12.

frames?#

readonly optional frames?: readonly string[]

The atlas frame names, in play order. Empty when from/to name a range instead.

from?#

readonly optional from?: string

The first frame of a contiguous atlas range, when frames is absent.

loop?#

readonly optional loop?: boolean

Whether the clip restarts at its end. Defaults to true.

name#

readonly name: string

The clip's name, unique within the document; what SpriteAnimator.play takes.

to?#

readonly optional to?: string

The last frame of a contiguous atlas range, inclusive.


SpriteFrameDefinition#

One frame rectangle, in image pixels with a top-left origin.

Properties#

h#

readonly h: number

The height, in image pixels.

name#

readonly name: string

The frame's name, unique within the document; what #frame: addresses.

pivot?#

readonly optional pivot?: Vec2Json

The pivot in [0, 1] of the frame — [0, 0] top-left, [0.5, 0.5] centre, [1, 1] bottom-right. Defaults to the centre. Written either as [x, y] or as { x, y }.

sourceSize?#

readonly optional sourceSize?: Vec2Json

The untrimmed source size, when the packer trimmed transparent margins. Defaults to w/h.

w#

readonly w: number

The width, in image pixels.

x#

readonly x: number

The left edge, in image pixels.

y#

readonly y: number

The top edge, in image pixels.


SpriteFrameInfo#

One frame of a loaded atlas, as game code sees it.

Properties#

heightPx#

readonly heightPx: number

Its drawn height, in image pixels.

index#

readonly index: number

Its index in the atlas, which is what Lite addresses frames by.

name#

readonly name: string

The frame's name.

pivot#

readonly pivot: Vec2Like

Its pivot in [0, 1] of the frame, [0, 0] top-left.

widthPx#

readonly widthPx: number

Its drawn width, in image pixels.


SpriteLayerEntry#

One Lite layer and everything the registry tracks alongside it.

Properties#

count#

readonly count: number

How many sprites the layer currently holds.

key#

readonly key: string

The composite key, built by spriteLayerKey.

layer#

readonly layer: Sprite2DLayer

The Lite layer.

screenSpace#

readonly screenSpace: boolean

Whether the layer keeps the identity view instead of following the Camera2D.

sortingLayer#

readonly sortingLayer: string

The sorting layer's name.

ySort#

readonly ySort: boolean

Whether the layer is Y-sorted.


SpriteLayerKey#

The layer key a sprite belongs to.

Remarks#

Two sprites share a Lite layer exactly when all four parts match. The atlas is part of the key because a Sprite2DLayer is bound to one atlas for its whole life (index.d.ts 11885, readonly atlas), and the blend mode is part of it for the same reason (readonly blendMode).

Properties#

atlas#

readonly atlas: SpriteAtlasAsset

The atlas every sprite in the layer draws from.

blend#

readonly blend: "alpha" | "premultiplied" | "additive" | "multiply" | "opaque"

The blend mode.

screenSpace#

readonly screenSpace: boolean

Whether the layer keeps the identity view instead of following the Camera2D.

sortingLayer#

readonly sortingLayer: string

The sorting layer's name.


TexturePackerImportOptions#

What importTexturePackerAtlas accepts alongside the document.

Properties#

image?#

readonly optional image?: string

The image address to write into the atlas. Defaults to the document's meta.image.

keepExtensions?#

readonly optional keepExtensions?: boolean

Whether to keep the .png on frame names. Defaults to false, which strips it.

premultipliedAlpha?#

readonly optional premultipliedAlpha?: boolean

Whether the image's RGB is already multiplied by its alpha. Defaults to false.

sampling?#

readonly optional sampling?: "linear" | "nearest"

The min/mag filter. Defaults to "linear".


TileAnimationFrame#

One frame of an animated tile.

Properties#

durationMs#

readonly durationMs: number

How long the step lasts, in milliseconds.

frame#

readonly frame: string

The atlas frame name drawn during this step.


TileChange#

One tile change, as Tilemap.onTileChanged reports it.

Properties#

current#

readonly current: number

The tile id that is there now.

layer#

readonly layer: number

The layer's index in the document.

previous#

readonly previous: number

The tile id that was there.

x#

readonly x: number

The cell's column, with 0 at the left.

y#

readonly y: number

The cell's row, with 0 at the bottom.


TileCollisionInfo#

Everything a physics backend needs to know about one tile of a tileset.

Properties#

oneWay#

readonly oneWay: boolean

Whether the tile is a one-way platform (solid only when crossed from above).

properties#

readonly properties: Readonly<Record<string, string | number | boolean>>

The tile's custom properties, carried through from the tileset or the importer.

shape#

readonly shape: TileCollisionShape

The tile's collision footprint in cell-local metres.


TileDefinition#

One tile of a tileset: what it draws, what it collides with, and what it carries.

Properties#

animation?#

readonly optional animation?: readonly TileAnimationFrame[]

The animation frames, when the tile animates. A single frame is treated as a static tile.

collider?#

readonly optional collider?: TileColliderDefinition

The collision footprint, in cell-normalised top-left-origin units. Absent means no collider.

frame#

readonly frame: string

The atlas frame the tile draws, by name.

id#

readonly id: number

The tile's index within its tileset, zero-based; the global id is tileset.firstId + id.

properties?#

readonly optional properties?: Readonly<Record<string, string | number | boolean>>

The tile's custom properties, carried through from the editor.


TiledImportOptions#

How importTiledMap maps Tiled's conventions onto ignifx's.

Properties#

atlasFor?#

readonly optional atlasFor?: (imageSource) => string

Maps a Tiled tileset's image path onto the address of the ignifx .atlas.json that was generated from it. Defaults to swapping the file extension for .atlas.json.

Parameters#
imageSource#

string

Returns#

string

pixelsPerUnit?#

readonly optional pixelsPerUnit?: number

The pixels one world metre spans. Defaults to 100, matching twoD.pixelsPerUnit.

sortingLayer?#

readonly optional sortingLayer?: string

The sorting layer every tile layer lands in unless it says otherwise. Defaults to "Default".


TilemapCollisionChunk#

The merged collision geometry of one chunk of a tilemap, in world-space metres relative to the tilemap entity's origin.

Remarks#

Adjacent solid tiles are merged into as few polygons as possible before they reach this shape, so a solid 3x2 block of tiles arrives as a single six-vertex rectangle rather than six boxes.

Properties#

chunkX#

readonly chunkX: number

The chunk's column index, in chunks.

chunkY#

readonly chunkY: number

The chunk's row index, in chunks.

oneWayEdges#

readonly oneWayEdges: readonly readonly [Vec2Like, Vec2Like][]

The one-way platform edges, each a [from, to] pair with solid side to the left of from → to.

polygons#

readonly polygons: readonly readonly Vec2Like[][]

The merged solid outlines, each wound counter-clockwise.


TilemapCollisionData#

The whole collision surface of a Tilemap, chunked so a physics backend can rebuild only the chunks that changed.

Remarks#

version increments whenever any chunk changes; a backend that caches colliders compares it to the version it last consumed and rebuilds when they differ. Tilemap.onCollisionChanged fires at the same moment.

Properties#

cellSize#

readonly cellSize: number

The edge length of one cell, in metres.

chunks#

readonly chunks: readonly TilemapCollisionChunk[]

The chunks that carry at least one collider; empty chunks are omitted.

chunkSize#

readonly chunkSize: number

The edge length of one chunk, in cells.

version#

readonly version: number

Increments on every change to the merged geometry.


TilemapDefinition#

The parsed .tilemap.json document.

Example#

typescript
const map = defineTilemap({  tileWidth: 32,  width: 2,  height: 1,  tilesets: [{ name: "hero", atlas: "2d/hero.atlas.json", firstId: 1, tiles: [{ id: 0, frame: "hero_0" }] }],  layers: [{ name: "Ground", tiles: [1, 0] }],});map.cellSize; // 0.32 — 32 px at the default 100 pixels per unit

Properties#

cellSize#

readonly cellSize: number

The world size of one cell, in metres — tileWidth / pixelsPerUnit.

Remarks#

Collision uses this single number on both axes. A map whose tiles are not square still gets a square collision cell; that is a deliberate MVP limitation and it is why the importers warn nothing and simply record both pixel sizes above.

format#

readonly format: "ignifx.tilemap"

Always "ignifx.tilemap".

formatVersion#

readonly formatVersion: number

Always 1 in this build.

height#

readonly height: number

The map's height, in cells.

layers#

readonly layers: readonly TilemapLayerDefinition[]

The tile layers, back to front: index 0 draws behind index 1.

objects#

readonly objects: readonly TilemapObjectDefinition[]

The objects gathered from every object layer, in document order.

properties#

readonly properties: Readonly<Record<string, string | number | boolean>>

The map's custom properties.

tileHeight#

readonly tileHeight: number

The height of one tile, in pixels.

tilesets#

readonly tilesets: readonly TilesetDefinition[]

The tilesets, sorted by ascending TilesetDefinition.firstId.

tileWidth#

readonly tileWidth: number

The width of one tile, in pixels.

width#

readonly width: number

The map's width, in cells.


TilemapInput#

What defineTilemap accepts: the document with every defaulted field optional.

Properties#

cellSize?#

readonly optional cellSize?: number

The metre size of one cell. Defaults to tileWidth / 100, the default pixels-per-unit.

format?#

readonly optional format?: string

Always "ignifx.tilemap" when present.

formatVersion?#

readonly optional formatVersion?: number

The document version.

height#

readonly height: number

The map's height, in cells.

layers?#

readonly optional layers?: readonly TilemapLayerInput[]

The tile layers, back to front. Defaults to none.

objects?#

readonly optional objects?: readonly TilemapObjectDefinition[]

The objects. Defaults to none.

properties?#

readonly optional properties?: Readonly<Record<string, string | number | boolean>>

The map's custom properties. Defaults to none.

tileHeight?#

readonly optional tileHeight?: number

The height of one tile, in pixels. Defaults to tileWidth.

tilesets?#

readonly optional tilesets?: readonly TilesetDefinition[]

The tilesets. Defaults to none.

tileWidth#

readonly tileWidth: number

The width of one tile, in pixels.

width#

readonly width: number

The map's width, in cells.


TilemapLayerDefinition#

One layer of tiles.

Remarks#

tiles is always the dense, decoded array in the parsed form: width * height global tile ids in row-major order with the top row first, which is how every editor stores a grid. 0 (EMPTY_TILE_ID) means the cell is empty. Runtime code that thinks in +Y-up cell coordinates reads index (height - 1 - cellY) * width + cellX.

Properties#

collision#

readonly collision: boolean

Whether the layer contributes collision geometry.

height#

readonly height: number

The layer's height, in cells.

name#

readonly name: string

The layer's name, unique within the document.

opacity#

readonly opacity: number

The layer's opacity in [0, 1].

orderInLayer#

readonly orderInLayer: number

The order within the sorting layer; higher draws in front.

parallax#

readonly parallax: Vec2Like

The parallax multiplier; { x: 1, y: 1 } moves with the camera.

sortingLayer#

readonly sortingLayer: string

The sorting layer the tiles draw in (docs/architecture/11-2d-toolkit.md §1).

tiles#

readonly tiles: readonly number[]

width * height global tile ids, row-major, top row first.

width#

readonly width: number

The layer's width, in cells.


TilemapLayerInput#

What defineTilemap accepts for one layer: every defaulted field optional, and tiles either dense or run-length encoded.

Properties#

collision?#

readonly optional collision?: boolean

Whether the layer collides. Defaults to false.

height?#

readonly optional height?: number

The layer's height in cells. Defaults to the map's height.

name#

readonly name: string

The layer's name, unique within the document.

opacity?#

readonly optional opacity?: number

The opacity in [0, 1]. Defaults to 1.

orderInLayer?#

readonly optional orderInLayer?: number

The order within the sorting layer. Defaults to 0.

parallax?#

readonly optional parallax?: Vec2Like

The parallax multiplier. Defaults to { x: 1, y: 1 }.

sortingLayer?#

readonly optional sortingLayer?: string

The sorting layer. Defaults to "Default".

tiles#

readonly tiles: readonly number[] | TileRleData

The tile ids, dense (row-major, top row first) or run-length encoded.

width?#

readonly optional width?: number

The layer's width in cells. Defaults to the map's width.


TilemapObjectDefinition#

One object placed on the map, to be turned into an entity by a registered TileObjectFactory.

Remarks#

x, y, width and height are world metres with +Y up, and x/y name the object's bottom-left corner. Importers do the conversion out of the editor's top-left pixel space, so nothing downstream has to know what editor the map came from.

Properties#

height#

readonly height: number

The height, in world metres.

name#

readonly name: string

The object's name, as authored; not required to be unique.

properties#

readonly properties: Readonly<Record<string, string | number | boolean>>

The object's custom properties.

type#

readonly type: string

The object's type — what app.twoD.registerTileObjectFactory keys on.

width#

readonly width: number

The width, in world metres.

x#

readonly x: number

The left edge, in world metres.

y#

readonly y: number

The bottom edge, in world metres, +Y up.


TileObjectContext#

What a TileObjectFactory is handed.

Properties#

name#

readonly name: string

The object's name, as the map wrote it.

position#

readonly position: Vec2Like

The object's bottom-left corner, in world metres relative to the tilemap entity.

properties#

readonly properties: Readonly<Record<string, string | number | boolean>>

The object's custom properties.

size#

readonly size: Vec2Like

The object's size, in world metres.

tilemap#

readonly tilemap: Entity

The tilemap entity the object came from, so a factory can parent to it.

type#

readonly type: string

The object's type, which selected this factory.

world#

readonly world: World

The world to create the entity in.


TileRleData#

A run-length-encoded tile array, as a .tilemap.json may store it to keep sparse maps small.

Properties#

rle#

readonly rle: readonly number[]

Flattened [count, value, count, value, …] pairs; see decodeTileRle.


TilesetDefinition#

A block of tiles cut from one atlas, occupying a contiguous run of global tile ids.

Properties#

atlas#

readonly atlas: string

The address of the .atlas.json the frames come from; empty for a collision-only tileset.

firstId#

readonly firstId: number

The global id of this tileset's tile 0. Always at least 1, because 0 means empty.

name#

readonly name: string

The tileset's name, unique within the document; also the frame-name prefix.

tiles#

readonly tiles: readonly TileDefinition[]

The tiles, indexed by their local TileDefinition.id.


TwoDErrorOptions#

Options accepted by twoDError: the same subset of IgnifxErrorOptions this package uses.

Properties#

cause?#

readonly optional cause?: unknown

The failure being wrapped, when there is one.

context?#

readonly optional context?: Readonly<Record<string, string | number | boolean | null>>

Identifiers that locate the failure.

hint?#

readonly optional hint?: string

One sentence telling the developer what to do about it.


TwoDLiteHandles#

The Babylon Lite objects app.twoD owns.

Properties#

renderer#

readonly renderer: SpriteRenderer | null

The sprite rendering context, or null under a headless app or before the first frame.


TwoDOptions#

What twoD() accepts. Every field overrides the matching twoD settings section value.

Properties#

mode?#

readonly optional mode?: "sprite" | "mixed"

Whether sprites are the whole frame ("sprite") or composite over the 3D scene ("mixed").

pixelsPerUnit?#

readonly optional pixelsPerUnit?: number

How many pixels one world metre spans.

ySort?#

readonly optional ySort?: Readonly<Record<string, boolean>>

Which sorting layers draw back-to-front by world Y.


TwoDPick#

What app.twoD.pickAt returns.

Properties#

component#

readonly component: SpriteRenderer

The sprite component that was hit.

entity#

readonly entity: Entity

The entity carrying the sprite that was hit.

u#

readonly u: number

Where inside the sprite's quad the hit landed, in [0, 1].

v#

readonly v: number

Where inside the sprite's quad the hit landed, in [0, 1].


TwoDSettings#

The resolved twoD settings section.

Example#

typescript
// ignifx.config.tsexport default defineConfig({  sortingLayers: { sortingLayers: ["Background", "Default", "Foreground"] },  twoD: { mode: "sprite", pixelsPerUnit: 16, ySort: { Default: true } },});

Properties#

mode#

readonly mode: "sprite" | "mixed"

Whether sprites are the whole frame ("sprite") or composite over the 3D scene ("mixed").

pixelsPerUnit#

readonly pixelsPerUnit: number

How many pixels one world metre spans. Defaults to 100.

ySort#

readonly ySort: Readonly<Record<string, boolean>>

Which sorting layers draw back-to-front by world Y rather than by orderInLayer. A layer the record does not mention does not Y-sort.


WorldBox#

A caller-owned world-space box, so reading the camera's bounds allocates nothing.

Properties#

max#

readonly max: MutableVec2

The upper corner, in world metres.

min#

readonly min: MutableVec2

The lower corner, in world metres.

Type Aliases#

LiteAtlasTexture#

LiteAtlasTexture = Texture2D

The GPU texture behind an atlas (index.d.ts 12907).

Remarks#

Unstable; excluded from the stability guarantees of CONSTITUTION.md Article IV.


LiteBounds2D#

LiteBounds2D = Bounds2D

Mutable axis-aligned 2D bounds, the shape getSprite2DVisibleBoundsToRef writes (index.d.ts 1352).

Remarks#

Unstable; excluded from the stability guarantees of CONSTITUTION.md Article IV.


LiteSprite2DHandle#

LiteSprite2DHandle = Sprite2DHandle

A stable identity for one sprite that survives Lite's swap-remove reindexing (index.d.ts 11880).

Remarks#

Unstable; excluded from the stability guarantees of CONSTITUTION.md Article IV.


LiteSprite2DLayer#

LiteSprite2DLayer = Sprite2DLayer

One ordered batch of sprites drawn from a single atlas with a single blend mode (index.d.ts 11885).

Remarks#

Unstable; excluded from the stability guarantees of CONSTITUTION.md Article IV.


LiteSprite2DView#

LiteSprite2DView = Sprite2DView

A layer's 2D camera: pan, zoom, and rotation in Lite's pixel space (index.d.ts 11988).

Remarks#

positionPx is the layer-pixel point that lands at the top-left of the viewport, not the centre — verified against sprite2DWorldToScreenToRef in lib/sprite/sprite-2d-view.js.

Unstable; excluded from the stability guarantees of CONSTITUTION.md Article IV.


LiteSpriteAtlas#

LiteSpriteAtlas = SpriteAtlas

A loaded atlas: one texture plus the frame rectangles inside it (index.d.ts 12041).

Remarks#

Unstable; excluded from the stability guarantees of CONSTITUTION.md Article IV.


LiteSpriteBlendMode#

LiteSpriteBlendMode = SpriteBlendMode

An opaque blend-mode descriptor (index.d.ts 12122).

Remarks#

Unstable; excluded from the stability guarantees of CONSTITUTION.md Article IV.


LiteSpriteFrame#

LiteSpriteFrame = SpriteFrame

One frame of an atlas: UVs in [0, 1], source size in pixels, and a pivot (index.d.ts 12156).

Remarks#

The pivot field is stored but not applied by the Sprite2DLayer pipeline; only Lite's billboard family reads it. @ignifx/2d applies it itself — see pivotedPositionToRef.

Unstable; excluded from the stability guarantees of CONSTITUTION.md Article IV.


LiteSpritePickInfo#

LiteSpritePickInfo = SpritePickInfo

A pickSprite2D hit: the layer, the dense sprite index, and the within-quad UV (index.d.ts 12179).

Remarks#

Unstable; excluded from the stability guarantees of CONSTITUTION.md Article IV.


LiteSpriteRenderer#

LiteSpriteRenderer = LiteSpriteRendererContext

Lite's sprite rendering context — the second rendering context @ignifx/2d registers on the app's surface, after the render scene, so 2D composites on top (index.d.ts 12215).

Remarks#

Unstable; excluded from the stability guarantees of CONSTITUTION.md Article IV.


LiteSpriteSampling#

LiteSpriteSampling = SpriteSampling

A sprite atlas's min/mag filter (index.d.ts 12229).

Remarks#

Unstable; excluded from the stability guarantees of CONSTITUTION.md Article IV.


SpriteBlendName#

SpriteBlendName = typeof SPRITE_BLEND_MODES[number]

How a sprite's colour combines with what is already in the framebuffer (docs/architecture/11-2d-toolkit.md §2.2).


SpriteEffectKind#

SpriteEffectKind = typeof SPRITE_EFFECT_KINDS[number]

Which shader a SpriteLayerEffect installs.


TileColliderDefinition#

TileColliderDefinition = { height: number; kind: "box"; oneWay?: boolean; width: number; x: number; y: number; } | { kind: "polygon"; oneWay?: boolean; points: readonly Vec2Like[]; } | { kind: "none"; }

A tile's collision footprint as authored: cell-normalised [0, 1] units with the origin at the cell's top-left corner and +Y pointing down.

Union Members#

Type Literal#

{ height: number; kind: "box"; oneWay?: boolean; width: number; x: number; y: number; }

height#

readonly height: number

The box's height, in cell-normalised units.

kind#

readonly kind: "box"

Discriminant: an axis-aligned box.

oneWay?#

readonly optional oneWay?: boolean

Whether the tile is a one-way platform. Defaults to false.

width#

readonly width: number

The box's width, in cell-normalised units.

x#

readonly x: number

The box's left edge, in cell-normalised units.

y#

readonly y: number

The box's top edge, in cell-normalised units measured downwards from the cell's top.


Type Literal#

{ kind: "polygon"; oneWay?: boolean; points: readonly Vec2Like[]; }

kind#

readonly kind: "polygon"

Discriminant: an outline.

oneWay?#

readonly optional oneWay?: boolean

Whether the tile is a one-way platform. Defaults to false.

points#

readonly points: readonly Vec2Like[]

The vertices in cell-normalised units with a top-left origin, in the editor's winding.


Type Literal#

{ kind: "none"; }

kind#

readonly kind: "none"

Discriminant: the tile renders but does not collide.

Remarks#

This is deliberately not TileCollisionShape, which is cell-local metres with a bottom-left origin, +Y up and counter-clockwise winding. Editors work top-down and the physics world works bottom-up; tileCollisionInfo converts, and nothing else should.

A box covering the top quarter of a cell — the usual one-way platform — is { kind: "box", x: 0, y: 0, width: 1, height: 0.25, oneWay: true }.


TileCollisionShape#

TileCollisionShape = { height: number; kind: "box"; width: number; x: number; y: number; } | { kind: "polygon"; points: readonly Vec2Like[]; } | { kind: "none"; }

The collision footprint of a single tile, expressed in cell-local metres with the origin at the bottom-left corner of the cell (ignifx 2D is +Y up — docs/adr/0011).

Union Members#

Type Literal#

{ height: number; kind: "box"; width: number; x: number; y: number; }

height#

readonly height: number

The box's height, in metres.

kind#

readonly kind: "box"

Discriminant: an axis-aligned box.

width#

readonly width: number

The box's width, in metres.

x#

readonly x: number

The box's left edge, in cell-local metres.

y#

readonly y: number

The box's bottom edge, in cell-local metres.


Type Literal#

{ kind: "polygon"; points: readonly Vec2Like[]; }

kind#

readonly kind: "polygon"

Discriminant: a convex or concave outline.

points#

readonly points: readonly Vec2Like[]

The outline's vertices in cell-local metres, wound counter-clockwise.


Type Literal#

{ kind: "none"; }

kind#

readonly kind: "none"

Discriminant: the tile does not collide.

Remarks#

"none" is the shape of a tile that renders but does not collide; it is the default for a tile whose tileset entry declares no collider.


TileObjectFactory#

TileObjectFactory = (context) => Entity | null

Builds the entities a tilemap's objects layer describes.

Parameters#

context#

TileObjectContext

Returns#

Entity | null


TwoDErrorCode#

TwoDErrorCode = typeof TwoDErrorCode[keyof typeof TwoDErrorCode]

The union of the codes the TwoDErrorCode table declares.


TwoDMode#

TwoDMode = typeof TWO_D_MODES[number]

How 2D composites with the 3D render scene.

Remarks#

"sprite" is a pure 2D game: sprites are the only thing drawn. "mixed" is 2.5D — the render scene draws first and the sprite pass composites on top without clearing, so meshes and sprites share a frame.


Vec2Json#

Vec2Json = Vec2Like | readonly [number, number]

A 2D value as a document may write it: [x, y], the form @ignifx/core encodes every vec2 field into a file as (schema/encode.ts line 393), or { x, y }, the form an importer emits.

Variables#

DEFAULT_CHUNK_SIZE#

const DEFAULT_CHUNK_SIZE: 32 = 32

How many cells one chunk spans by default (docs/architecture/11-2d-toolkit.md §2.5).


DEFAULT_CLIP_FPS#

const DEFAULT_CLIP_FPS: 12 = 12

The frames-per-second a clip that declares none plays at.


DEFAULT_ORTHOGRAPHIC_SIZE#

const DEFAULT_ORTHOGRAPHIC_SIZE: 5 = 5

The half-height, in metres, a camera that declares none shows.


DEFAULT_PIXELS_PER_UNIT#

const DEFAULT_PIXELS_PER_UNIT: 100 = 100

The default pixels-per-unit, matching twoD.pixelsPerUnit (docs/architecture/11-2d-toolkit.md §1). At 100, a 32-pixel sprite is 0.32 metres wide.


DEFAULT_REFERENCE_RESOLUTION#

const DEFAULT_REFERENCE_RESOLUTION: Vec2Like

The reference resolution a pixel-perfect camera fits an integer zoom to.


DEFAULT_SORTING_LAYER#

const DEFAULT_SORTING_LAYER: "Default" = "Default"

The sorting layer a component that names none draws on.


EMPTY_TILE_ID#

const EMPTY_TILE_ID: 0 = 0

The tile id that means "this cell is empty"; no tileset may claim it.


LDTK_DEFAULT_INTGRID_COLLIDERS#

const LDTK_DEFAULT_INTGRID_COLLIDERS: Readonly<Record<number, TileColliderDefinition>>

The default meaning of an LDtk IntGrid value, in cell-normalised top-left-origin units.

Remarks#

1 is "solid" — the whole cell collides. 2 is "one-way" — the top quarter of the cell collides, and only from above. Those two conventions cover the LDtk projects people actually ship, and anything else is project-specific, so LdtkImportOptions.intGridColliders replaces this table wholesale. An IntGrid value with no entry still gets a tile id and a frame; it simply does not collide.


LDTK_INTGRID_TILESET_NAME#

const LDTK_INTGRID_TILESET_NAME: "intgrid" = "intgrid"

The name given to the synthetic tileset that carries IntGrid colliders.


SORTING_LAYER_ORDER_STEP#

const SORTING_LAYER_ORDER_STEP: 1000 = 1000

How far apart two sorting layers' Lite order values sit.

Remarks#

A gap of 1000 leaves room for the per-(atlas, blend, space) sub-layers a single sorting layer expands into: one sorting layer holding sprites from twelve atlases in three blend modes still fits inside its slice without reaching the next layer's.


SPRITE_ANIMATION_ASSET_TYPE#

const SPRITE_ANIMATION_ASSET_TYPE: "spriteanimation" = "spriteanimation"

The asset type name the loader registers.


SPRITE_ANIMATION_FILE_EXTENSIONS#

const SPRITE_ANIMATION_FILE_EXTENSIONS: readonly string[]

The address suffixes that select the sprite-animation loader.


SPRITE_ANIMATION_FORMAT#

const SPRITE_ANIMATION_FORMAT: "ignifx.spriteanimation" = "ignifx.spriteanimation"

The format discriminator every .spriteanim.json document carries.


SPRITE_ANIMATION_FORMAT_VERSION#

const SPRITE_ANIMATION_FORMAT_VERSION: 1 = 1

The document version this build reads and writes.


SPRITE_ATLAS_ASSET_TYPE#

const SPRITE_ATLAS_ASSET_TYPE: "spriteatlas" = "spriteatlas"

The asset type name the loader registers.


SPRITE_ATLAS_FILE_EXTENSIONS#

const SPRITE_ATLAS_FILE_EXTENSIONS: readonly string[]

The address suffixes that select the sprite-atlas loader.


SPRITE_ATLAS_FORMAT#

const SPRITE_ATLAS_FORMAT: "ignifx.spriteatlas" = "ignifx.spriteatlas"

The format discriminator every .atlas.json document carries.


SPRITE_ATLAS_FORMAT_VERSION#

const SPRITE_ATLAS_FORMAT_VERSION: 1 = 1

The document version this build reads and writes.


SPRITE_BLEND_MODES#

const SPRITE_BLEND_MODES: readonly ["alpha", "premultiplied", "additive", "multiply", "opaque"]

The blend modes SpriteRenderer.blend accepts, in the order an inspector should list them.


SPRITE_EFFECT_KINDS#

const SPRITE_EFFECT_KINDS: readonly ["tint", "custom"]

The built-in effects, in the order an inspector should list them.


SPRITE_FRAME_FRAGMENT_PREFIX#

const SPRITE_FRAME_FRAGMENT_PREFIX: "frame:" = "frame:"

The fragment prefix that addresses one frame: "sprites/hero.atlas.json#frame:idle_0".


TILEMAP_ASSET_TYPE#

const TILEMAP_ASSET_TYPE: "tilemap" = "tilemap"

The asset type name the loader registers.


TILEMAP_FILE_EXTENSIONS#

const TILEMAP_FILE_EXTENSIONS: readonly string[]

The address suffixes that select the tilemap loader.


TILEMAP_FORMAT#

const TILEMAP_FORMAT: "ignifx.tilemap" = "ignifx.tilemap"

The format discriminator every .tilemap.json document carries.


TILEMAP_FORMAT_VERSION#

const TILEMAP_FORMAT_VERSION: 1 = 1

The document version this build reads and writes.


TINT_EFFECT_WGSL#

const TINT_EFFECT_WGSL: "let texel = textureSample(atlasTex, atlasSamp, uv); return vec4f(texel.rgb * fx.params.rgb, texel.a * fx.params.a);" = "let texel = textureSample(atlasTex, atlasSamp, uv); return vec4f(texel.rgb * fx.params.rgb, texel.a * fx.params.a);"

The WGSL body of the built-in tint effect.

Remarks#

Multiplies the sampled texel by fx.params.rgb and scales its alpha by fx.params.a, which is a per-layer tint that a per-sprite color cannot express — every sprite in the layer fades together, in one uniform write, rather than in one instance write each.


TWO_D_ANIMATION_ORDER#

const TWO_D_ANIMATION_ORDER: 0 = 0

The PostUpdate order the 2D animation system runs at.

Remarks#

PostUpdate is empty today — no core or extension system registers there — so 0 is the middle of an open phase. Anything a game adds later can sit either side of it by choosing a sign.


TWO_D_ERROR_MESSAGES#

const TWO_D_ERROR_MESSAGES: Readonly<Record<string, string>>

The one-line message template of every code, as ExtensionContext.registerErrorCodes wants it. Context keys appear in braces, matching the core table's convention.


TWO_D_MODES#

const TWO_D_MODES: readonly ["sprite", "mixed"]

Every rendering mode the 2D toolkit supports, in the order an inspector should list them (docs/architecture/11-2d-toolkit.md §1).


TWO_D_SETTINGS_SECTION#

const TWO_D_SETTINGS_SECTION: "twoD" = "twoD"

The section name as it appears in ignifx.config.ts and in a scene file's settings block.


TWO_D_SYNC_ORDER#

const TWO_D_SYNC_ORDER: -450 = -450

The PreRender order the 2D sync system runs at.

Remarks#

-450, not the -400 docs/architecture/11-2d-toolkit.md §2.2 names, because audio's pump already holds -400. See the module's own remarks.


twoD#

const twoD: (options?) => Extension

The @ignifx/2d extension factory.

Parameters#

options?#

TwoDOptions

Overrides for the twoD settings section.

Returns#

Extension

The extension descriptor to pass to createApp.

Example#

typescript
const app = await createApp({  canvas,  extensions: [twoD({ pixelsPerUnit: 16, ySort: { Default: true } })],});

TwoDErrorCode#

const TwoDErrorCode: object

Every diagnostic code @ignifx/2d can throw or log, keyed by an intention-revealing name so call sites read as prose and the compiler catches typos (coding standards §5.2).

Type Declaration#

atlasFrameNotExtruded#

readonly atlasFrameNotExtruded: "IGX-1102" = "IGX-1102"

An atlas frame has no one-pixel extruded border, which a pixel-perfect camera will bleed.

duplicateExtension#

readonly duplicateExtension: "IGX-1112" = "IGX-1112"

A second twoD() extension was registered on one app.

duplicateObjectFactory#

readonly duplicateObjectFactory: "IGX-1110" = "IGX-1110"

app.twoD.registerTileObjectFactory was called twice for one object type.

invalidAnimationFile#

readonly invalidAnimationFile: "IGX-1104" = "IGX-1104"

A .spriteanim.json file is not an ignifx.spriteanimation document this build can read.

invalidAtlasFile#

readonly invalidAtlasFile: "IGX-1103" = "IGX-1103"

A .atlas.json file is not an ignifx.spriteatlas document this build can read.

invalidTilemapFile#

readonly invalidTilemapFile: "IGX-1105" = "IGX-1105"

A .tilemap.json file is not an ignifx.tilemap document this build can read.

missingShaderSource#

readonly missingShaderSource: "IGX-1113" = "IGX-1113"

A SpriteLayerEffect declared the custom kind without a WGSL fragment body.

tileOutOfRange#

readonly tileOutOfRange: "IGX-1111" = "IGX-1111"

A tile coordinate is outside the tilemap layer's bounds.

unknownClip#

readonly unknownClip: "IGX-1108" = "IGX-1108"

SpriteAnimator.play named a clip the animation asset does not declare.

unknownFrame#

readonly unknownFrame: "IGX-1106" = "IGX-1106"

A sprite address names a frame the atlas does not declare.

unknownSortingLayer#

readonly unknownSortingLayer: "IGX-1107" = "IGX-1107"

A component named a sorting layer the sortingLayers settings section does not declare.

unsupportedImport#

readonly unsupportedImport: "IGX-1109" = "IGX-1109"

A tilemap importer was handed a document it cannot read, or an unsupported projection.

Example#

typescript
throw twoDError(TwoDErrorCode.unknownSortingLayer, "Foreground is not a declared sorting layer.", {  context: { sortingLayer: "Foreground" },});

VERSION#

const VERSION: "0.0.0" = "0.0.0"

The @ignifx/2d version this build was cut from.

Functions#

asepriteFrameName()#

asepriteFrameName(raw): string

Normalises an Aseprite frame key into an identifier a clip and a #frame: fragment can name.

The rule, applied in this order:

  1. Drop a trailing file extension — a dot, a letter, then up to seven more alphanumerics — so hero 0.aseprite and hero_0.png both lose their suffix but walk.2 does not.
  2. Replace every run of non-alphanumeric characters with a single _.
  3. Trim leading and trailing _.

Case is preserved: Hero (Idle) 0.aseprite becomes Hero_Idle_0, not hero_idle_0. A key that normalises to nothing at all ("###.png") becomes frame.

importAsepriteAtlas and importAsepriteAnimations both run keys through this function, which is what makes an imported clip's frame names line up with the imported atlas's.

Parameters#

raw#

string

The frame key as Aseprite wrote it — a hash key, or an array entry's filename.

Returns#

string

The normalised frame name.

Example#

typescript
asepriteFrameName("hero (idle) 0.aseprite"); // "hero_idle_0"asepriteFrameName("hero_0.png"); // "hero_0"

createSpriteAnimationLoader()#

createSpriteAnimationLoader(): AssetLoader<SpriteAnimationAsset>

Builds the loader for .spriteanim.json addresses.

Returns#

AssetLoader<SpriteAnimationAsset>

The loader to register with ctx.registerAssetLoader.

Example#

typescript
ctx.registerAssetLoader(createSpriteAnimationLoader());

createSpriteAtlasLoader()#

createSpriteAtlasLoader(): AssetLoader<SpriteAtlasAsset>

Builds the loader for .atlas.json addresses.

Returns#

AssetLoader<SpriteAtlasAsset>

The loader to register with ctx.registerAssetLoader.

Example#

typescript
ctx.registerAssetLoader(createSpriteAtlasLoader());

createTilemapLoader()#

createTilemapLoader(): AssetLoader<TilemapAsset>

Builds the loader for .tilemap.json addresses.

Returns#

AssetLoader<TilemapAsset>

The loader to register with ctx.registerAssetLoader.

Example#

typescript
ctx.registerAssetLoader(createTilemapLoader());

decodeTileRle()#

decodeTileRle(rle): readonly number[]

Expands the [count, value, …] pairs encodeTileRle produces back into a dense array.

Parameters#

rle#

readonly number[]

The encoded pairs.

Returns#

readonly number[]

The dense tile ids.

Throws#

IgnifxError with code IGX-1105 when the array has an odd length, or a run count that is not a finite non-negative integer.

Example#

typescript
decodeTileRle([2, 1, 3, 0]); // [1, 1, 0, 0, 0]

defaultTwoDSettings()#

defaultTwoDSettings(): TwoDSettings

The values used for everything a project omits.

Returns#

TwoDSettings

The default twoD section.


defineSpriteAnimation()#

defineSpriteAnimation(input, address?): SpriteAnimationDefinition

Fills in the defaults of an animation document and checks the invariants the animator relies on.

Parameters#

input#

SpriteAnimationInput

The document, as authored or as an importer emitted it.

address?#

string = "<inline>"

What to name in an error; defaults to "<inline>".

Returns#

SpriteAnimationDefinition

The complete document.

Throws#

IgnifxError with code IGX-1104 when the format tag, the version, or a clip is wrong.


defineSpriteAtlas()#

defineSpriteAtlas(input, address?): SpriteAtlasDefinition

Fills in the defaults of an atlas document and checks the invariants a loader relies on.

Parameters#

input#

SpriteAtlasInput

The document, as authored or as an importer emitted it.

address?#

string = "<inline>"

What to name in an error; defaults to "<inline>".

Returns#

SpriteAtlasDefinition

The complete document.

Throws#

IgnifxError with code IGX-1103 when the format tag, the version, the image address, or a frame rectangle is wrong, or two frames share a name.


defineTilemap()#

defineTilemap(input, address?): TilemapDefinition

Fills in the defaults of a tilemap document, decodes any run-length-encoded layer, and checks the invariants the renderer and the collider rely on.

Parameters#

input#

TilemapInput

The document, as authored or as an importer emitted it.

address?#

string = "<inline>"

What to name in an error; defaults to "\<inline\>".

Returns#

TilemapDefinition

The complete document, with every layer's tiles dense.

Throws#

IgnifxError with code IGX-1105 when the format tag or version is wrong, a tile size is not positive, a tileset's firstId is not positive, two layers share a name, a run-length array has an odd length, or a layer's decoded tile count is not width * height.


describeSchemas()#

describeSchemas(): Readonly<Record<string, SchemaDescription>>

The name pnpm docs:schemas discovers this package's schemas under.

Returns#

Readonly<Record<string, SchemaDescription>>

The same records describeTwoDSchemas returns.


describeSpriteAnimationFormat()#

describeSpriteAnimationFormat(): SchemaDescription

Describes the ignifx.spriteanimation file format.

Returns#

SchemaDescription

The record pnpm docs:schemas renders.


describeSpriteAtlasFormat()#

describeSpriteAtlasFormat(): SchemaDescription

Describes the ignifx.spriteatlas file format.

Returns#

SchemaDescription

The record pnpm docs:schemas renders.


describeTilemapFormat()#

describeTilemapFormat(): SchemaDescription

Describes the ignifx.tilemap file format.

Returns#

SchemaDescription

The record pnpm docs:schemas renders.


describeTwoDSchemas()#

describeTwoDSchemas(): Readonly<Record<string, SchemaDescription>>

Describes every component and file format this package declares, for the documentation harness.

Returns#

Readonly<Record<string, SchemaDescription>>

The records, keyed by namespaced type id.

Example#

typescript
describeTwoDSchemas()["ignifx/Camera2D"].fields["orthographicSize"].default; // 5

encodeTileRle()#

encodeTileRle(tiles): readonly number[]

Run-length encodes a dense tile array.

Parameters#

tiles#

readonly number[]

The dense tile ids.

Returns#

readonly number[]

The encoded pairs; empty for an empty input.

Remarks#

The layout is flat [count, value, count, value, …] pairs, read left to right, so [1, 1, 0, 0, 0] encodes to [2, 1, 3, 0]. It is the same shape Tiled's chunk encoding and LDtk's exports settle on, and it round-trips exactly through decodeTileRle.

Example#

typescript
encodeTileRle([1, 1, 0, 0, 0]); // [2, 1, 3, 0]

fieldInstancesToRecord()#

fieldInstancesToRecord(fields): Readonly<Record<string, string | number | boolean>>

Flattens LDtk's [{ __identifier, __type, __value }] field instances into a plain record.

Parameters#

fields#

unknown

The value of a fieldInstances field, or anything else.

Returns#

Readonly<Record<string, string | number | boolean>>

The flattened record; empty when fields is not a field-instance array.

Remarks#

Only string, number and boolean values survive. LDtk's richer field types — points, entity references, arrays, enum tuples — have no equivalent in the tilemap format's flat property record and are dropped rather than stringified.

Example#

typescript
fieldInstancesToRecord([{ __identifier: "facing", __type: "String", __value: "left" }]);// { facing: "left" }

findTileset()#

findTileset(map, tileId): TilesetDefinition | null

Resolves a global tile id to the tileset that owns it.

Parameters#

map#

TilemapDefinition

The parsed document.

tileId#

number

The global tile id.

Returns#

TilesetDefinition | null

The owning tileset, or null for the empty tile and for an id no tileset claims.

Remarks#

The owner is the tileset with the highest TilesetDefinition.firstId that is still less than or equal to tileId — the rule Tiled's firstgid implies. defineTilemap sorts the tilesets ascending, so this is a backward scan over a handful of entries.


gridAtlas()#

gridAtlas(options): SpriteAtlasDefinition

Cuts an evenly spaced sprite sheet into an ignifx.spriteatlas document.

Frames come out in reading order — left to right, then top to bottom — named <namePrefix>_<index> with index counting from 0 across the whole sheet, so a 4×2 grid ends at tile_7. columns and rows default to as many whole cells as the image holds (floor((imageWidth - 2·margin + spacing) / (cellWidth + spacing)), and likewise for rows) and are clamped to that capacity when given, so an over-large explicit count never produces a frame that falls off the image.

Parameters#

options#

GridAtlasImportOptions

The sheet's geometry and the frame naming.

Returns#

SpriteAtlasDefinition

The complete atlas document.

Remarks#

namePrefix is how a grid atlas lines up with the rest of the toolkit: @ignifx/2d's Tiled importer names a tileset's frames <tilesetName>_<index>, so passing the tileset's name as namePrefix makes a hand-cut grid atlas addressable by exactly the names a tilemap emits.

Throws#

IgnifxError with code IGX-1109 when a cell dimension is not positive, or when the geometry yields no frames at all.

Example#

typescript
const atlas = gridAtlas({  image: "2d/terrain.png",  imageWidth: 64,  imageHeight: 64,  cellWidth: 32,  cellHeight: 32,  namePrefix: "terrain",  sampling: "nearest",});atlas.frames.map((frame) => frame.name); // ["terrain_0", "terrain_1", "terrain_2", "terrain_3"]

importAsepriteAnimations()#

importAsepriteAnimations(json, options?): SpriteAnimationDefinition

Converts an Aseprite sheet export's tags into an ignifx.spriteanimation document.

Every entry in meta.frameTags becomes one clip, named after the tag, listing the frame names for indices from through to explicitly rather than as a range — a clip that lists names survives an atlas being repacked in a different order.

Playback direction is baked into that list, because ignifx clips play forwards:

  • "forward" (and anything unrecognised) lists from … to in order.
  • "reverse" lists them backwards.
  • "pingpong" lists them forwards and then appends the interior frames in reverse, so a three-frame tag becomes 0, 1, 2, 1 — the ends are not repeated, which is what makes the clip loop seamlessly.

loop is true unless the tag's repeat is the string "1", Aseprite's "play once".

Parameters#

json#

unknown

The parsed Aseprite document.

options?#

AsepriteAnimationImportOptions

The atlas address, the fallback rate, and a frame-naming override.

Returns#

SpriteAnimationDefinition

The complete animation document, already through defineSpriteAnimation.

Remarks#

Aseprite stores a duration per frame, in milliseconds, while an ignifx clip carries a single fps. A tag is therefore approximated by the mean of its frames' durations: fps is 1000 / averageDuration, rounded to three decimal places. A tag whose frames all share a duration converts exactly; one with uneven durations does not, and the individual frames will hold for the average instead of their authored time. Split such a tag, or even the durations out in Aseprite, when the timing matters. When no frame in the range declares a positive duration, options.defaultFps — itself defaulting to 12 — is used instead.

Aseprite has no frame-event concept, so no clip carries events.

Throws#

IgnifxError with code IGX-1109 when the document is not an object, when meta.frameTags is missing, is not an array, or is empty, when a tag has no name, or when frames cannot be named because the document has no readable frames and no frameNameOf was supplied.

Example#

typescript
const animations = importAsepriteAnimations(JSON.parse(text), { atlas: "2d/hero.atlas.json" });animations.clips[0]; // { name: "idle", frames: ["hero_0", "hero_1"], fps: 10, loop: true }

importAsepriteAtlas()#

importAsepriteAtlas(json, options?): SpriteAtlasDefinition

Converts an Aseprite JSON sheet export into an ignifx.spriteatlas document.

Aseprite writes a TexturePacker-shaped document — frames as either a hash or an array, meta.image, meta.size — plus its own meta.frameTags, meta.slices and meta.layers. The frame keys it produces are file-ish (hero 0.aseprite, hero (idle) 0.aseprite), so every one is put through asepriteFrameName; importAsepriteAnimations uses the same normaliser, which is what makes the imported clips and the imported atlas agree on names.

A trimmed frame keeps its sourceSize so the loader can place the trimmed rectangle back inside its original bounds.

Parameters#

json#

unknown

The parsed Aseprite document.

options?#

AsepriteImportOptions

The image override and sampling.

Returns#

SpriteAtlasDefinition

The complete atlas document.

Remarks#

Pivots are best-effort. Aseprite has no per-frame pivot; it has slices, which carry an optional pivot in sprite-canvas pixels relative to the slice's own bounds and apply from their key's frame index onwards. This importer takes the slice key with the greatest frame index at or below the frame being converted (ties going to the earlier slice in document order) and normalises bounds + pivot against the frame's untrimmed size, clamped into [0, 1]. That is right for the common case — one slice covering the character, authored on an untrimmed sheet — and approximate for anything else. Frames no slice covers get the centre.

Throws#

IgnifxError with code IGX-1109 when the document is not an object, when frames is neither an object nor an array, when it is empty, when no image address can be found, or when a frame has no rectangle.

Example#

typescript
const atlas = importAsepriteAtlas(JSON.parse(text), { sampling: "nearest" });atlas.frames[0]?.name; // "hero_idle_0", from the key "hero (idle) 0.aseprite"

importLdtkLevel()#

importLdtkLevel(ldtk, options?): TilemapDefinition

Imports one level of an LDtk project.

Parameters#

ldtk#

unknown

The parsed .ldtk project.

options?#

LdtkImportOptions = {}

The level to pick, pixels-per-unit, the sorting layer, and the mappings.

Returns#

TilemapDefinition

The ignifx.tilemap document for that level.

Remarks#

Three LDtk conventions need translating, and each is a place a naive importer goes wrong:

  • Layer order is reversed. LDtk stores layerInstances front-to-back — index 0 is the layer drawn on top. ignifx layers are back-to-front, so the list is reversed and orderInLayer follows the reversed index.
  • Tile layers are sparse. gridTiles is a list of { px, t } placements, not a grid; the importer expands it into the dense __cWid * __cHei array the tilemap format wants, filling the gaps with 0. t is a tile index within its tileset, so the global id is tileset.firstId + t. A layer's pxOffsetX/pxOffsetY shift the grid; a dense grid has no sub-cell placement, so the offset is rounded to whole cells.
  • IntGrid layers are collision, not art. An intGridCsv becomes a layer with collision: true whose ids point into a synthetic, art-less tileset named LDTK_INTGRID_TILESET_NAME; see LDTK_DEFAULT_INTGRID_COLLIDERS for the value mapping and LdtkImportOptions.intGridColliders for overriding it.

A tileset's customData entries are read as JSON, and an entry that parses to an object with solid: true gives its tile a full-cell box collider. Data that is not JSON, or that says something else, is ignored rather than treated as an error — customData is a free-form field and other tools put other things in it.

Per-tile flips (gridTiles[].f) are dropped, as they are in the Tiled importer: the tilemap format has no per-cell flip yet.

Throws#

IgnifxError with code IGX-1109 when the project has no levels, when LdtkImportOptions.level names a level that is not there, or when a layer's type is not Tiles, IntGrid or Entities; and IGX-1105 when what it decodes to is not a valid tilemap.

Example#

typescript
const map = importLdtkLevel(JSON.parse(await readFile("world.ldtk", "utf8")), { level: "Cave" });

importTexturePackerAtlas()#

importTexturePackerAtlas(json, options?): SpriteAtlasDefinition

Converts a TexturePacker JSON export into an ignifx.spriteatlas document.

Both of TexturePacker's JSON layouts are read and produce identical output for the same sheet: the hash layout, whose frames is an object keyed by file name, and the array layout, whose frames is an array of entries carrying a filename. Frame names lose their trailing file extension (hero_0.png becomes hero_0) unless keepExtensions is set.

A frame's pivot is used as-is when the document declares one: TexturePacker already writes pivots normalised into [0, 1] against a top-left origin, which is exactly ignifx's convention. Frames without one get the centre. A frame marked trimmed carries its sourceSize through so the loader can lay the trimmed rectangle back inside its original bounds.

Parameters#

json#

unknown

The parsed TexturePacker document.

options?#

TexturePackerImportOptions

The image override, name handling, and sampling.

Returns#

SpriteAtlasDefinition

The complete atlas document.

Remarks#

Rotated frames are rejected rather than silently drawn wrong — the sprite pipeline has no per-frame rotation flag.

spriteSourceSize's offset (x/y) has no home in SpriteFrameDefinition, which records only the untrimmed size, so a trimmed frame whose art is not centred in its source bounds may sit slightly off. Pack with trimming disabled, or with spriteSourceSize centred, when that matters.

Throws#

IgnifxError with code IGX-1109 when the document is not an object, when frames is neither an object nor an array, when it is empty, when no image address can be found, when a frame has no rectangle, or when a frame is rotated.

Example#

typescript
const atlas = importTexturePackerAtlas(JSON.parse(text), { image: "2d/hero.png" });atlas.frames[0]?.name; // "hero_0"

importTiledMap()#

importTiledMap(tmj, options?): TilemapDefinition

Imports a Tiled JSON map.

Parameters#

tmj#

unknown

The parsed .tmj document.

options?#

TiledImportOptions = {}

Pixels-per-unit, the default sorting layer, and the atlas address mapping.

Returns#

TilemapDefinition

The ignifx.tilemap document.

Remarks#

Three Tiled features are rejected outright with IGX-1109 rather than approximated: a non orthogonal orientation, an infinite map (whose layers are chunked rather than dense), and base64/compressed layer data (which arrives as a string). Everything else degrades quietly — image layers and group layers are skipped, and unknown properties are carried through.

Tiled stores the horizontal, vertical and diagonal flip flags in the top three bits of every global tile id. ignifx has no per-cell flip yet, so those bits are masked off and the tile draws unflipped; without the mask a flipped tile would resolve to a nonsensical tileset.

The frame names this importer emits are <tilesetName>_<localTileIndex> — the same names the grid-atlas generator gives the frames it cuts out of the tileset image, which is the contract that lets TilemapRenderer look a tile's sprite up without a side table.

Throws#

IgnifxError with code IGX-1109 when the document is not an orthogonal, finite, uncompressed Tiled map, and IGX-1105 when what it decodes to is not a valid tilemap.

Example#

typescript
const map = importTiledMap(JSON.parse(await readFile("cave.tmj", "utf8")), { pixelsPerUnit: 32 });

isFullCellSolid()#

isFullCellSolid(info, cellSize): boolean

Whether a tile's collider fills its whole cell and is not a one-way platform — the only shape the rectangle merge can absorb.

Parameters#

info#

TileCollisionInfo

The tile's collision info, in cell-local metres.

cellSize#

number

The edge length of one cell, in metres.

Returns#

boolean

Whether the tile is a plain, full-cell solid.

Example#

typescript
isFullCellSolid({ shape: { kind: "box", x: 0, y: 0, width: 1, height: 1 }, oneWay: false, properties: {} }, 1);// true

mergeTileCollisions()#

mergeTileCollisions(infoAt, options, version): TilemapCollisionData

Merges a grid of per-tile collision shapes into chunked, world-space polygons.

Parameters#

infoAt#

(x, y) => TileCollisionInfo

The per-cell collision info, in cell coordinates with y = 0 at the bottom.

options#

CollisionMergeOptions

The cell size, chunk size, and grid extent.

version#

number

The version stamp to carry into the result; callers increment it per rebuild.

Returns#

TilemapCollisionData

The chunked collision data.

Remarks#

Coordinates. infoAt is called with cell coordinates in which y = 0 is the bottom row, because the ignifx 2D world is +Y up; a caller reading a TilemapLayerDefinition, whose rows run top-first, indexes it as (height - 1 - y) * width + x. Everything this function emits is world metres relative to the tilemap's origin, so cell (x, y) spans [x·cellSize, (x+1)·cellSize] × [y·cellSize, (y+1)·cellSize].

The merge. Each chunk is handled independently, so a later edit rebuilds one chunk rather than the map. Inside a chunk, cells that isFullCellSolid accepts go into a boolean grid and are merged in two greedy passes: first every row is cut into maximal horizontal runs, then a run extends upwards for as long as the row above holds a run with exactly the same span, which is marked consumed. Each surviving block is emitted as one counter-clockwise rectangle. It is the classic row-then-column greedy mesher: linear in cells plus a small scan per row, and optimal for rectangles while deliberately not optimal in general — an L-shape comes out as two rectangles, not one six-vertex polygon, and that is the trade the algorithm makes for being O(n).

Anything the rectangle pass cannot absorb — a partial box, a slope polygon — is emitted as its own polygon, translated into world metres. Its winding is already counter-clockwise, because tileCollisionInfo guarantees it.

One-way platforms. A one-way tile contributes no polygon at all; it contributes its collider's top edge to oneWayEdges. The winding follows the same rule as a polygon: the solid material is to the left of from → to. For a directed edge d = to − from, "left" is d rotated a quarter turn counter-clockwise, (−dy, dx). An upward-facing platform is solid below its surface — that is the half you cannot pass through once you have landed — so we need (−dy, dx) = (0, −1), giving dy = 0 and dx = −1. The edge therefore runs from its right end to its left end.

Chunks that end up with neither a polygon nor a one-way edge are omitted entirely.

Example#

typescript
const data = mergeTileCollisions((x, y) => tileCollisionInfo(map, tileAt(x, y)), {  cellSize: map.cellSize,  chunkSize: 32,  width: map.width,  height: map.height,}, 1);

normalisePath()#

normalisePath(path): string

Collapses . and .. segments in a /-separated path.

Parameters#

path#

string

The path to normalise.

Returns#

string

The normalised path; leading .. segments that escape the root are dropped.


parseSpriteFragment()#

parseSpriteFragment(fragment): string | null

Splits a sprite address into its atlas address and its frame name.

Parameters#

fragment#

string | null

The part after #, or null for a bare atlas address.

Returns#

string | null

The frame name, or null when the fragment does not select a frame.

Example#

typescript
parseSpriteFragment("frame:idle_0"); // "idle_0"

pivotedPositionToRef()#

pivotedPositionToRef<TOut>(anchorXPx, anchorYPx, pivot, widthPx, heightPx, rotationRadians, out): TOut

Places the pivot of a sprite at a world point by offsetting the position Lite draws it at.

Type Parameters#

TOut#

TOut extends MutableVec2

Parameters#

anchorXPx#

number

The world anchor, in layer pixels.

anchorYPx#

number

The world anchor, in layer pixels.

pivot#

Vec2Like

The pivot in [0, 1] of the frame; [0, 0] is top-left, [1, 1] bottom-right.

widthPx#

number

The drawn width, in pixels.

heightPx#

number

The drawn height, in pixels.

rotationRadians#

number

The sprite's Lite rotation, which the offset turns with.

out#

TOut

The vector to write.

Returns#

TOut

out: the value to write to Sprite2DProps.positionPx.

Remarks#

Lite's sprite pipeline has one pivot per layer, not per sprite or per frame: the vertex shader reads L.pivot out of the layer uniform (lib/sprite/sprite-pipeline.js lines 25 and 264–265), and the per-frame SpriteFrame.pivot is consumed only by the billboard family (lib/sprite/billboard-sprite.js lines 166–167). ignifx therefore keeps every layer on the centre pivot [0.5, 0.5] and moves the sprite instead, which is what makes a per-frame pivot and SpriteRenderer.pivotOverride work at all.


pixelsToWorldToRef()#

pixelsToWorldToRef<TOut>(xPx, yPx, pixelsPerUnit, out): TOut

Converts a Lite layer-pixel point back to world metres.

Type Parameters#

TOut#

TOut extends MutableVec2

Parameters#

xPx#

number

The layer x, in pixels.

yPx#

number

The layer y, in pixels, with +Y down.

pixelsPerUnit#

number

The pixels one metre spans.

out#

TOut

The vector to write.

Returns#

TOut

out, in metres with +Y up.


readVec2()#

readVec2(value, fallback): Vec2Like

Normalises either written form of a 2D value.

Parameters#

value#

Vec2Json | undefined

What the document wrote, or undefined.

fallback#

Vec2Like

What to use when the document wrote nothing.

Returns#

Vec2Like

The normalised vector.


resolveClipFrames()#

resolveClipFrames(clip, indexOf): readonly number[]

Resolves a clip's frame names into atlas frame indices.

Parameters#

clip#

SpriteClipDefinition

The clip to resolve.

indexOf#

(name) => number

Maps an atlas frame name to its index, or -1 when the atlas has no such frame.

Returns#

readonly number[]

The indices in play order; empty when the clip names nothing the atlas has.


resolveRelative()#

resolveRelative(base, reference): string

Resolves a document-relative reference against the document's own address or URL.

Parameters#

base#

string

The address or URL of the document holding the reference.

reference#

string

What the document wrote.

Returns#

string

The resolved address or URL.

Remarks#

A reference that is absolute — one of the recognised URL schemes, or one starting with / — is returned untouched, so a project that prefers project-root addresses can write them. . and .. segments are collapsed, and a base with no / at all is treated as a file in the root.

Example#

typescript
resolveRelative("2d/hero.atlas.json", "hero.png"); // "2d/hero.png"resolveRelative("2d/hero.atlas.json", "../shared/pal.png"); // "shared/pal.png"resolveRelative("2d/hero.atlas.json", "/sprites/hero.png"); // "/sprites/hero.png"

selectCamera()#

selectCamera(world): Camera2D | null

Picks the camera the frame draws through: the highest-priority enabled Camera2D.

Parameters#

world#

World

The world to search.

Returns#

Camera2D | null

The camera, or null when the world has none enabled.


sizeForZoom()#

sizeForZoom(viewportHeightPx, zoom, pixelsPerUnit): number

The inverse of zoomForSize: what half-height a zoom shows.

Parameters#

viewportHeightPx#

number

The viewport height, in pixels.

zoom#

number

The Sprite2DView.zoom value.

pixelsPerUnit#

number

The pixels one metre spans.

Returns#

number

The half-height, in metres.


snapPixel()#

snapPixel(valuePx, zoom): number

Snaps a layer-pixel coordinate to the whole-pixel grid a pixel-perfect camera draws on.

Parameters#

valuePx#

number

The coordinate, in layer pixels.

zoom#

number

The camera's zoom; at zoom 2 the grid step is half a layer pixel.

Returns#

number

The snapped coordinate.


snapZoomToInteger()#

snapZoomToInteger(zoom): number

Snaps a zoom to the nearest usable integer for a pixel-perfect camera (docs/architecture/11-2d-toolkit.md §4).

Parameters#

zoom#

number

The continuous zoom zoomForSize produced.

Returns#

number

The snapped zoom, always greater than zero.

Remarks#

Zooms below 1 snap to the reciprocal of an integer (1/2, 1/3, …) rather than to zero, so a camera that is pulled far out still lands on a whole-texel scale.


spawnTilemapObjects()#

spawnTilemapObjects(app, service, tilemap): readonly Entity[]

Runs the registered factory for every object in one tilemap.

Parameters#

app#

App

The app.

service#

TwoDService

The 2D service holding the factory registry.

tilemap#

Tilemap

The tilemap whose objects layer to walk.

Returns#

readonly Entity[]

The entities that were created, in document order.

Example#

typescript
app.twoD.registerTileObjectFactory("spawn", ({ world, position }) => {  const player = world.createEntity({ name: "player" });  player.transform.position2D = new Vec2(position.x, position.y);  return player;});

spriteAnimationFileSchema()#

spriteAnimationFileSchema(): Schema

The ignifx.spriteanimation document schema.

Returns#

Schema

The schema, built fresh so no module holds state (CONSTITUTION.md §3.5).


spriteAnimationJsonSchema()#

spriteAnimationJsonSchema(): JsonObject

The JSON Schema a tool validates a .spriteanim.json document against.

Returns#

JsonObject

The JSON Schema object.


spriteAtlasFileSchema()#

spriteAtlasFileSchema(): Schema

The ignifx.spriteatlas document schema.

Returns#

Schema

The schema, built fresh so no module holds state (CONSTITUTION.md §3.5).


spriteAtlasJsonSchema()#

spriteAtlasJsonSchema(): JsonObject

The JSON Schema a tool validates a .atlas.json document against.

Returns#

JsonObject

The JSON Schema object.


spriteLayerKey()#

spriteLayerKey(sortingLayer, atlasAddress, blend, screenSpace): string

Builds the composite key two sprites must share to land in one Lite layer.

Parameters#

sortingLayer#

string

The sorting layer's name.

atlasAddress#

string

The atlas's address.

blend#

"alpha" | "premultiplied" | "additive" | "multiply" | "opaque"

The blend mode.

screenSpace#

boolean

Whether the layer ignores the camera.

Returns#

string

The key.


spriteRotationFromLite()#

spriteRotationFromLite(radians): number

Converts a Lite sprite rotation back to ignifx degrees.

Parameters#

radians#

number

The Sprite2DProps.rotation value.

Returns#

number

The ignifx rotation, in degrees counter-clockwise.


spriteRotationToLite()#

spriteRotationToLite(degrees): number

Converts an ignifx rotation about +Z into the rotation Lite gives a sprite.

Parameters#

degrees#

number

The ignifx rotation, in degrees counter-clockwise.

Returns#

number

The rotation to write to Sprite2DProps.rotation, in radians.

Remarks#

Transform.rotation2D is degrees counter-clockwise in a +Y-up world. A sprite's quad is built in Lite's +Y-down pixel space ((corner - pivot) * sizePx, then rotated), so the same visual turn is the negated angle there. Verified against the sprite vertex shader in @babylonjs/[email protected], lib/sprite/sprite-pipeline.js line 25.


tileCollisionInfo()#

tileCollisionInfo(map, tileId): TileCollisionInfo

Resolves a global tile id into the collision information a physics backend consumes.

Parameters#

map#

TilemapDefinition

The parsed document.

tileId#

number

The global tile id, 0 for an empty cell.

Returns#

TileCollisionInfo

The tile's runtime collision info; a non-colliding, non-one-way default for the empty tile, for an id no tileset claims, and for a tile that declares no collider.

Remarks#

This is the only place the authoring convention becomes the runtime one. A TileColliderDefinition is cell-normalised with a top-left origin and +Y down; a TileCollisionShape is cell-local metres with a bottom-left origin, +Y up and counter-clockwise winding. So:

  • a box's bottom edge is (1 - y - height) * cellSize, because the authored y measures the distance from the cell's top down to the box's top edge;
  • a polygon's points each become (x * cellSize, (1 - y) * cellSize), and the point order is reversed, because mirroring a ring about a horizontal axis flips its winding — a clockwise editor outline is counter-clockwise once flipped only if it is also walked backwards.

Example#

typescript
// A one-way platform authored as the top quarter of the cell, at cellSize 1:tileCollisionInfo(map, 2).shape; // { kind: "box", x: 0, y: 0.75, width: 1, height: 0.25 }

tiledPropertiesToRecord()#

tiledPropertiesToRecord(properties): Readonly<Record<string, string | number | boolean>>

Flattens Tiled's [{ name, type, value }] property arrays into a plain record.

Parameters#

properties#

unknown

The value of a Tiled properties field, or anything else.

Returns#

Readonly<Record<string, string | number | boolean>>

The flattened record; empty when properties is not a Tiled property array.

Remarks#

Only string, number and boolean values survive; Tiled's object and class property types carry editor-side references that mean nothing at runtime, and are dropped rather than stringified into something that looks meaningful but is not. color and file properties are strings in the JSON and come through as strings.

Example#

typescript
tiledPropertiesToRecord([{ name: "biome", type: "string", value: "cave" }]); // { biome: "cave" }

tileFrameName()#

tileFrameName(map, tileId): string | null

The atlas frame a global tile id draws.

Parameters#

map#

TilemapDefinition

The parsed document.

tileId#

number

The global tile id.

Returns#

string | null

The frame name, or null for the empty tile and for an id no tileset claims.

Example#

typescript
tileFrameName(map, 1); // "hero_0"

tilemapFileSchema()#

tilemapFileSchema(): Schema

The ignifx.tilemap document schema.

Returns#

Schema

The schema, built fresh so no module holds state (CONSTITUTION.md §3.5).


tilemapJsonSchema()#

tilemapJsonSchema(): JsonObject

The JSON Schema a tool validates a .tilemap.json document against.

Returns#

JsonObject

The JSON Schema object.


twoDError()#

twoDError(code, message, options?): IgnifxError

Builds an IgnifxError carrying one of this package's codes.

Parameters#

code#

TwoDErrorCode

The code from the TwoDErrorCode table.

message#

string

The actionable development sentence.

options?#

TwoDErrorOptions

Context identifiers, a remedy hint, and the wrapped cause.

Returns#

IgnifxError

The error to throw or to reject with.

Example#

typescript
throw twoDError(TwoDErrorCode.unknownClip, "hero.spriteanim.json declares no clip named jump.", {  context: { asset: "hero.spriteanim.json", clip: "jump" },});

twoDSettingsSchema()#

twoDSettingsSchema(): Schema

The schema the twoD section is validated against, in ignifx.config.ts and in a scene file alike.

Returns#

Schema

The schema, built fresh so no module holds state (CONSTITUTION.md §3.5).


viewRotationToLite()#

viewRotationToLite(degrees): number

Converts a Camera2D rotation into the rotation Lite gives a view.

Parameters#

degrees#

number

The camera rotation, in degrees counter-clockwise.

Returns#

number

The rotation to write to Sprite2DView.rotation, in radians.

Remarks#

A view rotation is applied to an already-flipped world offset rather than to a sprite-local offset, and the two flips cancel — so unlike spriteRotationToLite the sign is kept. Verified against sprite2DWorldToScreenToRef in @babylonjs/[email protected], lib/sprite/sprite-2d-view.js.


worldToPixelsToRef()#

worldToPixelsToRef<TOut>(x, y, pixelsPerUnit, out): TOut

Converts a world point in metres to a Lite layer-pixel point.

Type Parameters#

TOut#

TOut extends MutableVec2

Parameters#

x#

number

The world x, in metres.

y#

number

The world y, in metres, with +Y up.

pixelsPerUnit#

number

The pixels one metre spans.

out#

TOut

The vector to write.

Returns#

TOut

out, in pixels with +Y down.

Example#

typescript
worldToPixelsToRef(1.5, 0.5, 100, out); // out is (150, -50)

zoomForSize()#

zoomForSize(viewportHeightPx, orthographicSize, pixelsPerUnit): number

The zoom a Camera2D needs so that orthographicSize metres fill half the viewport's height (docs/architecture/11-2d-toolkit.md §2.1).

Parameters#

viewportHeightPx#

number

The viewport height, in pixels.

orthographicSize#

number

The camera's half-height, in metres.

pixelsPerUnit#

number

The pixels one metre spans.

Returns#

number

The Sprite2DView.zoom value; never zero, because Lite rejects a zero zoom.