On this page
  1. tecs.math.vec2
  2. Coordinates and boundaries
  3. Module contents
    1. Functions
  4. Functions
    1. add
    2. angle
    3. angleBetween
    4. cross
    5. distance
    6. distanceSquared
    7. dot
    8. length
    9. lengthSquared
    10. lerp
    11. moveTowards
    12. normalize
    13. project
    14. reflect
    15. rotate
    16. scale
    17. signedAngleBetween
    18. subtract

tecs.math.vec2

Allocation-free two-dimensional vector and point math.

vec2 takes separate coordinates and returns multiple values, so a system can update an archetype column without allocating vector objects:

local record Homing is tecs.ecs.Component
    targetX: number
    targetY: number
    speed: number
end

tecs.ecs.newFFIComponent({
    name = "Homing",
    container = Homing,
    fields = {
        {"targetX", "float"},
        {"targetY", "float"},
        {"speed", "float"},
    },
})

return tecs.newApplication({
    plugin = function(world: tecs.World)
        local homing <const> = world:newQuery({
            include = {tecs.Transform2D, Homing},
        })

        world:addSystem({
            name = "game.Homing",
            phase = tecs.ecs.phases.Update,
            run = function(dt: number)
                for archetype, length in homing:iter() do
                    local transforms <const> = archetype:getMut(
                        tecs.Transform2D
                    )
                    local targets <const> = archetype:get(Homing)

                    for row = 1, length do
                        local transform <const> = transforms[row]
                        local target <const> = targets[row]

                        transform.x, transform.y = tecs.math.vec2.moveTowards(
                            transform.x,
                            transform.y,
                            target.targetX,
                            target.targetY,
                            target.speed * dt
                        )
                        transform.rotation = tecs.math.vec2.angle(
                            target.targetX - transform.x,
                            target.targetY - transform.y
                        )
                    end
                end
            end,
        })
    end,
})

The writable Transform2D column comes from getMut; the read-only target column comes from get. Taking both through getMut would dirty Homing every frame and defeat consumers that skip clean columns.

Coordinates and boundaries

Every angle uses radians. A positive quarter turn maps (1, 0) to (0, 1), which appears clockwise when screen y grows downward.

Operations without a unique geometric answer return stable values. normalize(0, 0), either angle-between function with a zero vector, and project onto a zero axis return zero. reflect with a zero normal returns the original vector. lerp does not clamp, and moveTowards never overshoots.

Module contents

Functions

Function Kind Description
add Static Adds two vectors.
angle Static Computes a vector's direction.
angleBetween Static Computes the smaller unsigned angle between two vectors.
cross Static Computes the scalar two-dimensional cross product.
distance Static Computes the distance between two points.
distanceSquared Static Computes squared distance without taking a square root.
dot Static Computes the dot product of two vectors.
length Static Computes vector length.
lengthSquared Static Computes squared vector length without taking a square root.
lerp Static Interpolates linearly between two points.
moveTowards Static Moves a point toward another by at most a given distance.
normalize Static Produces a unit vector in the same direction.
project Static Projects a vector onto another vector.
reflect Static Reflects a vector across the line perpendicular to a normal.
rotate Static Rotates a vector around the origin.
scale Static Multiplies both coordinates by a scalar.
signedAngleBetween Static Computes the smaller signed angle from one vector to another.
subtract Static Subtracts the second vector from the first.

Functions

tecs.math.vec2.add Static

Adds two vectors.

function tecs.math.vec2.add(
    ax: number, ay: number, bx: number, by: number
): number, number

Arguments

Name Type Description
ax number First vector's x coordinate.
ay number First vector's y coordinate.
bx number Second vector's x coordinate.
by number Second vector's y coordinate.

Returns

Type Description
number The sum's x coordinate.
number The sum's y coordinate.

Examples

Combines a position with a per-frame velocity step.

local x, y = tecs.math.vec2.add(1, 2, 3, 4)

assert(x == 4 and y == 6)

tecs.math.vec2.angle Static

Computes a vector's direction.

function tecs.math.vec2.angle(x: number, y: number): number

Arguments

Name Type Description
x number Vector's x coordinate.
y number Vector's y coordinate.

Returns

Type Description
number atan2(y, x) in [-pi, pi]. A zero vector returns zero.

Examples

Converts a direction into a rotation for a sprite.

assert(tecs.math.vec2.angle(0, 1) == math.pi / 2)

tecs.math.vec2.angleBetween Static

Computes the smaller unsigned angle between two vectors.

function tecs.math.vec2.angleBetween(
    ax: number, ay: number, bx: number, by: number
): number

Arguments

Name Type Description
ax number First vector's x coordinate.
ay number First vector's y coordinate.
bx number Second vector's x coordinate.
by number Second vector's y coordinate.

Returns

Type Description
number Radians in [0, pi]. If either vector is zero, returns zero.

Examples

Measures the unsigned separation of two facing directions.

assert(tecs.math.vec2.angleBetween(1, 0, 0, 1) == math.pi / 2)

tecs.math.vec2.cross Static

Computes the scalar two-dimensional cross product.

function tecs.math.vec2.cross(
    ax: number, ay: number, bx: number, by: number
): number

Arguments

Name Type Description
ax number First vector's x coordinate.
ay number First vector's y coordinate.
bx number Second vector's x coordinate.
by number Second vector's y coordinate.

Returns

Type Description
number ax * by - ay * bx; positive puts the second vector on the positive rotation side of the first.

Examples

Determines which side of a direction another vector lies on.

assert(tecs.math.vec2.cross(1, 0, 0, 1) == 1)

tecs.math.vec2.distance Static

Computes the distance between two points.

function tecs.math.vec2.distance(
    ax: number, ay: number, bx: number, by: number
): number

Arguments

Name Type Description
ax number First point's x coordinate.
ay number First point's y coordinate.
bx number Second point's x coordinate.
by number Second point's y coordinate.

Returns

Type Description
number The nonnegative Euclidean distance between the points.

Examples

Measures how far apart two positions are.

assert(tecs.math.vec2.distance(1, 2, 4, 6) == 5)

tecs.math.vec2.distanceSquared Static

Computes squared distance without taking a square root.

Prefer this to distance for radius tests.

function tecs.math.vec2.distanceSquared(
    ax: number, ay: number, bx: number, by: number
): number

Arguments

Name Type Description
ax number First point's x coordinate.
ay number First point's y coordinate.
bx number Second point's x coordinate.
by number Second point's y coordinate.

Returns

Type Description
number The squared Euclidean distance between the points.

Examples

Tests whether a target lies inside a radius without a square root.

assert(tecs.math.vec2.distanceSquared(1, 2, 4, 6) == 25)

tecs.math.vec2.dot Static

Computes the dot product of two vectors.

function tecs.math.vec2.dot(
    ax: number, ay: number, bx: number, by: number
): number

Arguments

Name Type Description
ax number First vector's x coordinate.
ay number First vector's y coordinate.
bx number Second vector's x coordinate.
by number Second vector's y coordinate.

Returns

Type Description
number ax * bx + ay * by.

Examples

Tests how closely two directions face each other.

assert(tecs.math.vec2.dot(2, 3, 4, 5) == 23)

tecs.math.vec2.length Static

Computes vector length.

function tecs.math.vec2.length(x: number, y: number): number

Arguments

Name Type Description
x number Vector's x coordinate.
y number Vector's y coordinate.

Returns

Type Description
number The nonnegative Euclidean length.

Examples

Measures a velocity's speed.

assert(tecs.math.vec2.length(3, 4) == 5)

tecs.math.vec2.lengthSquared Static

Computes squared vector length without taking a square root.

Prefer this to length when comparing magnitudes: compare the answer with the other distance squared, such as radius * radius.

function tecs.math.vec2.lengthSquared(x: number, y: number): number

Arguments

Name Type Description
x number Vector's x coordinate.
y number Vector's y coordinate.

Returns

Type Description
number x * x + y * y.

Examples

Compares speed without taking a square root.

assert(tecs.math.vec2.lengthSquared(3, 4) == 25)

tecs.math.vec2.lerp Static

Interpolates linearly between two points.

function tecs.math.vec2.lerp(
    ax: number, ay: number, bx: number, by: number, t: number
): number, number

Arguments

Name Type Description
ax number Starting point's x coordinate.
ay number Starting point's y coordinate.
bx number Destination point's x coordinate.
by number Destination point's y coordinate.
t number Unclamped interpolation amount. Zero returns the start, one returns the destination, and values outside that interval extrapolate.

Returns

Type Description
number The interpolated x coordinate.
number The interpolated y coordinate.

Examples

Blends halfway between two positions.

local x, y = tecs.math.vec2.lerp(2, 4, 6, 8, 0.5)

assert(x == 4 and y == 6)

tecs.math.vec2.moveTowards Static

Moves a point toward another by at most a given distance.

A frame-rate-independent chase passes the speed for this frame:

function tecs.math.vec2.moveTowards(
    x: number,
    y: number,
    targetX: number,
    targetY: number,
    maxDistance: number
): number, number

Arguments

Name Type Description
x number Starting point's x coordinate.
y number Starting point's y coordinate.
targetX number Destination point's x coordinate.
targetY number Destination point's y coordinate.
maxDistance number Greatest distance to travel. A nonpositive value leaves the starting point unchanged.

Returns

Type Description
number The moved x coordinate. Reaching the destination returns it exactly and never overshoots.
number The moved y coordinate, with the same endpoint rule.

Examples

Moves toward a target without overshooting it.

local x, y = tecs.math.vec2.moveTowards(0, 0, 3, 4, 2)

assert(x == 1.2 and y == 1.6)

tecs.math.vec2.normalize Static

Produces a unit vector in the same direction.

function tecs.math.vec2.normalize(x: number, y: number): number, number

Arguments

Name Type Description
x number Vector's x coordinate.
y number Vector's y coordinate.

Returns

Type Description
number The normalized x coordinate. A zero vector returns zero because it has no direction.
number The normalized y coordinate, with the same zero-vector rule.

Examples

Builds a unit direction toward a target.

local x, y = tecs.math.vec2.normalize(3, 4)

assert(x == 0.6 and y == 0.8)

tecs.math.vec2.project Static

Projects a vector onto another vector.

The projection axis may have any length:

function tecs.math.vec2.project(
    x: number, y: number, ontoX: number, ontoY: number
): number, number

Arguments

Name Type Description
x number The vector's x coordinate.
y number The vector's y coordinate.
ontoX number Projection axis's x coordinate.
ontoY number Projection axis's y coordinate.

Returns

Type Description
number The projected x coordinate. The axis may have any length; a zero axis returns zero.
number The projected y coordinate, with the same zero-axis rule.

Examples

Keeps only the component of a velocity along an axis.

local x, y = tecs.math.vec2.project(3, 4, 1, 0)

assert(x == 3 and y == 0)

tecs.math.vec2.reflect Static

Reflects a vector across the line perpendicular to a normal.

The normal may have any length:

function tecs.math.vec2.reflect(
    x: number, y: number, normalX: number, normalY: number
): number, number

Arguments

Name Type Description
x number The vector's x coordinate.
y number The vector's y coordinate.
normalX number Surface normal's x coordinate.
normalY number Surface normal's y coordinate.

Returns

Type Description
number The reflected x coordinate. The normal may have any length; a zero normal returns the original x coordinate.
number The reflected y coordinate, with the same zero-normal rule.

Examples

Bounces a velocity from a surface normal.

local x, y = tecs.math.vec2.reflect(1, -1, 0, 1)

assert(x == 1 and y == 1)

tecs.math.vec2.rotate Static

Rotates a vector around the origin.

function tecs.math.vec2.rotate(
    x: number, y: number, radians: number
): number, number

Arguments

Name Type Description
x number Vector's x coordinate.
y number Vector's y coordinate.
radians number Rotation in radians. A positive quarter turn maps (1, 0) to (0, 1).

Returns

Type Description
number The rotated x coordinate.
number The rotated y coordinate.

Examples

Rotates a facing direction by a quarter turn.

local x, y = tecs.math.vec2.rotate(1, 0, math.pi / 2)

assert(math.abs(x) < 0.000001 and math.abs(y - 1) < 0.000001)

tecs.math.vec2.scale Static

Multiplies both coordinates by a scalar.

function tecs.math.vec2.scale(
    x: number, y: number, factor: number
): number, number

Arguments

Name Type Description
x number Vector's x coordinate.
y number Vector's y coordinate.
factor number Multiplier applied to both coordinates.

Returns

Type Description
number The scaled x coordinate.
number The scaled y coordinate.

Examples

Turns a unit direction into a movement step.

local x, y = tecs.math.vec2.scale(2, 3, 4)

assert(x == 8 and y == 12)

tecs.math.vec2.signedAngleBetween Static

Computes the smaller signed angle from one vector to another.

Use the answer directly as the shortest directional correction:

function tecs.math.vec2.signedAngleBetween(
    ax: number, ay: number, bx: number, by: number
): number

Arguments

Name Type Description
ax number Starting vector's x coordinate.
ay number Starting vector's y coordinate.
bx number Destination vector's x coordinate.
by number Destination vector's y coordinate.

Returns

Type Description
number Radians in [-pi, pi), positive in the same sense as rotate. If either vector is zero, returns zero; an exact half-turn is negative pi.

Examples

Chooses the shortest directional correction toward a target.

assert(tecs.math.vec2.signedAngleBetween(1, 0, 0, 1) == math.pi / 2)

tecs.math.vec2.subtract Static

Subtracts the second vector from the first.

function tecs.math.vec2.subtract(
    ax: number, ay: number, bx: number, by: number
): number, number

Arguments

Name Type Description
ax number First vector's x coordinate.
ay number First vector's y coordinate.
bx number Second vector's x coordinate.
by number Second vector's y coordinate.

Returns

Type Description
number The difference's x coordinate.
number The difference's y coordinate.

Examples

Finds the offset from a position to a target.

local x, y = tecs.math.vec2.subtract(5, 4, 1, 2)

assert(x == 4 and y == 2)