import { vec2 } from 'gl-matrix'; import { id, settings, serializesTo, ProjectileBase, GameObject } from 'shared'; import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box'; import { CirclePhysical } from './circle-physical'; import { DynamicPhysical } from '../physics/physicals/dynamic-physical'; import { PhysicalContainer } from '../physics/containers/physical-container'; import { PlanetPhysical } from './planet-physical'; import { ReactsToCollision } from '../physics/physicals/reacts-to-collision'; import { UpdateObjectMessage } from 'shared/lib/src/objects/update-object-message'; import { UpdateGameObjectMessage } from '../update-game-object-message'; @serializesTo(ProjectileBase) export class ProjectilePhysical extends ProjectileBase implements DynamicPhysical, ReactsToCollision { public readonly canCollide = true; public readonly canMove = true; private isDestroyed = false; private bounceCount = 0; private _boundingBox?: ImmutableBoundingBox; public object: CirclePhysical; constructor( center: vec2, radius: number, private velocity: vec2, readonly container: PhysicalContainer, ) { super(id(), center, radius); this.object = new CirclePhysical(center, radius, this, container, 0.9); } public calculateUpdates(): UpdateObjectMessage { return new UpdateGameObjectMessage(this, ['center']); } public get boundingBox(): ImmutableBoundingBox { if (!this._boundingBox) { this._boundingBox = (this.object as CirclePhysical).boundingBox; } return this._boundingBox; } public get gameObject(): this { return this; } public distance(target: vec2): number { return this.object.distance(target); } public destroy() { if (!this.isDestroyed) { this.isDestroyed = true; this.container.removeObject(this); } } public onCollision(other: GameObject) { if (this.bounceCount++ === settings.projectileMaxBounceCount) { this.destroy(); } } public step(deltaTime: number) { const gravity = vec2.create(); const intersecting = this.container.findIntersecting(this.boundingBox); intersecting.forEach((i) => { if (i instanceof PlanetPhysical) { vec2.add(gravity, gravity, i.getForce(this.center)); } }); vec2.add(this.velocity, this.velocity, vec2.scale(vec2.create(), gravity, deltaTime)); this.object.velocity = this.velocity; this.object.step2(deltaTime); } }