On this page
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, numberArguments
| 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): numberArguments
| 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
): numberArguments
| 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
): numberArguments
| 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
): numberArguments
| 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
): numberArguments
| 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
): numberArguments
| 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): numberArguments
| 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): numberArguments
| 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, numberArguments
| 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, numberArguments
| 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, numberArguments
| 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, numberArguments
| 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, numberArguments
| 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, numberArguments
| 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, numberArguments
| 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
): numberArguments
| 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, numberArguments
| 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)