@hiddentao/clockwork-engine
Version:
A TypeScript/PIXI.js game engine for deterministic, replayable games with built-in rendering
124 lines (123 loc) • 3.61 kB
JavaScript
export class Vector2D {
constructor(x, y) {
this.x = x;
this.y = y;
}
add(other) {
return new Vector2D(this.x + other.x, this.y + other.y);
}
subtract(other) {
return new Vector2D(this.x - other.x, this.y - other.y);
}
scale(scalar) {
return new Vector2D(this.x * scalar, this.y * scalar);
}
dot(other) {
return this.x * other.x + this.y * other.y;
}
length() {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
distance(other) {
return Vector2D.distance(this, other);
}
normalize() {
const len = this.length();
if (len === 0) {
return new Vector2D(0, 0);
}
return new Vector2D(this.x / len, this.y / len);
}
rotate(angle) {
const cos = Math.cos(angle);
const sin = Math.sin(angle);
return new Vector2D(this.x * cos - this.y * sin, this.x * sin + this.y * cos);
}
/**
* Calculate the angle of this vector in radians
* @returns The angle in radians [-PI, PI]
*/
angle() {
return Math.atan2(this.y, this.x);
}
/**
* Calculate the angle between this vector and another vector
* @param other The other vector
* @returns The angle in radians between the two vectors
*/
angleBetween(other) {
return Math.atan2(other.y - this.y, other.x - this.x);
}
clone() {
return new Vector2D(this.x, this.y);
}
toString() {
return `(${this.x}, ${this.y})`;
}
/**
* Serialize this Vector2D to a plain object
*/
serialize() {
return { x: this.x, y: this.y };
}
/**
* Deserialize a plain object to a Vector2D
*/
static deserialize(data) {
return new Vector2D(data.x, data.y);
}
/**
* Calculate distance between two vectors
*/
static distance(v1, v2) {
const dx = v1.x - v2.x;
const dy = v1.y - v2.y;
return Math.sqrt(dx * dx + dy * dy);
}
/**
* Calculate squared distance between two vectors (more efficient for comparisons)
*/
static distanceSquared(v1, v2) {
const dx = v1.x - v2.x;
const dy = v1.y - v2.y;
return dx * dx + dy * dy;
}
/**
* Check if two positions are within a specified distance of each other
* @param v1 First position
* @param v2 Second position
* @param distance Maximum distance between positions
* @returns True if the positions are within the specified distance
*/
static isWithinDistance(v1, v2, distance) {
return Vector2D.distanceSquared(v1, v2) <= distance * distance;
}
/**
* Normalize angle to (-PI, PI) range
*/
static normalizeAngle(angle) {
while (angle > Math.PI)
angle -= 2 * Math.PI;
while (angle < -Math.PI)
angle += 2 * Math.PI;
return angle;
}
/**
* Calculate the shortest angle difference between two angles
* @param angle1 First angle in radians
* @param angle2 Second angle in radians
* @returns The shortest angle difference in radians
*/
static angleDifference(angle1, angle2) {
// Normalize both angles to (-PI, PI) range
angle1 = Vector2D.normalizeAngle(angle1);
angle2 = Vector2D.normalizeAngle(angle2);
// Find the shortest angle difference
let diff = angle2 - angle1;
if (diff > Math.PI)
diff -= 2 * Math.PI;
if (diff < -Math.PI)
diff += 2 * Math.PI;
return diff;
}
}