Advertisement

← tower-of-time-game

src/ui/WaveStartOverlay.ts

5.8 KB Download file
/**
 * Wave Start Overlay - Shows animated "WAVE n START!" text
 *
 * Features:
 * - Full-screen semi-transparent black background
 * - Large white centered text with wave information
 * - Smooth fade in/out animations
 * - Auto-dismisses after specified duration
 */

export default class WaveStartOverlay extends Phaser.GameObjects.Container {
  private background: Phaser.GameObjects.Rectangle;
  private waveText: Phaser.GameObjects.Text;
  private isVisible: boolean = false;
  private displayDuration: number = 2000; // 2 seconds
  private fadeInDuration: number = 300; // 0.3 seconds
  private fadeOutDuration: number = 300; // 0.3 seconds

  constructor(scene: Phaser.Scene) {
    super(scene, 0, 0);

    // Create semi-transparent black background
    this.background = scene.add.rectangle(
      0,
      480 / 2 - 50,
      scene.scale.width,
      100,
      0x000000,
      0.5
    );
    this.background.setOrigin(0, 0);

    // Create wave text
    this.waveText = scene.add.text(
      scene.scale.width / 2,
      scene.scale.height / 2,
      "",
      {
        fontSize: "64px",
        fontFamily: "Arial, sans-serif",
        color: "#ffffff",
        stroke: "#000000",
        strokeThickness: 4,
        align: "center",
        fontStyle: "bold",
      }
    );
    this.waveText.setOrigin(0.5, 0.5);

    // Add to container
    this.add([this.background, this.waveText]);

    // Set high depth to appear above everything
    this.setDepth(1000);

    // Initially hidden
    this.setVisible(false);
    this.setAlpha(0);

    console.log("WaveStartOverlay created");
  }

  /**
   * Show the wave start overlay with animation
   * @param waveNumber The wave number to display
   * @param waveName Optional wave name
   * @param totalWaves Total number of waves (to determine if this is the final wave)
   */
  public showWave(
    waveNumber: number,
    waveName?: string,
    totalWaves?: number
  ): void {
    console.log(
      `WaveStartOverlay.showWave called: Wave ${waveNumber}${
        waveName ? ` (${waveName})` : ""
      }${totalWaves ? ` (${waveNumber}/${totalWaves})` : ""}`
    );

    if (this.isVisible) {
      // If already showing, hide first then show new wave
      console.log("Overlay already visible, hiding first");
      this.hide(() => this.showWave(waveNumber, waveName, totalWaves));
      return;
    }

    // Update text - show "FINAL WAVE" for the last wave
    let displayText: string;
    if (totalWaves && waveNumber === totalWaves) {
      displayText = "FINAL WAVE!";
    } else {
      displayText = `WAVE ${waveNumber} START!`;
    }
    // if (waveName) {
    //   displayText += `\n${waveName}`;
    // }
    this.waveText.setText(displayText);

    console.log(`Showing wave start overlay with text: "${displayText}"`);

    // Center text
    this.waveText.setPosition(
      this.scene.scale.width / 2,
      this.scene.scale.height / 2
    );

    this.isVisible = true;
    this.setVisible(true);

    // Fade in animation
    this.scene.tweens.add({
      targets: this,
      alpha: 1,
      duration: this.fadeInDuration,
      ease: "Power2",
      onComplete: () => {
        // Wait for display duration, then fade out
        this.scene.time.delayedCall(this.displayDuration, () => {
          this.hide();
        });
      },
    });

    // Scale animation for text
    this.waveText.setScale(0.8);
    this.scene.tweens.add({
      targets: this.waveText,
      scaleX: 1,
      scaleY: 1,
      duration: this.fadeInDuration,
      ease: "Back.easeOut",
    });

    console.log(`Showing wave start overlay: ${displayText}`);
  }

  /**
   * Hide the overlay with animation
   * @param onComplete Optional callback when hide animation completes
   */
  public hide(onComplete?: () => void): void {
    if (!this.isVisible) {
      if (onComplete) onComplete();
      return;
    }

    this.isVisible = false;

    // Fade out animation
    this.scene.tweens.add({
      targets: this,
      alpha: 0,
      duration: this.fadeOutDuration,
      ease: "Power2",
      onComplete: () => {
        this.setVisible(false);
        if (onComplete) onComplete();
      },
    });

    // Scale down text
    this.scene.tweens.add({
      targets: this.waveText,
      scaleX: 0.8,
      scaleY: 0.8,
      duration: this.fadeOutDuration,
      ease: "Power2",
    });
  }

  /**
   * Set the display duration for the overlay
   * @param duration Duration in milliseconds
   */
  public setDisplayDuration(duration: number): void {
    this.displayDuration = duration;
  }

  /**
   * Set the fade animation durations
   * @param fadeIn Fade in duration in milliseconds
   * @param fadeOut Fade out duration in milliseconds
   */
  public setFadeDurations(fadeIn: number, fadeOut: number): void {
    this.fadeInDuration = fadeIn;
    this.fadeOutDuration = fadeOut;
  }

  /**
   * Check if the overlay is currently visible
   */
  public isShowing(): boolean {
    return this.isVisible;
  }

  /**
   * Force hide immediately without animation
   */
  public forceHide(): void {
    this.isVisible = false;
    this.setVisible(false);
    this.setAlpha(0);

    // Stop any running tweens
    this.scene.tweens.killTweensOf(this);
    this.scene.tweens.killTweensOf(this.waveText);
  }

  /**
   * Update overlay size when screen size changes
   */
  public updateSize(): void {
    this.background.setSize(this.scene.scale.width, this.scene.scale.height);
    this.waveText.setPosition(
      this.scene.scale.width / 2,
      this.scene.scale.height / 2
    );
  }

  /**
   * Clean up when destroying
   */
  public destroy(fromScene?: boolean): void {
    // Stop any running tweens
    this.scene?.tweens.killTweensOf(this);
    this.scene?.tweens.killTweensOf(this.waveText);

    super.destroy(fromScene);
  }
}