62 lines
1.6 KiB
JavaScript
62 lines
1.6 KiB
JavaScript
import SAT from 'sat'
|
|
import { Shape, ShapeUtils, Vector2 } from 'three'
|
|
|
|
export default class Terrain {
|
|
id = crypto.randomUUID()
|
|
|
|
position = new Vector2()
|
|
relativeVertices = []
|
|
|
|
#colliders = []
|
|
#vertices = []
|
|
|
|
constructor(vertices) {
|
|
this.#vertices = vertices.map((v) => new Vector2(v.x, v.y))
|
|
this.#calculateColliders()
|
|
this.#calculatePosition()
|
|
this.#calculateRelativeVertices()
|
|
}
|
|
|
|
get colliders() { return this.#colliders }
|
|
get vertices() { return this.#vertices }
|
|
|
|
state() {
|
|
return {
|
|
...this,
|
|
position: {
|
|
x: this.x,
|
|
y: this.y,
|
|
},
|
|
}
|
|
}
|
|
|
|
#calculateColliders() {
|
|
const complexShape = new Shape()
|
|
|
|
complexShape.moveTo(this.#vertices.at(0).x, this.#vertices.at(0).y)
|
|
this.#vertices.slice(1).forEach((v) => complexShape.lineTo(v.x, v.y))
|
|
|
|
const points = complexShape.extractPoints(16)
|
|
|
|
const indicesToPolygon = (indices) => {
|
|
const satPoints = [
|
|
new SAT.Vector(...points.shape[indices[0]].toArray()),
|
|
new SAT.Vector(...points.shape[indices[1]].toArray()),
|
|
new SAT.Vector(...points.shape[indices[2]].toArray()),
|
|
]
|
|
|
|
return new SAT.Polygon(satPoints[0], [new SAT.Vector(), satPoints[1], satPoints[2]])
|
|
}
|
|
|
|
this.#colliders = ShapeUtils.triangulateShape(points.shape, points.holes).map(indicesToPolygon)
|
|
}
|
|
|
|
#calculatePosition() {
|
|
this.position = this.#vertices.reduce(((sum, v) => sum.add(v)), new Vector2()).divideScalar(this.#vertices.length)
|
|
}
|
|
|
|
#calculateRelativeVertices() {
|
|
this.relativeVertices = this.#vertices.map((v) => v.clone().sub(this.position))
|
|
}
|
|
}
|