mafia / frontend /src /ui /FloatingText.ts
Alfaxad's picture
Migrate Mafia game to ZeroGPU Gradio Space
c670567 verified
Raw
History Blame Contribute Delete
3.04 kB
/**
* ============================================================================
* 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;
}
}