Spaces:
Running
Running
import * as THREE from "three"; | |
export class Projectile { | |
constructor(pos, target, speed, scene, projectileEffect = null) { | |
this.position = pos.clone(); | |
this.target = target; | |
this.speed = speed; | |
this.scene = scene; | |
this.damage = 0; // Will be set by tower | |
this.projectileEffect = projectileEffect; | |
const geo = new THREE.SphereGeometry(0.15, 8, 8); | |
const mat = new THREE.MeshStandardMaterial({ | |
color: | |
projectileEffect && projectileEffect.color | |
? projectileEffect.color | |
: 0xffe082, | |
emissive: | |
projectileEffect && projectileEffect.emissive | |
? projectileEffect.emissive | |
: 0x553300, | |
}); | |
const mesh = new THREE.Mesh(geo, mat); | |
mesh.castShadow = true; | |
mesh.position.copy(this.position); | |
this.mesh = mesh; | |
scene.add(mesh); | |
this.alive = true; | |
} | |
update(dt, spawnHitEffect) { | |
if (!this.alive) return "dead"; | |
if (!this.target || this.target.isDead()) { | |
this.alive = false; | |
return "dead"; | |
} | |
const toTarget = new THREE.Vector3().subVectors( | |
this.target.mesh.position, | |
this.position | |
); | |
const dist = toTarget.length(); | |
if (dist < 0.4) { | |
this.target.takeDamage(this.damage); | |
// Apply on-hit effect if any | |
if ( | |
this.projectileEffect && | |
this.projectileEffect.type === "slow" && | |
this.target.applySlow | |
) { | |
const mult = this.projectileEffect.mult ?? 1.0; | |
const duration = this.projectileEffect.duration ?? 0; | |
this.target.applySlow(mult, duration); | |
} | |
spawnHitEffect(this.position); | |
this.alive = false; | |
return "hit"; | |
} | |
toTarget.normalize(); | |
this.position.addScaledVector(toTarget, this.speed * dt); | |
this.mesh.position.copy(this.position); | |
return "ok"; | |
} | |
destroy() { | |
this.scene.remove(this.mesh); | |
} | |
} | |