/** * Bodenmarkierung für verzögerte Einschläge (Orbital-Befehle, Mörser). * * Die Markierung zeigt den tatsächlichen Wirkungsradius und füllt sich bis zum * Einschlag – so kann der Spieler Gefahr erkennen und ausweichen. * @module systems/GroundMarker */ import { GAME } from '../config.js'; import { UI } from '../ui/theme.js'; export class GroundMarker { /** * @param {Phaser.Scene} scene * @param {number} x * @param {number} y * @param {number} radius * @param {number} color * @param {number} startAt Spielzeit bei Erstellung. * @param {number} impactAt Spielzeit des Einschlags. * @param {{label?: string, beam?: boolean}} [options] */ constructor(scene, x, y, radius, color, startAt, impactAt, options = {}) { this.scene = scene; this.x = x; this.y = y; this.radius = radius; this.color = color; this.startAt = startAt; this.impactAt = impactAt; this.beam = options.beam ?? false; this.graphics = scene.add.graphics().setDepth(GAME.depth.markers); this.label = options.label ? scene.add .text(x, y, '', { fontFamily: UI.uiFont, fontStyle: 'bold', fontSize: '16px', color: '#f4ecd8', stroke: '#0d1321', strokeThickness: 4, }) .setOrigin(0.5) .setDepth(GAME.depth.markers + 1) : null; this.labelText = options.label ?? ''; } /** * Zeichnet den aktuellen Zustand. * @param {number} now */ update(now) { const total = Math.max(1, this.impactAt - this.startAt); const progress = Math.min(1, Math.max(0, (now - this.startAt) / total)); // Puls wird zum Einschlag hin schneller – intuitive Warnung ohne Text. const pulse = 0.5 + 0.5 * Math.sin(now / (120 - 80 * progress)); const g = this.graphics; g.clear(); g.fillStyle(this.color, 0.12 + 0.1 * pulse); g.fillCircle(this.x, this.y, this.radius); g.fillStyle(this.color, 0.35); g.fillCircle(this.x, this.y, this.radius * progress); g.lineStyle(3, this.color, 0.6 + 0.4 * pulse); g.strokeCircle(this.x, this.y, this.radius); if (this.beam) { g.lineStyle(2 + 6 * progress, this.color, 0.25 + 0.5 * progress); g.lineBetween(this.x, this.y - 900, this.x, this.y); } if (this.label) { const seconds = Math.max(0, (this.impactAt - now) / 1000).toFixed(1).replace('.', ','); this.label.setText(`${this.labelText} ${seconds}`); } } /** @param {number} now @returns {boolean} */ isDue(now) { return now >= this.impactAt; } destroy() { this.graphics.destroy(); this.label?.destroy(); } }