Vector
The Vector element provides 3D vector mathematics for position, velocity, and force calculations. While designed for 3D operations, it maintains backward compatibility with 2D use cases by defaulting the z-coordinate to 0.
Creating Vectors
const draw = (K: KlintContext) => {
// Create a 2D vector (z defaults to 0)
const position = K.createVector(100, 200);
// Create a 3D vector explicitly
const position3D = K.createVector(100, 200, 50);
// Create from class (if needed)
const velocity = new K.Vector(5, -3, 0);
}
Properties
x: X-coordinatey: Y-coordinatez: Z-coordinate (defaults to 0 for 2D compatibility)
Methods
Basic Operations
add(vector)
add(v: Vector) => Vector
Adds another vector to this vector (including z component).
const pos = K.createVector(100, 100, 10);
const vel = K.createVector(2, -1, 0.5);
pos.add(vel); // pos is now (102, 99, 10.5)
sub(vector)
sub(v: Vector) => Vector
Subtracts another vector from this vector (including z component).
const a = K.createVector(100, 100, 20);
const b = K.createVector(20, 30, 5);
a.sub(b); // a is now (80, 70, 15)
mult(scalar)
mult(n: number) => Vector
Multiplies the vector by a scalar (affects all components).
const vec = K.createVector(10, 20, 30);
vec.mult(0.5); // vec is now (5, 10, 15)
div(scalar)
div(n: number) => Vector
Divides the vector by a scalar (affects all components).
const vec = K.createVector(100, 50, 25);
vec.div(10); // vec is now (10, 5, 2.5)
Geometric Operations
rotate(angle)
rotate(angle: number) => Vector
Rotates the vector by an angle around the z-axis (2D rotation, z component unchanged).
const vec = K.createVector(100, 0, 5);
vec.rotate(Math.PI / 2); // vec is now (0, 100, 5)
normalize()
normalize() => Vector
Normalizes the vector to unit length (magnitude = 1) in 3D space.
const vec = K.createVector(100, 100, 100);
vec.normalize(); // vec is now (0.577..., 0.577..., 0.577...)
Measurement Functions
mag() / length()
mag() => number
length() => number // Alias for mag()
Returns the magnitude (length) of the vector in 3D space.
const vec = K.createVector(2, 3, 6);
const magnitude = vec.mag(); // 7
dist(vector)
dist(v: Vector) => number
Calculates 3D distance to another vector.
const a = K.createVector(0, 0, 0);
const b = K.createVector(2, 3, 6);
const distance = a.dist(b); // 7
dot(vector)
dot(v: Vector) => number
Calculates the 3D dot product with another vector.
const a = K.createVector(2, 3, 4);
const b = K.createVector(5, 6, 7);
const dotProduct = a.dot(b); // 56 (2*5 + 3*6 + 4*7)
angle()
angle() => number
Returns the angle of the vector in radians (2D calculation, ignoring z).
const vec = K.createVector(1, 1, 10);
const angle = vec.angle(); // π/4 radians (45 degrees)
Advanced Operations
cross(vector)
cross(v: Vector) => Vector
Calculates the 3D cross product with another vector, returning a new vector.
const a = K.createVector(1, 0, 0);
const b = K.createVector(0, 1, 0);
const cross = a.cross(b); // (0, 0, 1)
relativeTo(vector)
relativeTo(v: Vector) => Vector
Makes this vector relative to another vector by subtracting the reference vector.
const worldPos = K.createVector(100, 200, 50);
const origin = K.createVector(50, 100, 25);
worldPos.relativeTo(origin); // worldPos is now (50, 100, 25)
lookAt(target)
lookAt(target: Vector) => Vector
Makes this vector point towards a target vector (normalized direction).
const position = K.createVector(0, 0, 0);
const target = K.createVector(3, 4, 0);
position.lookAt(target); // position is now (0.6, 0.8, 0)
toScreen(width, height)
toScreen(width: number, height: number) => Vector
Converts from normalized coordinates (-1 to 1) to screen coordinates.
const normalizedPos = K.createVector(0, 0, 0); // Center
normalizedPos.toScreen(800, 600); // (400, 300, 0)
slerp(vector, amount)
slerp(v: Vector, amt: number) => Vector
Spherical linear interpolation between this vector and another vector.
const a = K.createVector(1, 0, 0);
const b = K.createVector(0, 1, 0);
a.slerp(b, 0.5); // Smooth interpolation halfway between vectors
Utility Functions
copy()
copy() => Vector
Creates a copy of the vector (including z component).
const original = K.createVector(10, 20, 30);
const copy = original.copy();
copy.mult(2); // original is unchanged
set(x, y, z)
set(x: number, y: number, z?: number) => Vector
Sets the vector's coordinates (z defaults to 0).
const vec = K.createVector(0, 0, 0);
vec.set(100, 200, 300); // vec is now (100, 200, 300)
vec.set(50, 75); // vec is now (50, 75, 0)
Static Methods
fromAngle(center, angle, radius)
Vector.fromAngle(center: Vector, angle: number, radius: number) => Vector
Creates a vector at a specific angle and distance from a center point (2D operation, preserves z).
const center = K.createVector(200, 200, 100);
const point = K.Vector.fromAngle(center, Math.PI / 4, 100);
// point is 100 units away from center at 45 degrees, z=100
Common Patterns
3D Physics Simulation
const draw = (K: KlintContext) => {
// Initialize if first frame
if (!K.State.has('particles')) {
const particles = [];
for (let i = 0; i < 10; i++) {
particles.push({
position: K.createVector(K.width/2, K.height/2, 0),
velocity: K.createVector(
(Math.random() - 0.5) * 4,
(Math.random() - 0.5) * 4,
(Math.random() - 0.5) * 2
),
acceleration: K.createVector(0, 0.1, 0) // gravity
});
}
K.State.set('particles', particles);
}
const particles = K.State.get('particles');
K.background("#222");
particles.forEach(particle => {
// Apply physics
particle.velocity.add(particle.acceleration);
particle.position.add(particle.velocity);
// Bounce off edges (2D bounds)
if (particle.position.x < 0 || particle.position.x > K.width) {
particle.velocity.x *= -0.8;
}
if (particle.position.y < 0 || particle.position.y > K.height) {
particle.velocity.y *= -0.8;
}
// Constrain to canvas
particle.position.x = K.constrain(particle.position.x, 0, K.width);
particle.position.y = K.constrain(particle.position.y, 0, K.height);
// Size based on z-depth
const size = 5 + particle.position.z * 0.1;
// Draw particle
K.fillColor("white");
K.circle(particle.position.x, particle.position.y, size);
});
}
3D Steering and Following
const draw = (K: KlintContext) => {
const { mouse } = KlintMouse();
// Initialize agent
if (!K.State.has('agent')) {
K.State.set('agent', {
position: K.createVector(K.width/2, K.height/2, 0),
velocity: K.createVector(0, 0, 0),
maxSpeed: 3
});
}
const agent = K.State.get('agent');
const target = K.createVector(mouse.x, mouse.y, 0);
// Calculate desired velocity toward target
const desired = target.copy().sub(agent.position);
desired.normalize().mult(agent.maxSpeed);
// Steering force
const steer = desired.copy().sub(agent.velocity);
steer.mult(0.1); // steering strength
// Update agent
agent.velocity.add(steer);
agent.position.add(agent.velocity);
K.background("#333");
// Draw agent
K.fillColor("cyan");
K.circle(agent.position.x, agent.position.y, 20);
// Draw 3D velocity vector
K.strokeColor("yellow");
K.strokeWidth(2);
const velEnd = agent.position.copy().add(
agent.velocity.copy().mult(10)
);
K.line(
agent.position.x, agent.position.y,
velEnd.x, velEnd.y
);
}
Spherical Interpolation Animation
const draw = (K: KlintContext) => {
if (!K.State.has('vectors')) {
K.State.set('vectors', {
start: K.createVector(1, 0, 0),
end: K.createVector(0, 1, 0),
current: K.createVector(1, 0, 0),
t: 0
});
}
const vectors = K.State.get('vectors');
const center = K.createVector(K.width/2, K.height/2, 0);
// Animate interpolation
vectors.t += 0.01;
if (vectors.t > 1) vectors.t = 0;
// Reset current and interpolate
vectors.current.set(vectors.start.x, vectors.start.y, vectors.start.z);
vectors.current.slerp(vectors.end, vectors.t);
K.background("#111");
// Draw interpolated vector
const scaled = vectors.current.copy().mult(100);
const end = center.copy().add(scaled);
K.strokeColor("white");
K.strokeWidth(3);
K.line(center.x, center.y, end.x, end.y);
K.fillColor("red");
K.circle(end.x, end.y, 8);
}
Cross Product Visualization
const draw = (K: KlintContext) => {
const center = K.createVector(K.width/2, K.height/2, 0);
// Two vectors
const a = K.createVector(100, 0, 0);
const b = K.createVector(50, 80, 0);
// Cross product (perpendicular to both)
const cross = a.cross(b);
K.background("#222");
// Draw vectors
K.strokeColor("red");
K.strokeWidth(3);
K.line(center.x, center.y, center.x + a.x, center.y + a.y);
K.strokeColor("blue");
K.line(center.x, center.y, center.x + b.x, center.y + b.y);
// Show cross product magnitude as text
K.fillColor("white");
K.text(`Cross product Z: ${cross.z.toFixed(2)}`, 10, 30);
}
Notes
- 3D Support: All operations now work in 3D space, with z defaulting to 0 for 2D compatibility
- Method Chaining: All vector operations modify the original vector and return
thisfor chaining:vec.normalize().mult(speed).add(offset) - Copy When Needed: Use
copy()when you need to preserve the original vector during operations - Angles in Radians: All angle operations use radians; use
degrees * (Math.PI / 180)for conversion - Performance: For performance-critical code, consider reusing vectors instead of creating new ones
- Cross Product: Returns a new vector perpendicular to both input vectors (right-hand rule)
- Slerp: Provides smooth interpolation that maintains constant angular velocity
- Screen Coordinates:
toScreen()converts from normalized device coordinates to pixel coordinates