106 lines
3.2 KiB
JavaScript
106 lines
3.2 KiB
JavaScript
class ZombieSpawner {
|
|
constructor(scene, gridX, gridY, spawnRadius = 5, maxZombies = 3, respawnTime = 30000) {
|
|
this.scene = scene;
|
|
this.gridX = gridX;
|
|
this.gridY = gridY;
|
|
this.spawnRadius = spawnRadius;
|
|
this.maxZombies = maxZombies;
|
|
this.respawnTime = respawnTime;
|
|
this.spawnedZombies = [];
|
|
this.respawnTimer = 0;
|
|
this.isActive = true;
|
|
|
|
this.createVisual();
|
|
}
|
|
|
|
createVisual() {
|
|
const screenPos = this.scene.iso.toScreen(this.gridX, this.gridY);
|
|
const x = screenPos.x + this.scene.terrainOffsetX;
|
|
const y = screenPos.y + this.scene.terrainOffsetY;
|
|
|
|
// Spawner sprite (dark portal/grave)
|
|
this.sprite = this.scene.add.sprite(x, y, 'gravestone');
|
|
this.sprite.setOrigin(0.5, 1);
|
|
this.sprite.setScale(0.1); // Tiny size!
|
|
this.sprite.setDepth(this.scene.iso.getDepth(this.gridX, this.gridY, this.scene.iso.LAYER_OBJECTS));
|
|
this.sprite.setTint(0x440044); // Purple tint for spawner
|
|
|
|
// Pulsing effect
|
|
this.scene.tweens.add({
|
|
targets: this.sprite,
|
|
alpha: 0.6,
|
|
duration: 1000,
|
|
yoyo: true,
|
|
repeat: -1
|
|
});
|
|
}
|
|
|
|
spawn() {
|
|
if (this.spawnedZombies.length >= this.maxZombies) return;
|
|
|
|
// Random position around spawner
|
|
const offsetX = Phaser.Math.Between(-this.spawnRadius, this.spawnRadius);
|
|
const offsetY = Phaser.Math.Between(-this.spawnRadius, this.spawnRadius);
|
|
const spawnX = this.gridX + offsetX;
|
|
const spawnY = this.gridY + offsetY;
|
|
|
|
// Create zombie
|
|
const zombie = new NPC(
|
|
this.scene,
|
|
spawnX,
|
|
spawnY,
|
|
this.scene.terrainOffsetX,
|
|
this.scene.terrainOffsetY,
|
|
'zombie'
|
|
);
|
|
|
|
zombie.spawner = this; // Reference back to spawner
|
|
this.spawnedZombies.push(zombie);
|
|
this.scene.npcs.push(zombie);
|
|
|
|
// Spawn effect
|
|
this.scene.events.emit('show-floating-text', {
|
|
x: spawnX * 48,
|
|
y: spawnY * 48,
|
|
text: '💀 Spawn!',
|
|
color: '#FF00FF'
|
|
});
|
|
|
|
if (this.scene.soundManager) {
|
|
this.scene.soundManager.playHit(); // Re-use hit sound for spawn
|
|
}
|
|
|
|
console.log(`👹 Spawner at ${this.gridX},${this.gridY} spawned zombie`);
|
|
}
|
|
|
|
removeZombie(zombie) {
|
|
const index = this.spawnedZombies.indexOf(zombie);
|
|
if (index > -1) {
|
|
this.spawnedZombies.splice(index, 1);
|
|
}
|
|
}
|
|
|
|
update(delta) {
|
|
if (!this.isActive) return;
|
|
|
|
// Clean up dead zombies
|
|
this.spawnedZombies = this.spawnedZombies.filter(z =>
|
|
this.scene.npcs.includes(z) && z.hp > 0
|
|
);
|
|
|
|
// Respawn check
|
|
if (this.spawnedZombies.length < this.maxZombies) {
|
|
this.respawnTimer += delta;
|
|
if (this.respawnTimer >= this.respawnTime) {
|
|
this.respawnTimer = 0;
|
|
this.spawn();
|
|
}
|
|
}
|
|
}
|
|
|
|
destroy() {
|
|
if (this.sprite) this.sprite.destroy();
|
|
if (this.particles) this.particles.destroy();
|
|
}
|
|
}
|