Spaces:
Running on Zero
Running on Zero
| /** | |
| * ============================================================================ | |
| * FLOATING TEXT - Animated popup text (damage numbers, score, etc.) | |
| * ============================================================================ | |
| * | |
| * This is a STATIC utility class. It is NOT instantiated with `new`. | |
| * | |
| * Creates text that floats upward and fades out. Used for: | |
| * - Damage numbers ("25 DMG") | |
| * - Score popups ("+100") | |
| * - Status effects ("SHIELDED!", "MISS!") | |
| * - Combo indicators ("x1.5 COMBO!") | |
| * | |
| * Auto-destroys after animation completes. | |
| * | |
| * CORRECT USAGE: | |
| * // From a scene (static method): | |
| * FloatingText.show(scene, 400, 300, '-25', { color: '#ff0000' }); | |
| * | |
| * // From a BaseBattleScene subclass (inherited helper): | |
| * this.showFloatingText('-25', 400, 300, { color: '#ff0000' }); | |
| * | |
| * !! WRONG - WILL CAUSE RUNTIME ERROR !! | |
| * new FloatingText(scene, ...) // NOT a constructor! | |
| * new FloatingText(...) // NOT a constructor! | |
| */ | |
| import Phaser from 'phaser'; | |
| export interface FloatingTextConfig { | |
| /** Text color (CSS format, default: '#ffffff') */ | |
| color?: string; | |
| /** Font size (CSS format, default: '24px') */ | |
| fontSize?: string; | |
| /** Font family (default: 'Arial') */ | |
| fontFamily?: string; | |
| /** Bold text (default: true) */ | |
| bold?: boolean; | |
| /** Stroke color (default: '#000000') */ | |
| strokeColor?: string; | |
| /** Stroke width (default: 4) */ | |
| strokeWidth?: number; | |
| /** Float distance in pixels (default: 60) */ | |
| floatDistance?: number; | |
| /** Animation duration in ms (default: 1000) */ | |
| duration?: number; | |
| /** Start with a scale bounce (default: false) */ | |
| bounce?: boolean; | |
| /** Horizontal drift (pixels, default: 0) */ | |
| driftX?: number; | |
| } | |
| export class FloatingText { | |
| /** | |
| * Create and animate a floating text. | |
| * Static factory method -- auto-destroys on completion. | |
| */ | |
| static show( | |
| scene: Phaser.Scene, | |
| x: number, | |
| y: number, | |
| text: string, | |
| config?: FloatingTextConfig, | |
| ): Phaser.GameObjects.Text { | |
| const c = config ?? {}; | |
| const textObj = scene.add | |
| .text(x, y, text, { | |
| fontSize: c.fontSize ?? '24px', | |
| fontFamily: c.fontFamily ?? 'Arial', | |
| color: c.color ?? '#ffffff', | |
| fontStyle: c.bold !== false ? 'bold' : '', | |
| stroke: c.strokeColor ?? '#000000', | |
| strokeThickness: c.strokeWidth ?? 4, | |
| }) | |
| .setOrigin(0.5) | |
| .setDepth(999); | |
| const duration = c.duration ?? 1000; | |
| const floatDist = c.floatDistance ?? 60; | |
| // Optional bounce | |
| if (c.bounce) { | |
| textObj.setScale(0.5); | |
| scene.tweens.add({ | |
| targets: textObj, | |
| scaleX: 1.2, | |
| scaleY: 1.2, | |
| duration: 100, | |
| yoyo: true, | |
| onComplete: () => textObj.setScale(1), | |
| }); | |
| } | |
| // Float up + fade out | |
| scene.tweens.add({ | |
| targets: textObj, | |
| y: y - floatDist, | |
| x: x + (c.driftX ?? 0), | |
| alpha: 0, | |
| duration: duration, | |
| ease: 'Cubic.easeOut', | |
| onComplete: () => textObj.destroy(), | |
| }); | |
| return textObj; | |
| } | |
| } | |