97 lines
2.7 KiB
JavaScript
97 lines
2.7 KiB
JavaScript
import { BaseEnemy } from './BaseEnemy.js';
|
|
|
|
const PREFERRED_DIST = 280;
|
|
const SHOOT_INTERVAL = 3000; // ms between bursts
|
|
const PROJECTILE_SPEED = 175;
|
|
const PROJECTILE_DAMAGE = 8;
|
|
const SPRAY_COUNT = 5;
|
|
const SPRAY_HALF_ARC = Math.PI / 6; // ±30° around aim direction
|
|
|
|
export class SprayerEnemy extends BaseEnemy {
|
|
constructor(scene, x, y, player) {
|
|
super(scene, x, y, player, {
|
|
frameOffset: 9,
|
|
radius: 15,
|
|
hp: 50,
|
|
speed: 40,
|
|
xp: 25,
|
|
contactDamage: 8,
|
|
});
|
|
this._shootTimer = SHOOT_INTERVAL * Math.random();
|
|
this.projectiles = scene.add.group();
|
|
this._deathPulseColor = 0x00ffcc;
|
|
}
|
|
|
|
_die() {
|
|
this._gridDeathPulse();
|
|
super._die();
|
|
}
|
|
|
|
update(delta) {
|
|
super.update(delta);
|
|
if (this._dying) return;
|
|
this._strafe();
|
|
this._handleShoot(delta);
|
|
this._updateProjectiles();
|
|
}
|
|
|
|
_strafe() {
|
|
const dist = Phaser.Math.Distance.Between(this.x, this.y, this.player.x, this.player.y);
|
|
const angle = Phaser.Math.Angle.Between(this.x, this.y, this.player.x, this.player.y);
|
|
let vx = 0, vy = 0;
|
|
|
|
if (dist > PREFERRED_DIST + 30) {
|
|
vx = Math.cos(angle) * this.speed;
|
|
vy = Math.sin(angle) * this.speed;
|
|
} else if (dist < PREFERRED_DIST - 30) {
|
|
vx = -Math.cos(angle) * this.speed;
|
|
vy = -Math.sin(angle) * this.speed;
|
|
} else {
|
|
const perp = angle + Math.PI / 2;
|
|
vx = Math.cos(perp) * this.speed;
|
|
vy = Math.sin(perp) * this.speed;
|
|
}
|
|
this.sprite.body.setVelocity(vx, vy);
|
|
}
|
|
|
|
_handleShoot(delta) {
|
|
this._shootTimer -= delta;
|
|
if (this._shootTimer <= 0) {
|
|
this._shootTimer = SHOOT_INTERVAL;
|
|
this._fireSpray();
|
|
}
|
|
}
|
|
|
|
_fireSpray() {
|
|
const baseAngle = Phaser.Math.Angle.Between(this.x, this.y, this.player.x, this.player.y);
|
|
for (let i = 0; i < SPRAY_COUNT; i++) {
|
|
// Spread bullets evenly across the arc: indices 0..4 map to -1..+1
|
|
const t = SPRAY_COUNT === 1 ? 0 : (i / (SPRAY_COUNT - 1)) * 2 - 1;
|
|
const angle = baseAngle + t * SPRAY_HALF_ARC;
|
|
|
|
const proj = this.scene.add.circle(this.x, this.y, 5, 0x00ffaa);
|
|
this.scene.physics.add.existing(proj);
|
|
proj.body.setVelocity(
|
|
Math.cos(angle) * PROJECTILE_SPEED,
|
|
Math.sin(angle) * PROJECTILE_SPEED,
|
|
);
|
|
proj.damage = PROJECTILE_DAMAGE;
|
|
this.projectiles.add(proj);
|
|
this.scene.events.emit('enemy-projectile-spawned', proj);
|
|
}
|
|
}
|
|
|
|
_updateProjectiles() {
|
|
const W = this.scene.scale.width;
|
|
const H = this.scene.scale.height;
|
|
this.projectiles.getChildren().forEach(p => {
|
|
if (p.x < -30 || p.x > W + 30 || p.y < -30 || p.y > H + 30) p.destroy();
|
|
});
|
|
}
|
|
|
|
destroy() {
|
|
this.projectiles.clear(true, true);
|
|
super.destroy();
|
|
}
|
|
}
|