80 lines
2.1 KiB
TypeScript
80 lines
2.1 KiB
TypeScript
import * as THREE from 'three';
|
|
import type { Game } from './Game';
|
|
import { gasDamage, gasRadius, gasDuration } from './Skills';
|
|
|
|
const TICK = 0.5;
|
|
|
|
export class GasCloud {
|
|
body: THREE.Group;
|
|
private level: number;
|
|
private life: number;
|
|
private duration: number;
|
|
private radius: number;
|
|
private tickTimer = 0;
|
|
private puffs: THREE.Mesh[] = [];
|
|
|
|
constructor(position: THREE.Vector3, level: number) {
|
|
this.level = level;
|
|
this.radius = gasRadius(level);
|
|
this.duration = gasDuration(level);
|
|
this.life = this.duration;
|
|
this.body = new THREE.Group();
|
|
this.body.position.copy(position);
|
|
this.body.position.y = 0;
|
|
|
|
const puffGeom = new THREE.SphereGeometry(1, 16, 12);
|
|
const puffMat = new THREE.MeshToonMaterial({
|
|
color: 0x66bb44,
|
|
transparent: true,
|
|
opacity: 0.3,
|
|
depthWrite: false,
|
|
});
|
|
|
|
for (let i = 0; i < 5; i++) {
|
|
const puff = new THREE.Mesh(puffGeom, puffMat);
|
|
const a = (i / 5) * Math.PI * 2;
|
|
puff.position.set(
|
|
Math.cos(a) * this.radius * 0.35,
|
|
0.6 + Math.random() * 0.5,
|
|
Math.sin(a) * this.radius * 0.35
|
|
);
|
|
puff.scale.setScalar(this.radius * (0.3 + Math.random() * 0.2));
|
|
this.body.add(puff);
|
|
this.puffs.push(puff);
|
|
}
|
|
}
|
|
|
|
update(dt: number, game: Game): boolean {
|
|
this.life -= dt;
|
|
if (this.life <= 0) return false;
|
|
|
|
const fade = Math.min(1, this.life / 0.6);
|
|
for (const puff of this.puffs) {
|
|
(puff.material as THREE.MeshToonMaterial).opacity = 0.3 * fade;
|
|
puff.rotation.y += dt * 0.2;
|
|
}
|
|
|
|
this.tickTimer -= dt;
|
|
if (this.tickTimer <= 0) {
|
|
this.tickTimer = TICK;
|
|
const damage = gasDamage(this.level) * TICK;
|
|
for (const enemy of game.enemies) {
|
|
if (enemy.dead) continue;
|
|
const dist = enemy.body.position.distanceTo(this.body.position);
|
|
if (dist < this.radius) {
|
|
enemy.takeDamage(damage, game, false, this.body.position);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
dispose() {
|
|
this.body.removeFromParent();
|
|
for (const puff of this.puffs) {
|
|
puff.geometry.dispose();
|
|
(puff.material as THREE.Material).dispose();
|
|
}
|
|
}
|
|
}
|