overrun/js/entities/enemies/SprayerEnemy.js

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