Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Nightre/Rapid.js/llms.txt

Use this file to discover all available pages before exploring further.

MatrixStack is a high-performance hierarchical transform manager modelled after the Canvas 2D context’s save() / restore() API. It maintains both a local matrix (transforms applied at the current level) and a world matrix (the accumulated transform from all parent levels). MatrixStore is the underlying flat buffer that stores every 2D 3×3 matrix as a compact 6-element array [a, b, c, d, tx, ty] packed into a single Float32Array, maximising memory locality and minimising GC pressure. Access MatrixStack via rapid.matrixStack and MatrixStore via rapid.matrix.

MatrixStack

MatrixStack is accessed through rapid.matrixStack. It uses MatrixStore internally and exposes a save/restore interface familiar from Canvas 2D.
rapid.clear() calls matrixStack.reset() at the start of every frame. You should not need to call reset() directly in normal usage.

save()

save(): { world: number; local: number; step: number }
Pushes the current world matrix onto the stack and allocates a new local/world matrix pair for the next level in the hierarchy. Equivalent to CanvasRenderingContext2D.save().
return.world
number
Index of the newly allocated world matrix in MatrixStore.
return.local
number
Index of the newly allocated local matrix in MatrixStore.
return.step
number
The current step counter, usable with updateMatrix().
rapid.matrixStack.save();
rapid.matrixStack.translate(100, 100);
rapid.drawSprite({ texture: childTex });
rapid.matrixStack.restore();

restore()

restore(): void
Pops the most recently saved matrix state, reverting curWorldM and curLocalM to their pre-save() values. Equivalent to CanvasRenderingContext2D.restore(). Silently no-ops if the stack is empty.

translate(x, y)

translate(x: number, y: number): void
Applies a translation to both the local and world matrices.
x
number
required
Translation along the X axis in logical pixels.
y
number
required
Translation along the Y axis in logical pixels.
rapid.matrixStack.save();
rapid.matrixStack.translate(250, 150);
rapid.drawRect({ width: 100, height: 60, color: Color.Red });
rapid.matrixStack.restore();

scale(scaleX, scaleY?)

scale(scaleX: number, scaleY?: number): void
Applies a scale to both the local and world matrices.
scaleX
number
required
Scale factor along the X axis.
scaleY
number
Scale factor along the Y axis. Defaults to scaleX for uniform scaling.
rapid.matrixStack.save();
rapid.matrixStack.scale(2);           // uniform 2×
rapid.matrixStack.scale(1.5, 0.5);   // non-uniform
rapid.matrixStack.restore();

rotate(radians)

rotate(radians: number): void
Applies a rotation (in radians, clockwise in screen space) to both the local and world matrices.
radians
number
required
Rotation angle in radians.
rapid.matrixStack.save();
rapid.matrixStack.rotate(Math.PI / 4); // 45°
rapid.drawSprite({ texture: arrowTex });
rapid.matrixStack.restore();

rotateWithOffset(radians, offsetX, offsetY)

rotateWithOffset(radians: number, offsetX: number, offsetY: number): void
Rotates around a pivot point offset from the current origin, without requiring manual translate → rotate → translate-back calls. Internally performs: translate by (offsetX, offsetY), rotate by radians, translate by (-offsetX, -offsetY).
radians
number
required
Rotation angle in radians.
offsetX
number
required
X component of the pivot in local space.
offsetY
number
required
Y component of the pivot in local space.
// Rotate a 64×64 sprite around its centre
rapid.matrixStack.save();
rapid.matrixStack.rotateWithOffset(angle, 32, 32);
rapid.drawSprite({ texture: spriteTex });
rapid.matrixStack.restore();

identity()

identity(): void
Resets both the local and world matrices to the identity matrix, removing any accumulated transforms at the current stack level without disturbing the stack itself.
rapid.matrixStack.save();
rapid.matrixStack.translate(500, 500);
rapid.matrixStack.identity(); // undo the translate
rapid.drawSprite({ texture: tex }); // drawn at (0, 0)
rapid.matrixStack.restore();

reset()

reset(): void
Clears the entire stack — matrices, step counters, and action records — and re-initialises the root local/world matrix pair to identity. Called automatically by rapid.clear() every frame.

applyTransform(transform, width?, height?)

applyTransform(transform: ITransformOptions, width?: number, height?: number): void
Applies a complete ITransformOptions object to the stack. If transform.saveTransform is true (the default), save() is called first. Handles x/y, position, rotation, scale, offsetX/offsetY, offset, and origin in the correct order.
transform
ITransformOptions
required
The transform descriptor. See ITransformOptions for all fields.
width
number
Logical width used to resolve origin anchor percentages. Default 0.
height
number
Logical height used to resolve origin anchor percentages. Default 0.
rapid.matrixStack.applyTransform(
  { x: 200, y: 100, rotation: Math.PI / 6, origin: 0.5 },
  texture.width,
  texture.height,
);
rapid.drawSprite({ texture, saveTransform: false });
rapid.matrixStack.restore();

updateMatrix(step)

updateMatrix(step: number | { step: number }): void
Recalculates all world matrices from the given step downward in the recorded hierarchy. Use this in retained/deferred scene graph scenarios where you mutate a node’s local matrix after the initial traversal and need to propagate the change to descendants without re-running the full traversal.
step
number | { step: number }
required
The step index returned by save(), or an object with a step property.
const nodeState = rapid.matrixStack.save();
rapid.matrixStack.translate(nodeX, nodeY);
// ... build children

// Later, update the node position without full re-traversal:
rapid.matrixStack.translate(newX - nodeX, newY - nodeY);
rapid.matrixStack.updateMatrix(nodeState);

localToWorld(x, y)

localToWorld(x: number, y: number): { x: number; y: number }
Transforms a point from the current local space to world (screen) space using the current world matrix.
return
{ x: number; y: number }
World-space coordinates.
const worldPos = rapid.matrixStack.localToWorld(0, 0);
console.log("Object is at world position:", worldPos);

worldToLocal(x, y)

worldToLocal(x: number, y: number): { x: number; y: number }
Transforms a point from world (screen) space to the current local space using the inverse of the current world matrix. Useful for hit-testing pointer input against transformed objects.
return
{ x: number; y: number }
Local-space coordinates.
const localMouse = rapid.matrixStack.worldToLocal(mouseX, mouseY);
if (localMouse.x >= 0 && localMouse.x <= sprite.width &&
    localMouse.y >= 0 && localMouse.y <= sprite.height) {
  // pointer is inside the sprite
}

getGlobalPosition()

getGlobalPosition(): { x: number; y: number }
Returns the world-space translation (tx, ty) extracted directly from the current world matrix — the position the origin would appear at on screen.
return
{ x: number; y: number }
World-space position.

getGlobalScale()

getGlobalScale(): { x: number; y: number }
Extracts the accumulated scale from the current world matrix by computing the length of each basis vector.
return
{ x: number; y: number }
World-space scale factors.

getGlobalRotation()

getGlobalRotation(): number
Extracts the accumulated rotation (in radians) from the current world matrix using Math.atan2.
return
number
World-space rotation in radians.

getTransform()

getTransform(): Float32Array
Returns a copy of the current world matrix as a 6-element Float32Array [a, b, c, d, tx, ty].
return
Float32Array
6-element 2D transform array.

setTransform(f)

setTransform(f: Float32Array): void
Directly overwrites the current world matrix with the provided 6-element array. Use this to restore a previously captured transform or to apply an externally computed matrix.
f
Float32Array
required
A 6-element [a, b, c, d, tx, ty] transform array.
const saved = rapid.matrixStack.getTransform();
// ... other transforms ...
rapid.matrixStack.setTransform(saved); // restore

toCSSMatrix()

toCSSMatrix(): string
Returns a CSS matrix() string representing the current world matrix, suitable for use in element.style.transform.
return
string
CSS matrix(a, b, c, d, tx, ty) string.
uiElement.style.transform = rapid.matrixStack.toCSSMatrix();

MatrixStore

MatrixStore is accessed via rapid.matrix. It is a low-level flat-array container — each matrix is stored as 6 consecutive Float32Array elements [a, b, c, d, tx, ty] representing the upper 2×3 portion of a homogeneous 3×3 matrix. Matrices are referenced by an integer index returned at allocation time.
Most users interact with MatrixStack rather than MatrixStore directly. Use MatrixStore when you need to maintain transform trees outside the main frame traversal, or when building custom scene-graph tooling.

alloc()

alloc(): number
Allocates a new matrix, initialises it to identity, and returns its index.
return
number
Index of the new identity matrix.

allocDirty()

allocDirty(): number
Allocates a new matrix slot without initialising its elements. Faster than alloc() when you intend to overwrite all six values immediately (e.g. via copy).
return
number
Index of the new uninitialized matrix.

identity(index)

identity(index: number): void
Sets the matrix at index to the 2D identity transform [1, 0, 0, 1, 0, 0].

reset()

reset(): void
Deallocates all matrices, resetting the store to zero-count. Called by MatrixStack.reset() every frame.

translate(index, x, y)

translate(index: number, x: number, y: number): void
Post-multiplies a translation by (x, y) into the matrix at index.

scale(index, scaleX, scaleY)

scale(index: number, scaleX: number, scaleY: number): void
Post-multiplies a scale by (sx, sy) into the matrix at index.

rotate(index, radians)

rotate(index: number, radians: number): void
Post-multiplies a rotation by radians into the matrix at index.

rotateWithOffset(index, radians, offsetX, offsetY)

rotateWithOffset(index: number, radians: number, offsetX: number, offsetY: number): void
Rotates the matrix at index around a local pivot (offsetX, offsetY) — equivalent to translate → rotate → translate-back.
// Rotate a 128×128 sprite around its centre
rapid.matrix.rotateWithOffset(matIdx, angle, 64, 64);

copy(dst, src)

copy(dst: number, src: number): void
Copies all six elements from the matrix at src into the matrix at dst.

multiply(dst, src)

multiply(dst: number, src: number): void
Multiplies the matrix at dst by the matrix at src, storing the result back in dst. Equivalent to multiplyOut(dst, dst, src).

multiplyOut(out, aIdx, bIdx)

multiplyOut(out: number, aIdx: number, bIdx: number): void
Multiplies matrix aIdx by matrix bIdx and stores the result in out. out may safely alias aIdx or bIdx.

invert(index)

invert(index: number): void
Inverts the matrix at index in-place. If the matrix is singular (non-invertible), falls back to identity.
const camIdx = rapid.matrix.alloc();
rapid.matrix.copy(camIdx, rapid.matrixStack.curWorldM);
rapid.matrix.invert(camIdx); // now camIdx is the inverse camera transform

transformPoint(index, x, y)

transformPoint(index: number, x: number, y: number): { x: number; y: number }
Transforms the point (x, y) by the matrix at index and returns the result.
return
{ x: number; y: number }
Transformed point.

worldToLocal(index, x, y)

worldToLocal(index: number, x: number, y: number): { x: number; y: number }
Inverts the matrix at index (into a temporary slot) and transforms (x, y) through it, converting a world-space point to the local space of index. The temporary matrix is immediately freed.
return
{ x: number; y: number }
Point in local space.

localToWorld(index, x, y)

localToWorld(index: number, x: number, y: number): { x: number; y: number }
Transforms (x, y) from the local space of index to world space — equivalent to transformPoint.
return
{ x: number; y: number }
Point in world space.

getPosition(index)

getPosition(index: number): { x: number; y: number }
Extracts the translation (tx, ty) from the matrix at index.
return
{ x: number; y: number }
Translation component.

getScale(index)

getScale(index: number): { x: number; y: number }
Computes the scale by measuring the length of the two basis vectors of the matrix at index.
return
{ x: number; y: number }
Scale factors { x, y }.

getRotation(index)

getRotation(index: number): number
Extracts the rotation in radians from the matrix at index using Math.atan2(b, a).
return
number
Rotation in radians.

toCSSMatrix(index)

toCSSMatrix(index: number): string
Returns a CSS matrix() string for the matrix at index.
return
string
CSS matrix(a, b, c, d, tx, ty) string.
const idx = rapid.matrix.alloc();
rapid.matrix.translate(idx, 100, 200);
rapid.matrix.rotate(idx, 0.5);
console.log(rapid.matrix.toCSSMatrix(idx));
// → "matrix(0.877, 0.479, -0.479, 0.877, 100, 200)"

ITransformOptions Interface

ITransformOptions is accepted by every draw method and by MatrixStack.applyTransform(). Properties are applied in this order: x/ypositionrotationscaleoffsetX/offsetY/offsetorigin.
saveTransform
boolean
When true (default), save() is called before applying any transforms and the caller is responsible for calling restore() (or using withTransform). Set to false to mutate the current matrix in-place without pushing a new stack frame.
afterSave
() => void
Optional callback executed immediately after the save() call (if any), before transforms are applied. Useful for inserting additional state setup.
x
number
Translation along the X axis in logical pixels.
y
number
Translation along the Y axis in logical pixels.
position
Vec2
Translation as a Vec2. Applied after x/y. Both may be used simultaneously — they are additive.
rotation
number
Rotation in radians, applied after position.
scale
number | Vec2
Uniform scale when a number; per-axis scale when a Vec2. Applied after rotation.
offsetX
number
Additional X translation applied after scale, in the already-scaled local space. Useful for moving the draw origin without affecting rotation pivot.
offsetY
number
Additional Y translation applied after scale.
offset
Vec2
Additional translation as a Vec2, summed with offsetX/offsetY.
origin
number | Vec2
Normalised pivot point in 0–1 range relative to the sprite’s width / height. 0.5 centres the pivot. A Vec2 sets X and Y independently. The calculated pixel offset is subtracted from offsetX/offsetY.For example, origin: 0.5 on a 64×64 sprite shifts the draw origin by (-32, -32), so the sprite rotates around its centre.
Example — all options together
rapid.drawSprite({
  texture: shipTexture,
  x: 400,
  y: 300,
  rotation: heading,
  scale: new Vec2(2, 2),
  origin: 0.5,           // pivot at sprite centre
  offsetX: 0,
  offsetY: -engineOffsetY, // thruster flame offset
});
When you pass ITransformOptions fields directly to a draw method (e.g. drawSprite), Rapid skips the save/restore overhead entirely if none of the transform fields are present, making no-op paths essentially free.

Build docs developers (and LLMs) love