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#
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#
Overrides#
Component.constructor
Properties#
allowMultiple#
staticallowMultiple: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#
staticschema:Schema
The declarative fields (ADR-0004).
typeId#
statictypeId: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()#
staticdefine<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#
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#
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#
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#
Inherited from#
Script.constructor
Properties#
allowMultiple#
staticallowMultiple:boolean=false
One follow per entity.
typeId#
statictypeId: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()#
staticdefine<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#
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#
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#
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#
Overrides#
Component.constructor
Properties#
allowMultiple#
staticallowMultiple: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#
staticschema:Schema
The declarative fields (ADR-0004).
sortingLayer#
sortingLayer:
string
Which sorting layer this component slows down.
typeId#
statictypeId: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()#
staticdefine<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#
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#
const layers = new SortingLayerTable(["Background", "Default", "Foreground"]);layers.indexOf("Foreground"); // 2Constructors#
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#
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#
const clips = await app.assets.load<SpriteAnimationAsset>("2d/hero.spriteanim.json").promise;clips.clipNames(); // ["idle", "run"]Properties#
address#
readonlyaddress:string
The address the document was loaded from.
assetType#
staticassetType:string=SPRITE_ANIMATION_ASSET_TYPE
The type name the asset service registers animation documents under.
atlasAddress#
readonlyatlasAddress:string
The atlas address the document names, already resolved against its own address.
definition#
readonlydefinition: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#
The atlas the frame names index into.
Returns#
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#
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#
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#
Overrides#
Component.constructor
Properties#
allowMultiple#
staticallowMultiple: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#
staticschema:Schema
The declarative fields (ADR-0004).
speed#
speed:
number
A multiplier on the clip's own frame rate.
typeId#
statictypeId: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()#
staticdefine<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#
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?#
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#
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#
const handle = app.assets.load<SpriteAtlasAsset>("2d/hero.atlas.json");const atlas = await handle.promise;atlas.frameIndex("idle_0"); // 0Properties#
address#
readonlyaddress:string
The address the atlas was loaded from.
assetType#
staticassetType:string=SPRITE_ATLAS_ASSET_TYPE
The type name the asset service registers sprite atlases under.
definition#
readonlydefinition: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#
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#
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#
Overrides#
Component.constructor
Properties#
allowMultiple#
staticallowMultiple: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#
staticschema: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#
readonlya:number
b#
readonlyb:number
g#
readonlyg:number
r#
readonlyr:number
typeId#
statictypeId: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()#
staticdefine<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#
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#
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#
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#
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#
Overrides#
Component.constructor
Properties#
allowMultiple#
staticallowMultiple: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#
staticschema: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#
statictypeId: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#
readonlymax:Vec2Like
min#
readonlymin: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#
readonlysprite: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()#
staticdefine<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#
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#
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 layerExtends#
Component
Implements#
ComponentHooks
Constructors#
Constructor#
new Tilemap():
Tilemap
Builds a tilemap with the schema's defaults.
Returns#
Overrides#
Component.constructor
Properties#
allowMultiple#
staticallowMultiple: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#
staticschema:Schema
The declarative fields (ADR-0004).
typeId#
statictypeId: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#
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#
The topmost non-empty collider, or a "none" shape.
define()#
staticdefine<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#
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#
const map = await app.assets.load<TilemapAsset>("2d/level-1.tilemap.json").promise;map.definition.layers.length; // 2Properties#
address#
readonlyaddress:string
The address the document was loaded from.
assetType#
staticassetType:string=TILEMAP_ASSET_TYPE
The type name the asset service registers tilemaps under.
atlasAddresses#
readonlyatlasAddresses: readonlystring[]
Each tileset's atlas address, resolved against this document's address.
definition#
readonlydefinition: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#
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#
Overrides#
Component.constructor
Properties#
allowMultiple#
staticallowMultiple: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#
staticschema:Schema
The declarative fields (ADR-0004).
sortingLayer#
sortingLayer:
string
Which sorting layer the tiles draw on, when the document's layers name none.
typeId#
statictypeId: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()#
staticdefine<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#
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#
Advances animated tiles on the same clock.
Returns#
Properties#
name#
readonlyname:"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#
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#
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#
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#
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#
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#
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#
readonlyname:"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?#
readonlyoptionalatlas?:string
The .atlas.json address the clips index into. Defaults to "", the renderer's own atlas.
defaultFps?#
readonlyoptionaldefaultFps?:number
The rate a tag gets when Aseprite recorded no usable frame durations. Defaults to 12.
frameNameOf?#
readonlyoptionalframeNameOf?: (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?#
readonlyoptionalimage?:string
The image address to write into the atlas. Defaults to the document's meta.image.
premultipliedAlpha?#
readonlyoptionalpremultipliedAlpha?:boolean
Whether the image's RGB is already multiplied by its alpha. Defaults to false.
sampling?#
readonlyoptionalsampling?:"linear"|"nearest"
The min/mag filter. Defaults to "linear"; pixel art wants "nearest".
CollisionMergeOptions#
The grid mergeTileCollisions walks.
Properties#
cellSize#
readonlycellSize:number
The edge length of one cell, in metres.
chunkSize#
readonlychunkSize:number
The edge length of one chunk, in cells; 32 is what TilemapRenderer uses.
height#
readonlyheight:number
The grid's height, in cells.
width#
readonlywidth:number
The grid's width, in cells.
GridAtlasImportOptions#
What gridAtlas needs to cut an evenly spaced sheet into frames.
Properties#
cellHeight#
readonlycellHeight:number
One cell's height, in pixels. Must be positive.
cellWidth#
readonlycellWidth:number
One cell's width, in pixels. Must be positive.
columns?#
readonlyoptionalcolumns?:number
How many columns to emit. Defaults to as many as the image holds; clamped to that.
image#
readonlyimage:string
The address of the image the frames are cut from.
imageHeight#
readonlyimageHeight:number
The image's full height, in pixels.
imageWidth#
readonlyimageWidth:number
The image's full width, in pixels.
margin?#
readonlyoptionalmargin?:number
The border left around the whole grid, in pixels. Defaults to 0.
namePrefix?#
readonlyoptionalnamePrefix?:string
The <prefix>_<index> frame names use. Defaults to "tile".
pivot?#
readonlyoptionalpivot?:Vec2Like
The pivot every frame gets, in [0, 1]. Defaults to the centre.
premultipliedAlpha?#
readonlyoptionalpremultipliedAlpha?:boolean
Whether the image's RGB is already multiplied by its alpha. Defaults to false.
rows?#
readonlyoptionalrows?:number
How many rows to emit. Defaults to as many as the image holds; clamped to that.
sampling?#
readonlyoptionalsampling?:"linear"|"nearest"
The min/mag filter. Defaults to "linear"; pixel art wants "nearest".
spacing?#
readonlyoptionalspacing?:number
The gap between adjacent cells, in pixels. Defaults to 0.
LdtkImportOptions#
How importLdtkLevel maps LDtk's conventions onto ignifx's.
Properties#
atlasFor?#
readonlyoptionalatlasFor?: (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?#
readonlyoptionalintGridColliders?:Readonly<Record<number,TileColliderDefinition>>
Replaces LDTK_DEFAULT_INTGRID_COLLIDERS for this import.
level?#
readonlyoptionallevel?:string
The identifier of the level to import. Defaults to the project's first level.
pixelsPerUnit?#
readonlyoptionalpixelsPerUnit?:number
The pixels one world metre spans. Defaults to 100, matching twoD.pixelsPerUnit.
sortingLayer?#
readonlyoptionalsortingLayer?:string
The sorting layer every layer lands in. Defaults to "Default".
PlayClipOptions#
What SpriteAnimator.play accepts.
Properties#
restart?#
readonlyoptionalrestart?:boolean
Whether to rewind a clip that is already playing. Defaults to false.
SpriteAnimationDefinition#
The parsed .spriteanim.json document.
Properties#
atlas#
readonlyatlas:string
The address of the .atlas.json the clips index into; empty uses the renderer's own atlas.
clips#
readonlyclips: readonlySpriteClipDefinition[]
The clips, in declaration order; the first is the default when the component names none.
format#
readonlyformat:"ignifx.spriteanimation"
Always "ignifx.spriteanimation".
formatVersion#
readonlyformatVersion:number
Always 1 in this build.
SpriteAnimationEvent#
A frame event: a name emitted on SpriteAnimator.onEvent when the clip reaches a frame.
Properties#
frame#
readonlyframe:number
The zero-based index within the clip, not within the atlas.
name#
readonlyname:string
The name emitted on SpriteAnimator.onEvent.
SpriteAnimationInput#
What defineSpriteAnimation accepts.
Properties#
atlas?#
readonlyoptionalatlas?:string
The address of the .atlas.json the clips index into.
clips#
readonlyclips: readonlySpriteClipDefinition[]
The clips.
format?#
readonlyoptionalformat?:string
Always "ignifx.spriteanimation" when present.
formatVersion?#
readonlyoptionalformatVersion?: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#
readonlyatlas:SpriteAtlasAsset
The atlas the frame lives in.
frame#
readonlyframe:number
The frame index.
name#
readonlyname:string
The frame's name.
SpriteAtlasAssetLiteHandles#
The Babylon Lite objects a SpriteAtlasAsset owns.
Properties#
atlas#
readonlyatlas:SpriteAtlas|null
The Lite atlas, or null under a headless app, which uploads nothing.
SpriteAtlasDefinition#
The parsed .atlas.json document.
Example#
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#
readonlyformat:"ignifx.spriteatlas"
Always "ignifx.spriteatlas".
formatVersion#
readonlyformatVersion:number
Always 1 in this build.
frames#
readonlyframes: readonlySpriteFrameDefinition[]
The frames, in the order they are indexed.
image#
readonlyimage:string
The address of the image the frames are cut from.
premultipliedAlpha#
readonlypremultipliedAlpha:boolean
Whether the image's RGB is already multiplied by its alpha. Defaults to false.
sampling#
readonlysampling:"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?#
readonlyoptionalformat?:string
Always "ignifx.spriteatlas" when present.
formatVersion?#
readonlyoptionalformatVersion?:number
The document version.
frames#
readonlyframes: readonlySpriteFrameDefinition[]
The frames.
image#
readonlyimage:string
The address of the image the frames are cut from.
premultipliedAlpha?#
readonlyoptionalpremultipliedAlpha?:boolean
Whether the image is premultiplied. Defaults to false.
sampling?#
readonlyoptionalsampling?:"linear"|"nearest"
The min/mag filter. Defaults to "linear".
SpriteClip#
One clip, resolved against an atlas.
Properties#
durationSeconds#
readonlydurationSeconds:number
How long one pass through the clip takes, in seconds.
events#
readonlyevents: readonlySpriteAnimationEvent[]
Events fired as the clip passes a frame.
fps#
readonlyfps:number
Frames per second.
frames#
readonlyframes: readonlynumber[]
The atlas frame indices, in play order.
loop#
readonlyloop:boolean
Whether the clip restarts at its end.
name#
readonlyname:string
The clip's name.
SpriteClipDefinition#
One clip: an ordered run of atlas frames with a rate and a loop flag.
Properties#
events?#
readonlyoptionalevents?: readonlySpriteAnimationEvent[]
Events fired as the clip passes a frame.
fps?#
readonlyoptionalfps?:number
Frames per second. Defaults to 12.
frames?#
readonlyoptionalframes?: readonlystring[]
The atlas frame names, in play order. Empty when from/to name a range instead.
from?#
readonlyoptionalfrom?:string
The first frame of a contiguous atlas range, when frames is absent.
loop?#
readonlyoptionalloop?:boolean
Whether the clip restarts at its end. Defaults to true.
name#
readonlyname:string
The clip's name, unique within the document; what SpriteAnimator.play takes.
to?#
readonlyoptionalto?:string
The last frame of a contiguous atlas range, inclusive.
SpriteFrameDefinition#
One frame rectangle, in image pixels with a top-left origin.
Properties#
h#
readonlyh:number
The height, in image pixels.
name#
readonlyname:string
The frame's name, unique within the document; what #frame: addresses.
pivot?#
readonlyoptionalpivot?: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?#
readonlyoptionalsourceSize?:Vec2Json
The untrimmed source size, when the packer trimmed transparent margins. Defaults to w/h.
w#
readonlyw:number
The width, in image pixels.
x#
readonlyx:number
The left edge, in image pixels.
y#
readonlyy:number
The top edge, in image pixels.
SpriteFrameInfo#
One frame of a loaded atlas, as game code sees it.
Properties#
heightPx#
readonlyheightPx:number
Its drawn height, in image pixels.
index#
readonlyindex:number
Its index in the atlas, which is what Lite addresses frames by.
name#
readonlyname:string
The frame's name.
pivot#
readonlypivot:Vec2Like
Its pivot in [0, 1] of the frame, [0, 0] top-left.
widthPx#
readonlywidthPx:number
Its drawn width, in image pixels.
SpriteLayerEntry#
One Lite layer and everything the registry tracks alongside it.
Properties#
count#
readonlycount:number
How many sprites the layer currently holds.
key#
readonlykey:string
The composite key, built by spriteLayerKey.
layer#
readonlylayer:Sprite2DLayer
The Lite layer.
screenSpace#
readonlyscreenSpace:boolean
Whether the layer keeps the identity view instead of following the Camera2D.
sortingLayer#
readonlysortingLayer:string
The sorting layer's name.
ySort#
readonlyySort: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#
readonlyatlas:SpriteAtlasAsset
The atlas every sprite in the layer draws from.
blend#
readonlyblend:"alpha"|"premultiplied"|"additive"|"multiply"|"opaque"
The blend mode.
screenSpace#
readonlyscreenSpace:boolean
Whether the layer keeps the identity view instead of following the Camera2D.
sortingLayer#
readonlysortingLayer:string
The sorting layer's name.
TexturePackerImportOptions#
What importTexturePackerAtlas accepts alongside the document.
Properties#
image?#
readonlyoptionalimage?:string
The image address to write into the atlas. Defaults to the document's meta.image.
keepExtensions?#
readonlyoptionalkeepExtensions?:boolean
Whether to keep the .png on frame names. Defaults to false, which strips it.
premultipliedAlpha?#
readonlyoptionalpremultipliedAlpha?:boolean
Whether the image's RGB is already multiplied by its alpha. Defaults to false.
sampling?#
readonlyoptionalsampling?:"linear"|"nearest"
The min/mag filter. Defaults to "linear".
TileAnimationFrame#
One frame of an animated tile.
Properties#
durationMs#
readonlydurationMs:number
How long the step lasts, in milliseconds.
frame#
readonlyframe:string
The atlas frame name drawn during this step.
TileChange#
One tile change, as Tilemap.onTileChanged reports it.
Properties#
current#
readonlycurrent:number
The tile id that is there now.
layer#
readonlylayer:number
The layer's index in the document.
previous#
readonlyprevious:number
The tile id that was there.
x#
readonlyx:number
The cell's column, with 0 at the left.
y#
readonlyy: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#
readonlyoneWay:boolean
Whether the tile is a one-way platform (solid only when crossed from above).
properties#
readonlyproperties:Readonly<Record<string,string|number|boolean>>
The tile's custom properties, carried through from the tileset or the importer.
shape#
readonlyshape: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?#
readonlyoptionalanimation?: readonlyTileAnimationFrame[]
The animation frames, when the tile animates. A single frame is treated as a static tile.
collider?#
readonlyoptionalcollider?:TileColliderDefinition
The collision footprint, in cell-normalised top-left-origin units. Absent means no collider.
frame#
readonlyframe:string
The atlas frame the tile draws, by name.
id#
readonlyid:number
The tile's index within its tileset, zero-based; the global id is tileset.firstId + id.
properties?#
readonlyoptionalproperties?: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?#
readonlyoptionalatlasFor?: (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?#
readonlyoptionalpixelsPerUnit?:number
The pixels one world metre spans. Defaults to 100, matching twoD.pixelsPerUnit.
sortingLayer?#
readonlyoptionalsortingLayer?: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#
readonlychunkX:number
The chunk's column index, in chunks.
chunkY#
readonlychunkY:number
The chunk's row index, in chunks.
oneWayEdges#
readonlyoneWayEdges: readonly readonly [Vec2Like,Vec2Like][]
The one-way platform edges, each a [from, to] pair with solid side to the left of from → to.
polygons#
readonlypolygons: readonly readonlyVec2Like[][]
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#
readonlycellSize:number
The edge length of one cell, in metres.
chunks#
readonlychunks: readonlyTilemapCollisionChunk[]
The chunks that carry at least one collider; empty chunks are omitted.
chunkSize#
readonlychunkSize:number
The edge length of one chunk, in cells.
version#
readonlyversion:number
Increments on every change to the merged geometry.
TilemapDefinition#
The parsed .tilemap.json document.
Example#
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 unitProperties#
cellSize#
readonlycellSize: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#
readonlyformat:"ignifx.tilemap"
Always "ignifx.tilemap".
formatVersion#
readonlyformatVersion:number
Always 1 in this build.
height#
readonlyheight:number
The map's height, in cells.
layers#
readonlylayers: readonlyTilemapLayerDefinition[]
The tile layers, back to front: index 0 draws behind index 1.
objects#
readonlyobjects: readonlyTilemapObjectDefinition[]
The objects gathered from every object layer, in document order.
properties#
readonlyproperties:Readonly<Record<string,string|number|boolean>>
The map's custom properties.
tileHeight#
readonlytileHeight:number
The height of one tile, in pixels.
tilesets#
readonlytilesets: readonlyTilesetDefinition[]
The tilesets, sorted by ascending TilesetDefinition.firstId.
tileWidth#
readonlytileWidth:number
The width of one tile, in pixels.
width#
readonlywidth:number
The map's width, in cells.
TilemapInput#
What defineTilemap accepts: the document with every defaulted field optional.
Properties#
cellSize?#
readonlyoptionalcellSize?:number
The metre size of one cell. Defaults to tileWidth / 100, the default pixels-per-unit.
format?#
readonlyoptionalformat?:string
Always "ignifx.tilemap" when present.
formatVersion?#
readonlyoptionalformatVersion?:number
The document version.
height#
readonlyheight:number
The map's height, in cells.
layers?#
readonlyoptionallayers?: readonlyTilemapLayerInput[]
The tile layers, back to front. Defaults to none.
objects?#
readonlyoptionalobjects?: readonlyTilemapObjectDefinition[]
The objects. Defaults to none.
properties?#
readonlyoptionalproperties?:Readonly<Record<string,string|number|boolean>>
The map's custom properties. Defaults to none.
tileHeight?#
readonlyoptionaltileHeight?:number
The height of one tile, in pixels. Defaults to tileWidth.
tilesets?#
readonlyoptionaltilesets?: readonlyTilesetDefinition[]
The tilesets. Defaults to none.
tileWidth#
readonlytileWidth:number
The width of one tile, in pixels.
width#
readonlywidth: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#
readonlycollision:boolean
Whether the layer contributes collision geometry.
height#
readonlyheight:number
The layer's height, in cells.
name#
readonlyname:string
The layer's name, unique within the document.
opacity#
readonlyopacity:number
The layer's opacity in [0, 1].
orderInLayer#
readonlyorderInLayer:number
The order within the sorting layer; higher draws in front.
parallax#
readonlyparallax:Vec2Like
The parallax multiplier; { x: 1, y: 1 } moves with the camera.
sortingLayer#
readonlysortingLayer:string
The sorting layer the tiles draw in (docs/architecture/11-2d-toolkit.md §1).
tiles#
readonlytiles: readonlynumber[]
width * height global tile ids, row-major, top row first.
width#
readonlywidth: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?#
readonlyoptionalcollision?:boolean
Whether the layer collides. Defaults to false.
height?#
readonlyoptionalheight?:number
The layer's height in cells. Defaults to the map's height.
name#
readonlyname:string
The layer's name, unique within the document.
opacity?#
readonlyoptionalopacity?:number
The opacity in [0, 1]. Defaults to 1.
orderInLayer?#
readonlyoptionalorderInLayer?:number
The order within the sorting layer. Defaults to 0.
parallax?#
readonlyoptionalparallax?:Vec2Like
The parallax multiplier. Defaults to { x: 1, y: 1 }.
sortingLayer?#
readonlyoptionalsortingLayer?:string
The sorting layer. Defaults to "Default".
tiles#
readonlytiles: readonlynumber[] |TileRleData
The tile ids, dense (row-major, top row first) or run-length encoded.
width?#
readonlyoptionalwidth?: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#
readonlyheight:number
The height, in world metres.
name#
readonlyname:string
The object's name, as authored; not required to be unique.
properties#
readonlyproperties:Readonly<Record<string,string|number|boolean>>
The object's custom properties.
type#
readonlytype:string
The object's type — what app.twoD.registerTileObjectFactory keys on.
width#
readonlywidth:number
The width, in world metres.
x#
readonlyx:number
The left edge, in world metres.
y#
readonlyy:number
The bottom edge, in world metres, +Y up.
TileObjectContext#
What a TileObjectFactory is handed.
Properties#
name#
readonlyname:string
The object's name, as the map wrote it.
position#
readonlyposition:Vec2Like
The object's bottom-left corner, in world metres relative to the tilemap entity.
properties#
readonlyproperties:Readonly<Record<string,string|number|boolean>>
The object's custom properties.
size#
readonlysize:Vec2Like
The object's size, in world metres.
tilemap#
readonlytilemap:Entity
The tilemap entity the object came from, so a factory can parent to it.
type#
readonlytype:string
The object's type, which selected this factory.
world#
readonlyworld: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#
readonlyrle: readonlynumber[]
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#
readonlyatlas:string
The address of the .atlas.json the frames come from; empty for a collision-only tileset.
firstId#
readonlyfirstId:number
The global id of this tileset's tile 0. Always at least 1, because 0 means empty.
name#
readonlyname:string
The tileset's name, unique within the document; also the frame-name prefix.
tiles#
readonlytiles: readonlyTileDefinition[]
The tiles, indexed by their local TileDefinition.id.
TwoDErrorOptions#
Options accepted by twoDError: the same subset of IgnifxErrorOptions this package uses.
Properties#
cause?#
readonlyoptionalcause?:unknown
The failure being wrapped, when there is one.
context?#
readonlyoptionalcontext?:Readonly<Record<string,string|number|boolean|null>>
Identifiers that locate the failure.
hint?#
readonlyoptionalhint?:string
One sentence telling the developer what to do about it.
TwoDLiteHandles#
The Babylon Lite objects app.twoD owns.
Properties#
renderer#
readonlyrenderer: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?#
readonlyoptionalmode?:"sprite"|"mixed"
Whether sprites are the whole frame ("sprite") or composite over the 3D scene ("mixed").
pixelsPerUnit?#
readonlyoptionalpixelsPerUnit?:number
How many pixels one world metre spans.
ySort?#
readonlyoptionalySort?:Readonly<Record<string,boolean>>
Which sorting layers draw back-to-front by world Y.
TwoDPick#
What app.twoD.pickAt returns.
Properties#
component#
readonlycomponent:SpriteRenderer
The sprite component that was hit.
entity#
readonlyentity:Entity
The entity carrying the sprite that was hit.
u#
readonlyu:number
Where inside the sprite's quad the hit landed, in [0, 1].
v#
readonlyv:number
Where inside the sprite's quad the hit landed, in [0, 1].
TwoDSettings#
The resolved twoD settings section.
Example#
// ignifx.config.tsexport default defineConfig({ sortingLayers: { sortingLayers: ["Background", "Default", "Foreground"] }, twoD: { mode: "sprite", pixelsPerUnit: 16, ySort: { Default: true } },});Properties#
mode#
readonlymode:"sprite"|"mixed"
Whether sprites are the whole frame ("sprite") or composite over the 3D scene ("mixed").
pixelsPerUnit#
readonlypixelsPerUnit:number
How many pixels one world metre spans. Defaults to 100.
ySort#
readonlyySort: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#
readonlymax:MutableVec2
The upper corner, in world metres.
min#
readonlymin: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: readonlyVec2Like[]; } | {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#
readonlyheight:number
The box's height, in cell-normalised units.
kind#
readonlykind:"box"
Discriminant: an axis-aligned box.
oneWay?#
readonlyoptionaloneWay?:boolean
Whether the tile is a one-way platform. Defaults to false.
width#
readonlywidth:number
The box's width, in cell-normalised units.
x#
readonlyx:number
The box's left edge, in cell-normalised units.
y#
readonlyy: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#
readonlykind:"polygon"
Discriminant: an outline.
oneWay?#
readonlyoptionaloneWay?:boolean
Whether the tile is a one-way platform. Defaults to false.
points#
readonlypoints: readonlyVec2Like[]
The vertices in cell-normalised units with a top-left origin, in the editor's winding.
Type Literal#
{ kind: "none"; }
kind#
readonlykind:"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: readonlyVec2Like[]; } | {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#
readonlyheight:number
The box's height, in metres.
kind#
readonlykind:"box"
Discriminant: an axis-aligned box.
width#
readonlywidth:number
The box's width, in metres.
x#
readonlyx:number
The box's left edge, in cell-local metres.
y#
readonlyy:number
The box's bottom edge, in cell-local metres.
Type Literal#
{ kind: "polygon"; points: readonly Vec2Like[]; }
kind#
readonlykind:"polygon"
Discriminant: a convex or concave outline.
points#
readonlypoints: readonlyVec2Like[]
The outline's vertices in cell-local metres, wound counter-clockwise.
Type Literal#
{ kind: "none"; }
kind#
readonlykind:"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#
Returns#
Entity | null
TwoDErrorCode#
TwoDErrorCode = typeof
TwoDErrorCode[keyof typeofTwoDErrorCode]
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#
constDEFAULT_CHUNK_SIZE:32=32
How many cells one chunk spans by default (docs/architecture/11-2d-toolkit.md §2.5).
DEFAULT_CLIP_FPS#
constDEFAULT_CLIP_FPS:12=12
The frames-per-second a clip that declares none plays at.
DEFAULT_ORTHOGRAPHIC_SIZE#
constDEFAULT_ORTHOGRAPHIC_SIZE:5=5
The half-height, in metres, a camera that declares none shows.
DEFAULT_PIXELS_PER_UNIT#
constDEFAULT_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#
constDEFAULT_REFERENCE_RESOLUTION:Vec2Like
The reference resolution a pixel-perfect camera fits an integer zoom to.
DEFAULT_SORTING_LAYER#
constDEFAULT_SORTING_LAYER:"Default"="Default"
The sorting layer a component that names none draws on.
EMPTY_TILE_ID#
constEMPTY_TILE_ID:0=0
The tile id that means "this cell is empty"; no tileset may claim it.
LDTK_DEFAULT_INTGRID_COLLIDERS#
constLDTK_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#
constLDTK_INTGRID_TILESET_NAME:"intgrid"="intgrid"
The name given to the synthetic tileset that carries IntGrid colliders.
SORTING_LAYER_ORDER_STEP#
constSORTING_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#
constSPRITE_ANIMATION_ASSET_TYPE:"spriteanimation"="spriteanimation"
The asset type name the loader registers.
SPRITE_ANIMATION_FILE_EXTENSIONS#
constSPRITE_ANIMATION_FILE_EXTENSIONS: readonlystring[]
The address suffixes that select the sprite-animation loader.
SPRITE_ANIMATION_FORMAT#
constSPRITE_ANIMATION_FORMAT:"ignifx.spriteanimation"="ignifx.spriteanimation"
The format discriminator every .spriteanim.json document carries.
SPRITE_ANIMATION_FORMAT_VERSION#
constSPRITE_ANIMATION_FORMAT_VERSION:1=1
The document version this build reads and writes.
SPRITE_ATLAS_ASSET_TYPE#
constSPRITE_ATLAS_ASSET_TYPE:"spriteatlas"="spriteatlas"
The asset type name the loader registers.
SPRITE_ATLAS_FILE_EXTENSIONS#
constSPRITE_ATLAS_FILE_EXTENSIONS: readonlystring[]
The address suffixes that select the sprite-atlas loader.
SPRITE_ATLAS_FORMAT#
constSPRITE_ATLAS_FORMAT:"ignifx.spriteatlas"="ignifx.spriteatlas"
The format discriminator every .atlas.json document carries.
SPRITE_ATLAS_FORMAT_VERSION#
constSPRITE_ATLAS_FORMAT_VERSION:1=1
The document version this build reads and writes.
SPRITE_BLEND_MODES#
constSPRITE_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#
constSPRITE_EFFECT_KINDS: readonly ["tint","custom"]
The built-in effects, in the order an inspector should list them.
SPRITE_FRAME_FRAGMENT_PREFIX#
constSPRITE_FRAME_FRAGMENT_PREFIX:"frame:"="frame:"
The fragment prefix that addresses one frame: "sprites/hero.atlas.json#frame:idle_0".
TILEMAP_ASSET_TYPE#
constTILEMAP_ASSET_TYPE:"tilemap"="tilemap"
The asset type name the loader registers.
TILEMAP_FILE_EXTENSIONS#
constTILEMAP_FILE_EXTENSIONS: readonlystring[]
The address suffixes that select the tilemap loader.
TILEMAP_FORMAT#
constTILEMAP_FORMAT:"ignifx.tilemap"="ignifx.tilemap"
The format discriminator every .tilemap.json document carries.
TILEMAP_FORMAT_VERSION#
constTILEMAP_FORMAT_VERSION:1=1
The document version this build reads and writes.
TINT_EFFECT_WGSL#
constTINT_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#
constTWO_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#
constTWO_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#
constTWO_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#
constTWO_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#
constTWO_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#
consttwoD: (options?) =>Extension
The @ignifx/2d extension factory.
Parameters#
options?#
Overrides for the twoD settings section.
Returns#
Extension
The extension descriptor to pass to createApp.
Example#
const app = await createApp({ canvas, extensions: [twoD({ pixelsPerUnit: 16, ySort: { Default: true } })],});TwoDErrorCode#
constTwoDErrorCode: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#
readonlyatlasFrameNotExtruded:"IGX-1102"="IGX-1102"
An atlas frame has no one-pixel extruded border, which a pixel-perfect camera will bleed.
duplicateExtension#
readonlyduplicateExtension:"IGX-1112"="IGX-1112"
A second twoD() extension was registered on one app.
duplicateObjectFactory#
readonlyduplicateObjectFactory:"IGX-1110"="IGX-1110"
app.twoD.registerTileObjectFactory was called twice for one object type.
invalidAnimationFile#
readonlyinvalidAnimationFile:"IGX-1104"="IGX-1104"
A .spriteanim.json file is not an ignifx.spriteanimation document this build can read.
invalidAtlasFile#
readonlyinvalidAtlasFile:"IGX-1103"="IGX-1103"
A .atlas.json file is not an ignifx.spriteatlas document this build can read.
invalidTilemapFile#
readonlyinvalidTilemapFile:"IGX-1105"="IGX-1105"
A .tilemap.json file is not an ignifx.tilemap document this build can read.
missingShaderSource#
readonlymissingShaderSource:"IGX-1113"="IGX-1113"
A SpriteLayerEffect declared the custom kind without a WGSL fragment body.
tileOutOfRange#
readonlytileOutOfRange:"IGX-1111"="IGX-1111"
A tile coordinate is outside the tilemap layer's bounds.
unknownClip#
readonlyunknownClip:"IGX-1108"="IGX-1108"
SpriteAnimator.play named a clip the animation asset does not declare.
unknownFrame#
readonlyunknownFrame:"IGX-1106"="IGX-1106"
A sprite address names a frame the atlas does not declare.
unknownSortingLayer#
readonlyunknownSortingLayer:"IGX-1107"="IGX-1107"
A component named a sorting layer the sortingLayers settings section does not declare.
unsupportedImport#
readonlyunsupportedImport:"IGX-1109"="IGX-1109"
A tilemap importer was handed a document it cannot read, or an unsupported projection.
Example#
throw twoDError(TwoDErrorCode.unknownSortingLayer, "Foreground is not a declared sorting layer.", { context: { sortingLayer: "Foreground" },});VERSION#
constVERSION:"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:
- Drop a trailing file extension — a dot, a letter, then up to seven more alphanumerics — so
hero 0.asepriteandhero_0.pngboth lose their suffix butwalk.2does not. - Replace every run of non-alphanumeric characters with a single
_. - 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#
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#
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#
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#
ctx.registerAssetLoader(createTilemapLoader());decodeTileRle()#
decodeTileRle(
rle): readonlynumber[]
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#
decodeTileRle([2, 1, 3, 0]); // [1, 1, 0, 0, 0]defaultTwoDSettings()#
defaultTwoDSettings():
TwoDSettings
The values used for everything a project omits.
Returns#
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#
The document, as authored or as an importer emitted it.
address?#
string = "<inline>"
What to name in an error; defaults to "<inline>".
Returns#
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#
The document, as authored or as an importer emitted it.
address?#
string = "<inline>"
What to name in an error; defaults to "<inline>".
Returns#
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#
The document, as authored or as an importer emitted it.
address?#
string = "<inline>"
What to name in an error; defaults to "\<inline\>".
Returns#
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#
describeTwoDSchemas()["ignifx/Camera2D"].fields["orthographicSize"].default; // 5encodeTileRle()#
encodeTileRle(
tiles): readonlynumber[]
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#
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#
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#
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#
The sheet's geometry and the frame naming.
Returns#
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#
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) listsfrom … toin order."reverse"lists them backwards."pingpong"lists them forwards and then appends the interior frames in reverse, so a three-frame tag becomes0, 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#
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#
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?#
The image override and sampling.
Returns#
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#
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#
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
layerInstancesfront-to-back — index0is the layer drawn on top. ignifx layers are back-to-front, so the list is reversed andorderInLayerfollows the reversed index. - Tile layers are sparse.
gridTilesis a list of{ px, t }placements, not a grid; the importer expands it into the dense__cWid * __cHeiarray the tilemap format wants, filling the gaps with0.tis a tile index within its tileset, so the global id istileset.firstId + t. A layer'spxOffsetX/pxOffsetYshift 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
intGridCsvbecomes a layer withcollision: truewhose 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#
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?#
The image override, name handling, and sampling.
Returns#
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#
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#
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#
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#
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#
isFullCellSolid({ shape: { kind: "box", x: 0, y: 0, width: 1, height: 1 }, oneWay: false, properties: {} }, 1);// truemergeTileCollisions()#
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#
The cell size, chunk size, and grid extent.
version#
number
The version stamp to carry into the result; callers increment it per rebuild.
Returns#
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#
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#
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): readonlynumber[]
Resolves a clip's frame names into atlas frame indices.
Parameters#
clip#
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#
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): readonlyEntity[]
Runs the registered factory for every object in one tilemap.
Parameters#
app#
App
The app.
service#
The 2D service holding the factory registry.
tilemap#
The tilemap whose objects layer to walk.
Returns#
readonly Entity[]
The entities that were created, in document order.
Example#
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#
The parsed document.
tileId#
number
The global tile id, 0 for an empty cell.
Returns#
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 authoredymeasures 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#
// 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#
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#
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#
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#
The code from the TwoDErrorCode table.
message#
string
The actionable development sentence.
options?#
Context identifiers, a remedy hint, and the wrapped cause.
Returns#
IgnifxError
The error to throw or to reject with.
Example#
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#
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.