Math
Back to the reference

Math

Angles, interpolation, quaternions and seeded randomness.

39 symbols

clampfunctionnacatamalon

clamp(value: number, min: number, max: number) => number

Keeps value between min and max: below min it gives min, above max it gives max, and in between the value itself. It is what keeps a player inside the screen or a volume between 0 and 1, and it replaces Math.min(max, Math.max(min, value)), which is easy to write with the two the wrong way round.

Parameters

valuenumber

The number to keep in range.

minnumber

The lowest it may be.

maxnumber

The highest it may be.

Example

useUpdate((delta) => {
    hero.transform.x = clamp(hero.transform.x + speed * delta, 8, 312);
});
View source · math/clamp.ts:23

degToRadfunctionnacatamalon

degToRad(deg: number) => number

Converts deg (degrees) to radians: the unit every rotation in the engine uses (sprite transform.rotation, a camera's rotation, a 3D object's rotationX and rotationY). Lets you author angles the way you think about them: transform.rotation = degToRad(45).

Parameters

degnumber

The angle in degrees.

View source · math/angle/deg_to_rad.ts:15

lerpfunctionnacatamalon

lerp(a: number, b: number, t: number) => number

Linear interpolation between numbers a and b: t = 0 returns a, t = 1 returns b. Not clamped. The scalar building block under fades, manual tweens, and lerpColor / vec2Lerp. GLSL calls this mix.

Parameters

anumber

Where it starts.

bnumber

Where it ends.

tnumber

How far along, 0 to 1.

View source · math/lerp.ts:15

lerpAnglefunctionnacatamalon

lerpAngle(a: number, b: number, t: number) => number

Interpolates from angle a toward b (both radians) along the shortest arc, so going from 350° to 10° turns 20° forward instead of 340° back. Ideal for smoothly steering a sprite toward a target heading. t=0 returns a, t=1 returns an angle equivalent to b. Not clamped.

Parameters

anumber

The angle it starts at, in radians.

bnumber

The angle it turns towards, in radians.

tnumber

How far along, 0 to 1.

View source · math/angle/lerp_angle.ts:18

quatFromAxisAnglefunctionnacatamalon

quatFromAxisAngle(ax: number, ay: number, az: number, angle: number) => TQuat

Builds a quaternion that rotates by angle radians about the axis (ax, ay, az). The natural way to author "spin this much around this direction": a barrel roll is a rotation about the ship's forward axis, a turn is one about its up axis.

Parameters

axnumber

The axis to turn about. Any length.

aynumber

The axis to turn about.

aznumber

The axis to turn about.

anglenumber

Rotation about the axis, in radians.

View source · math/quat/index.ts:70

quatFromEulerfunctionnacatamalon

quatFromEuler(x: number, y: number, z: number) => TQuat

Builds a quaternion from yaw/pitch/roll Euler angles (radians), using the exact same axis order the renderer applies to Euler transforms: yaw (Y), then pitch (X), then roll (Z). That equivalence is the point: a mesh authored with rotation/rotationX/rotationY can be switched to a quaternion built here and face the identical direction, so you only pay the Euler→quat conversion once, up front, and evolve the quaternion from then on.

Parameters

xnumber

Pitch, rotation about X, in radians.

ynumber

Yaw, rotation about Y, in radians.

znumber

Roll, rotation about Z, in radians.

View source · math/quat/index.ts:53

quatMultiplyfunctionnacatamalon

quatMultiply(a: TQuat, b: TQuat) => TQuat

Composes two rotations: the result applies b first, then a (same convention as matrix multiplication). This is how you accumulate orientation incrementally: orientation = multiply(deltaSpin, orientation) each frame rolls a ship a little further without ever touching Euler angles or risking gimbal lock.

Parameters

aTQuat

The second turn.

bTQuat

The first turn.

View source · math/quat/index.ts:86

quatNormalizefunctionnacatamalon

quatNormalize(q: TQuat) => TQuat

Re-normalizes a quaternion back onto the unit sphere. Repeated multiplications accumulate floating-point error that slowly scales the rotation; call this periodically on a long-lived accumulated orientation to keep it a pure rotation.

Parameters

qTQuat

A quaternion.

View source · math/quat/index.ts:112

quatRotateVec3functionnacatamalon

quatRotateVec3(q: TQuat, v: { x, y, z }) => { x, y, z }

Rotates a vector by a quaternion: q · v · q⁻¹, in its expanded (branch-free) form.

The scene graph's composition is expressed in position/rotation/scale rather than in matrices (see composeWorldTransforms), and this is the one operation that needs: a child's local offset, turned by its parent's orientation, is where the child actually sits.

Parameters

qTQuat

The turn.

v{ x, y, z }

The vector to turn.

View source · math/quat/index.ts:157

radToDegfunctionnacatamalon

radToDeg(rad: number) => number

Converts rad (radians) to degrees: handy for showing an engine angle in a debug overlay or editor field, where degrees read more naturally than radians.

Parameters

radnumber

The angle in radians.

View source · math/angle/rad_to_deg.ts:14

TAUvariablenacatamalon

TAU: number

A full turn in radians (2π): the period of the trig functions. Useful for expressing whole rotations and for wrapping angles back into range.

View source · math/angle/constants.ts:9

useRandomfunctionhooknacatamalon

useRandom() => TRandomHandle

The random numbers of this game.

Use it instead of Math.random() whenever a result should be repeatable: give createGame a seed and every run of the game draws exactly the same numbers in the same order, which is what makes a level layout, a replay or a bug report reproducible. Without a seed each run is different.

seed(n) starts the sequence again from n at any moment.

Example

export const Level: TSceneFn = () => {
    const random = useRandom();

    for (let i = 0; i < 20; i++) {
        createSprite({ key: 'tree', transform: { x: random.rand(0, 480), y: random.rand(0, 320) } });
    }

    return createScene();
};
View source · hooks/random/use_random.ts:32

vec2Anglefunctionnacatamalon

vec2Angle(a: TVec2) => number

The angle a direction points at, in radians: 0 is right and it turns towards +y, which is down on screen. It is what a sprite's transform.rotation wants, so ship.transform.rotation = vec2Angle(velocity) turns a ship to face where it is going.

Parameters

aTVec2

The direction.

View source · math/vec2/angle.ts:15

vec2Equalsfunctionnacatamalon

vec2Equals(a: TVec2, b: TVec2) => boolean

Whether every component is exactly equal. Exact, so two results of arithmetic that should agree can differ in the last decimal: compare a distance with a small number for those.

Parameters

aTVec2

The first vector.

bTVec2

The second vector.

View source · math/vec2/equals.ts:15

vec3Equalsfunctionnacatamalon

vec3Equals(a: TVec3, b: TVec3) => boolean

Whether every component is exactly equal. Exact, so two results of arithmetic that should agree can differ in the last decimal: compare a distance with a small number for those.

Parameters

aTVec3

The first vector.

bTVec3

The second vector.

View source · math/vec3/equals.ts:15

wrapAnglefunctionnacatamalon

wrapAngle(rad: number) => number

Wraps rad into the range [-π, π). Rotations accumulated frame by frame (transform.rotation += spin * dt) drift far outside that range over time; wrapping keeps angle comparisons and interpolation well-behaved: call it before lerpAngle, or whenever you need a canonical heading.

Parameters

radnumber

The angle in radians, however many turns it has added up.

View source · math/angle/wrap.ts:16

TQuattypenacatamalon

TQuat: [number, number, number, number]

A unit quaternion [x, y, z, w]: the engine's storage form for a full 3D orientation. Chosen over Euler angles for anything that rotates freely in 3D (a flying ship, a physics body): it never gimbal-locks, composes with a single multiply, and interpolates smoothly with slerp. It is a plain number tuple on purpose: four JSON-serializable numbers, so a TransformRecord.quaternion round- trips through the editor/save with no special casing (a Float32Array would stringify as {"0":...}, not an array). The matrix is only ever the derived render form (toMat4); the quaternion is the state you keep and evolve.

View source · math/quat/index.ts:18

TRandomHandletypenacatamalon

A per-game random handle, returned by useRandom. Every method draws from this game's own seeded generator: two games on the same page never share a stream, and seed only affects the game it belongs to. Seeding makes a sequence reproducible (same seed → same numbers), which is what the editor/metadata model needs to rebuild a procedural scene from a single saved seed.

Properties

rand
randInt
chance
choose
shuffle
seed
View source · math/random/create_random.ts:12

TVec2typenacatamalon

A point or a direction in 2D: x, y.

Every vec2* function takes anything with those fields, so a transform works as it is: vec2Distance(player.transform, coin.transform) needs no vector built first. They never change what they are given: a vector that comes back is always a new object.

Properties

xnumber
ynumber
View source · math/vec2/index.ts:12

TVec3typenacatamalon

A point or a direction in 3D: x, y, z.

Every vec3* function takes anything with those fields, so a 3D transform works as it is: vec3Distance(player.transform, coin.transform) needs no vector built first. They never change what they are given: a vector that comes back is always a new object.

Properties

xnumber
ynumber
znumber
View source · math/vec3/index.ts:12