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); | |
| } | |
| } | |