import { axisAlignedBoundingBox } from "../collision/aa.ts"; import { CircleLike } from "../collision/circular.ts"; import { Vector } from "../mod.ts"; import { Point } from "./vector.ts"; export class Polygon { points: Vector[]; center: Vector; constructor(points: Point[]) { this.points = points.map((p) => new Vector(p)); this.center = this.calcCenter(); } draw(color?: string) { for (let i = 0; i < this.points.length; i++) { const p1 = this.points[i]; const p2 = this.points.at(i - this.points.length + 1)!; doodler.line(p1.copy().add(this.center), p2.copy().add(this.center), { color, }); const { x, y, w, h } = this.aaHitbox(); doodler.drawRect(new Vector(x, y), w, h, { color: "lime" }); } } calcCenter() { if (!this.points.length) return new Vector(); const center = new Vector(); for (const point of this.points) { center.add(point); } center.div(this.points.length); return center; } circularHitbox(): CircleLike { let greatestDistance = 0; for (const p of this.points) { greatestDistance = Math.max( p.copy().add(this.center).dist(this.center), greatestDistance, ); } return { center: this.center.copy(), radius: greatestDistance, }; } aaHitbox(): axisAlignedBoundingBox { let smallestX, biggestX, smallestY, biggestY; smallestX = smallestY = Infinity; biggestX = biggestY = -Infinity; for (const p of this.points) { const temp = p.copy().add(this.center); smallestX = Math.min(temp.x, smallestX); biggestX = Math.max(temp.x, biggestX); smallestY = Math.min(temp.y, smallestY); biggestY = Math.max(temp.y, biggestY); } return { x: smallestX, y: smallestY, w: biggestX - smallestX, h: biggestY - smallestY, }; } static createPolygon(sides = 3, radius = 100) { sides = Math.round(sides); if (sides < 3) { throw "You need at least 3 sides for a polygon"; } const poly = new Polygon([]); // figure out the angles required const rotangle = (Math.PI * 2) / sides; let angle = 0; // loop through and generate each point for (let i = 0; i < sides; i++) { angle = (i * rotangle) + ((Math.PI - rotangle) * 0.5); const pt = new Vector(Math.cos(angle) * radius, Math.sin(angle) * radius); poly.points.push(pt); } poly.center = poly.calcCenter(); return poly; } }