diff options
author | Elizabeth Hunt <elizabeth.hunt@simponic.xyz> | 2023-07-20 20:47:32 -0700 |
---|---|---|
committer | Elizabeth Hunt <elizabeth.hunt@simponic.xyz> | 2023-07-20 20:47:32 -0700 |
commit | 72c6c7de12e9833f52bf2d0718d70f044f8ab57e (patch) | |
tree | 152f5f31d59011bb8c617bfbcfc44cc8f47ecad5 /engine/components/BoundingBox.ts | |
parent | 0fd9fb097552686f2257c1aa689d797e80057bd1 (diff) | |
download | jumpstorm-72c6c7de12e9833f52bf2d0718d70f044f8ab57e.tar.gz jumpstorm-72c6c7de12e9833f52bf2d0718d70f044f8ab57e.zip |
a bit of refactoring; importing engine into bun for server
Diffstat (limited to 'engine/components/BoundingBox.ts')
-rw-r--r-- | engine/components/BoundingBox.ts | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/engine/components/BoundingBox.ts b/engine/components/BoundingBox.ts new file mode 100644 index 0000000..2b1d648 --- /dev/null +++ b/engine/components/BoundingBox.ts @@ -0,0 +1,97 @@ +import { Component, ComponentNames } from "."; +import type { Coord2D, Dimension2D } from "../interfaces"; +import { dotProduct, rotateVector, normalizeVector } from "../utils"; + +export class BoundingBox extends Component { + public center: Coord2D; + public dimension: Dimension2D; + public rotation: number; + + constructor(center: Coord2D, dimension: Dimension2D, rotation?: number) { + super(ComponentNames.BoundingBox); + + this.center = center; + this.dimension = dimension; + this.rotation = rotation ?? 0; + } + + public isCollidingWith(box: BoundingBox): boolean { + const boxes = [this.getVertices(), box.getVertices()]; + for (const poly of boxes) { + for (let i = 0; i < poly.length; ++i) { + const [A, B] = [poly[i], poly[(i + 1) % poly.length]]; + const normal: Coord2D = { x: B.y - A.y, y: A.x - B.x }; + + const [[minThis, maxThis], [minBox, maxBox]] = boxes.map((box) => + box.reduce( + ([min, max], vertex) => { + const projection = dotProduct(normal, vertex); + return [Math.min(min, projection), Math.max(max, projection)]; + }, + [Infinity, -Infinity] + ) + ); + + if (maxThis < minBox || maxBox < minThis) return false; + } + } + + return true; + } + + public getVertices(): Coord2D[] { + return [ + { x: -this.dimension.width / 2, y: -this.dimension.height / 2 }, + { x: -this.dimension.width / 2, y: this.dimension.height / 2 }, + { x: this.dimension.width / 2, y: this.dimension.height / 2 }, + { x: this.dimension.width / 2, y: -this.dimension.height / 2 }, + ] + .map((vertex) => rotateVector(vertex, this.rotation)) + .map((vertex) => { + return { + x: vertex.x + this.center.x, + y: vertex.y + this.center.y, + }; + }); + } + + private getAxes() { + const corners: Coord2D[] = this.getVerticesRelativeToCenter(); + const axes: Coord2D[] = []; + + for (let i = 0; i < corners.length; ++i) { + const [cornerA, cornerB] = [ + corners[i], + corners[(i + 1) % corners.length], + ].map((corner) => rotateVector(corner, this.rotation)); + + axes.push( + normalizeVector({ + x: cornerB.y - cornerA.y, + y: -(cornerB.x - cornerA.x), + }) + ); + } + + return axes; + } + + private project(axis: Coord2D): [number, number] { + const corners = this.getCornersRelativeToCenter(); + let [min, max] = [Infinity, -Infinity]; + + for (const corner of corners) { + const rotated = rotateVector(corner, this.rotation); + const translated = { + x: rotated.x + this.center.x, + y: rotated.y + this.center.y, + }; + const projection = dotProduct(translated, axis); + + min = Math.min(projection, min); + max = Math.max(projection, max); + } + + return [min, max]; + } +} |