import type { Iwt2ArenaBounds, Iwt2Vec2 } from './types' export const IWT2_ZERO_VECTOR: Iwt2Vec2 = { x: 0, y: 0 } export function addVec2(a: Iwt2Vec2, b: Iwt2Vec2): Iwt2Vec2 { return { x: a.x + b.x, y: a.y + b.y } } export function subtractVec2(a: Iwt2Vec2, b: Iwt2Vec2): Iwt2Vec2 { return { x: a.x - b.x, y: a.y - b.y } } export function scaleVec2(vector: Iwt2Vec2, scale: number): Iwt2Vec2 { return { x: vector.x * scale, y: vector.y * scale } } export function dotVec2(a: Iwt2Vec2, b: Iwt2Vec2): number { return a.x * b.x + a.y * b.y } export function lengthSqVec2(vector: Iwt2Vec2): number { return dotVec2(vector, vector) } export function lengthVec2(vector: Iwt2Vec2): number { return Math.sqrt(lengthSqVec2(vector)) } export function distanceVec2(a: Iwt2Vec2, b: Iwt2Vec2): number { return lengthVec2(subtractVec2(a, b)) } export function normalizeVec2(vector: Iwt2Vec2): Iwt2Vec2 { const length = lengthVec2(vector) if (length <= 0.0001) return { ...IWT2_ZERO_VECTOR } return { x: vector.x / length, y: vector.y / length } } export function clamp(value: number, min: number, max: number): number { return Math.min(max, Math.max(min, value)) } export function clampVec2ToArena(position: Iwt2Vec2, radius: number, bounds: Iwt2ArenaBounds): Iwt2Vec2 { return { x: clamp(position.x, radius, bounds.width - radius), y: clamp(position.y, radius, bounds.height - radius), } } export function moveToward(current: Iwt2Vec2, target: Iwt2Vec2, maxDistance: number): Iwt2Vec2 { const offset = subtractVec2(target, current) const distance = lengthVec2(offset) if (distance <= maxDistance || distance <= 0.0001) return { ...target } return addVec2(current, scaleVec2(offset, maxDistance / distance)) } export function withFallbackFacing(nextFacing: Iwt2Vec2, fallback: Iwt2Vec2): Iwt2Vec2 { if (lengthSqVec2(nextFacing) <= 0.0001) return { ...fallback } return normalizeVec2(nextFacing) }