/**
* Хит-флэш: лерп цвета tint от исходного к «вспышке» и обратно.
* Чистая логика (без Pixi) — результат применимо к любому числовому свойству.
*/
export class TintFlash {
private elapsed: number | null = null;
/** tint на момент запуска (возвращается к нему по окончании). */
private base: number;
/**
* @param from исходный tint (например 0xffffff)
* @param to цвет вспышки
* @param seconds полная длительность (туда-обратно)
*/
constructor(
from: number,
private readonly to: number,
private readonly seconds: number
) {
this.base = from;
}
/** Запустить (перезапускается с нуля). */
start(): void {
this.elapsed = 0;
}
/**
* Обновить; возвращает текущий tint или null, если флэш не активен.
* При окончании возвращает исходный цвет.
*/
update(dt: number): number | null {
if (this.elapsed === null) return null;
this.elapsed += dt;
if (this.elapsed >= this.seconds) {
this.elapsed = null;
return this.base;
}
// треугольная волна: 0..1..0
const t = 1 - Math.abs(this.elapsed / this.seconds - 0.5) * 2;
return lerpColor(this.base, this.to, t);
}
get active(): boolean {
return this.elapsed !== null;
}
}
/** Лерп двух цветов 0xRRGGBB по каналам. */
export function lerpColor(a: number, b: number, t: number): number {
const ar = (a >> 16) & 0xff;
const ag = (a >> 8) & 0xff;
const ab = a & 0xff;
const br = (b >> 16) & 0xff;
const bg = (b >> 8) & 0xff;
const bb = b & 0xff;
const r = Math.round(ar + (br - ar) * t);
const g = Math.round(ag + (bg - ag) * t);
const bl = Math.round(ab + (bb - ab) * t);
return (r << 16) | (g << 8) | bl;
}