import SAT from 'sat' import SATX from './satx.js' import { Vector2 } from 'three' export default class Projectile { id = crypto.randomUUID() after = null speed = 1000 radius = 5 owner = null onCollide = null visualHeight = 50 #position = new Vector2() #dest = null #game = null get collider() { return new SAT.Circle(new SAT.Vector(this.x, this.y), this.radius) } constructor(...options) { Object.entries(options).forEach((value, key) => this[key] = value) } get game() { return this.#game } get position() { return this.#position } get x() { return this.position.x } get y() { return this.position.y } set game(value) { this.#game = value } set x(value) { this.position.x = value } set y(value) { this.position.y = value } set destination(value) { this.#dest = value } checkCollisions() { (this.game?.entities ?? []).filter((e) => e.id != this.id).forEach((e) => { if (e.id == this.owner) { return } if (SATX.collideObject(this.collider, e.collider)) { this.onCollide(this, e) } }) } checkIfArrived() { if (!this.#position.equals(this.#dest)) { return } if (this.after != null) { this.after(this) } this.despawn() } despawn() { this.game?.despawn(this) } state() { return { ...this, position: { x: this.x, y: this.y, }, } } takeStep() { const speed = (this.speed / (this.game?.tickBudget ?? 1000)) const destination = this.#dest const difference = destination.clone().sub(this.position) const distance = difference.length() const direction = difference.clone().normalize() const stepTaken = this.position.clone().add(direction.multiplyScalar(speed)) const position = distance <= speed ? destination : stepTaken this.position.copy(position) } update() { this.takeStep() if (this.onCollide != null) { this.checkCollisions() } this.checkIfArrived() } }