Advertisement

← tower-of-time-game

src/prefabs/SplashTower.ts

4.9 KB Download file
// SplashTower - Fires area-of-effect blasts that damage all enemies in radius

/* START-USER-IMPORTS */
import Enemy from "./Enemy";
import Tower from "./Tower";
import GlobalSoundManager from "../utils/GlobalSoundManager";
/* END-USER-IMPORTS */

export default class SplashTower extends Tower {
  constructor(
    scene: Phaser.Scene,
    x?: number,
    y?: number,
    texture?: string,
    frame?: number | string
  ) {
    super(scene, x ?? 578, y ?? 372, texture || "tower4", frame);

    this.setOrigin(0, 0);

    /* START-USER-CTR-CODE */
    // Initialize tower properties
    this.initializeTower();
    /* END-USER-CTR-CODE */
  }

  /* START-USER-CODE */

  // SplashTower-specific properties
  private effectRadius: number = 60; // Default blast radius

  /**
   * Configure tower with TowerConfig
   */
  public configure(config: any): void {
    super.configure(config);

    // Configure SplashTower-specific properties
    if (config.effectRadius !== undefined) {
      this.effectRadius = config.effectRadius;
    }
  }

  /**
   * SplashTower-specific update logic
   */
  protected updateTowerLogic(currentTime: number): void {
    // Fire blast at target if we have one and shooting cooldown is ready
    if (
      this.currentTarget &&
      currentTime - this.lastShotTime >= this.shootingInterval
    ) {
      this.fireBlast(this.currentTarget);
      this.lastShotTime = currentTime;
    }
  }

  /**
   * Fire a blast at the target location
   * @param target Primary target enemy
   */
  private fireBlast(target: Enemy): void {
    // Play blast sound
    GlobalSoundManager.playSound(this.scene, "blast");

    // Calculate blast center position (tower's center)
    const blastX = this.x + this.width / 2;
    const blastY = this.y + this.height / 2;

    // Get all enemies within blast radius
    const enemiesInBlast = this.getEnemiesInBlastRadius(blastX, blastY);

    console.log("enemiesInBlast", enemiesInBlast);

    if (enemiesInBlast.length === 0) {
      return;
    }

    // Deal damage to all enemies in blast radius
    enemiesInBlast.forEach((enemy) => {
      enemy.takeDamage(this.damage);
    });

    // Create visual effect (placeholder - could be enhanced with particles)
    this.createBlastEffect(blastX, blastY);

    console.debug(
      `SplashTower fired blast at (${blastX}, ${blastY}), hit ${enemiesInBlast.length} enemies`
    );
  }

  /**
   * Get all enemies within blast radius of a point
   */
  private getEnemiesInBlastRadius(centerX: number, centerY: number): Enemy[] {
    const enemies = this.getAllEnemies();
    const radiusSquared = this.effectRadius * this.effectRadius;

    return enemies.filter((enemy) => {
      if (!enemy.canBeTargeted()) {
        return false;
      }

      const dx = enemy.x - centerX;
      const dy = enemy.y - centerY;
      const distanceSquared = dx * dx + dy * dy;

      return distanceSquared <= radiusSquared;
    });
  }

  /**
   * Create visual blast effect
   */
  private createBlastEffect(x: number, y: number): void {
    // Create a simple circle graphic for the blast effect
    const blastGraphic = this.scene.add.graphics();
    blastGraphic.lineStyle(3, 0xff6600, 1); // Orange outline
    blastGraphic.fillStyle(0xff9900, 0.3); // Semi-transparent orange fill

    // Position the graphics object at the blast center
    blastGraphic.x = x;
    blastGraphic.y = y;

    // Draw the circle centered at (0,0) relative to the graphics object
    blastGraphic.fillCircle(0, 0, this.effectRadius);
    blastGraphic.strokeCircle(0, 0, this.effectRadius);

    // Add to effect layer if available
    const layers = (this.scene as any).getLayers?.();
    if (layers && layers.effect) {
      layers.effect.add(blastGraphic);
      blastGraphic.setDepth(250); // Above bullets
    } else {
      blastGraphic.setDepth(200);
    }

    // Animate the blast effect
    this.scene.tweens.add({
      targets: blastGraphic,
      scaleX: 1.5,
      scaleY: 1.5,
      alpha: 0,
      duration: 300,
      ease: "Power2",
      onComplete: () => {
        blastGraphic.destroy();
      },
    });
  }

  /**
   * Get blast radius for external access
   */
  public getBlastRadius(): number {
    return this.effectRadius;
  }

  /**
   * Set blast radius
   */
  public setBlastRadius(radius: number): void {
    this.effectRadius = radius;
  }

  /**
   * Pause tower operations (called during rewind)
   */
  public pauseTower(): void {
    this.isPaused = true;
    this.currentTarget = null; // Clear current target when paused
    console.debug("SplashTower paused for rewind");
  }

  /**
   * Resume tower operations (called when exiting rewind)
   */
  public resumeTower(): void {
    this.isPaused = false;
    console.debug("SplashTower resumed from rewind");
  }

  /**
   * Check if tower is currently paused
   */
  public isPaused_(): boolean {
    return this.isPaused;
  }

  /* END-USER-CODE */
}